I'm trying to read the xml from a soap response. It is given below
`<OTA_AirLowFareSearchRS xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Version="1.9.2" PricedItinCount="1" BrandedOneWayItinCount="0" SimpleOneWayItinCount="0" DepartedItinCount="0" SoldOutItinCount="0" AvailableItinCount="0">
<Success xmlns="http://www.opentravel.org/OTA/2003/05"/>
<Warnings xmlns="http://www.opentravel.org/OTA/2003/05">...</Warnings>
<PricedItineraries xmlns="http://www.opentravel.org/OTA/2003/05">
<PricedItinerary SequenceNumber="1">
<AirItinerary DirectionInd="OneWay">
<OriginDestinationOptions>
<OriginDestinationOption ElapsedTime="1920">
<FlightSegment DepartureDateTime="2017-03-21T21:45:00" ArrivalDateTime="2017-03-22T09:50:00" StopQuantity="0" FlightNumber="7336" ResBookDesigCode="T" ElapsedTime="425">
<DepartureAirport LocationCode="CDL" TerminalID="1"/>
<ArrivalAirport LocationCode="CDA" TerminalID="1A"/>
<OperatingAirline Code="AA" FlightNumber="810"/>
<Equipment AirEquipType="000"/>
<MarketingAirline Code="PP"/>
<DisclosureAirline Code="AC"/>
<MarriageGrp>O</MarriageGrp>
<DepartureTimeZone GMTOffset="-10"/>
<ArrivalTimeZone GMTOffset="11"/>
<TPA_Extensions>
<eTicket Ind="true"/>
</TPA_Extensions>
</FlightSegment>
</OriginDestinationOption>
</OriginDestinationOptions>
</AirItinerary>
</PricedItinerary>
</PricedItineraries>
</OTA_AirLowFareSearchRS>`
I've tried a lot of stuff with LINQ to XML, but nothing seems to work.
Here's a sample i've tried using
var xml = XDocument.Parse(stringXMLResponse);
var result = from item in xml.Descendants("FlightSegment")
select new
{
v1 = item.FirstAttribute.Value
};
Any suggestions would be encouraged. Thank you.
You can write your LINQ query like this. You may need to tweak it your requirement but it works with your XML string.
var selected = from x in xdoc.Descendants()
where x.NodeType == XmlNodeType.Element
&& x.Name.LocalName == "FlightSegment"
select x;
Here is fiddler : https://dotnetfiddle.net/NxkT38
Related
I would like to get datas from a specific XML format. The XML document looks like that:
<MyXML>
<Sources>
<S1>www.example1.org</S1>
<S2>www.example2.org</S2>
</Sources>
<Books>
<Book id="1">
<Datas>
<Data name="Book_1_Name" tag="1111" />
<Data name="Book_2_Name" tag="2222" />
</Datas>
</Book >
<Book id="2">
<Datas>
<Data name="Book_1_Name" tag="3333" />
<Data name="Book_2_Name" tag="4444" />
</Datas>
</Book >
</Books>
My question is:
How can I get www.example1.org if I know S1?
How can I search "Book_1_name" from Book id=1?
I am using C# with XDocument like this:
XDocument.Load(_XML_path);
var node = _configXml.XPathSelectElement("MyXML/Books/Datas");
You can use XPath, About XPath see this : http://www.xfront.com/xpath/
var _configXml = XDocument.Load(_XML_path);
//how to get S1 element.
var s1 = _configXml.XPathSelectElement("MyXML/Sources/S1");
//how search
var search = _configXml.XPathSelectElements("//Book[#id='1']//Data[#name='Book_1_Name']");
Console.WriteLine(s1.Value);
Console.WriteLine(search.First().Attribute("tag").Value);
You should map the XML to a C# object. Then, you can use the following to get what you want:
XmlSerializer serializer = new XmlSerializer(typeof(MyXML));
var xml = (MyXML)serializer.Deserialize(new StringReader(XDocument.Load(_XML_path)));
var s1 = xml.Sources.S1;
If you want to stick with a XDocument, you can do the following
var books = doc.Element("MyXML").Element("Books");
var bookById = books.Elements("Book")
.Where(b => b.Attribute("id").Value == "1")
.Select(b => b.Element("Datas"));
In the first line, you are selecting the Books node (please note, in a real-world scenario, I'd add some checks here). In the following line you are first getting all Book sub-elements (books.Elements("Book")), checking them for the ID you are searching for (Where(b => b.Attribute("id").Value == "1")) and then select the data node from the respective book. You could re-write this to query syntax
var bookById = from book in books.Elements("Book")
let id = book.Attribute("id")
let datas = book.Element("Datas")
where id != null
&& datas != null
&& id.Value == "1"
select datas;
which is a bit longer, but easier to read.
Basically, I am having trouble trying to understand where I am going wrong in here..
Basically, I have the following XML:
<Directory>
<CustDirectory name="Name1">
<Person name="Foo" />
<Person name="Goo" />
<Person name="Gentu" />
</CustDirectory>
<CustDirectory name="Name2">
<Person name="F22" />
<Person name="Gentu" />
</CustDirectory>
</Directory>
Using forms, I am updating a list of contacts and I want to write the list to XML depending on which category (stored as a string).
What I have decided to use is therefore LINQ to do it, but, I can't seem to figure out there .Where and have read through questions on stackoverflow and can't seem to figure it out.
Here is my attempt:
var con = e.Element("Directory").Element("CustDirectory").Descendants("Person").Where(p => p.Attribute("name").Value.ToStr == "Name2");
This does not work and throws up a null exception... When I take off the .Where clause, the data contained in the descendent shows correctly.
Could anyone please tell me where I am going wrong in terms of the LINQ query so I can select all the descendants of a particular root?
If I understood correctly your question you are trying to extract all the Person elements that belongs to a given CustDirectory. In this case you should use something more like:
var con = e.Element("Directory").Descendants("CustDirectory").Where(p => p.Attribute("name").Value == "Name2").Elements("Person");
Everything looks right except for the ToStr part.
To select only the Person elements under the CustDirectory with the name Name2 you will need to put your Where on that, like this:
var con = e.Element("Directory").Elements("CustDirectory")
.First(cd => cd.Attribute("name").Value == "Name2").Descendants("Person");
Note that I changed Element("CustDirectory") to Elements("CustDirectory").
You don't need Element("Directory") at the beginning, because e it self is already referenced <Directory> (different case if e is an XDocument instead of XElement as you said in comment). This example able to return <Person> nodes give sample XML posted in question :
var e = XElement.Parse("...");
var con = e.Elements("CustDirectory")
.Where(p => p.Attribute("name").Value == "Name2")
.Elements("Person");
void Main()
{
var xml = #"<Directory>
<CustDirectory name=""Name1"">
<Person name=""Foo""/>
<Person name=""Goo""/>
<Person name=""Gentu""/>
</CustDirectory>
<CustDirectory name=""Name2"">
<Person name=""F22""/>
<Person name=""Gentu""/>
</CustDirectory>
</Directory>";
var xmlDoc = XDocument.Parse(xml);
var con = xmlDoc.Element("Directory")
.Elements("CustDirectory")
.Where(p => p.Attribute("name").Value == "Name2")
.Descendants("Person")
// added bonus to get a specific node
.Where(p => p.Attribute("name").Value == "F22");
Console.WriteLine(con);
}
I have a source xml:
<Source>
<First>
<Name>Name1</Name>
</First>
<First>
<Name>Name2</Name>
</First>
</Source>
I have an empty target xml, where I want to copy data from the source xml.
Empty target xml is:
<Target>
<Second>
<FirstName></FirstName>
</Second>
<Second>
<FirstName></FirstName>
</Second>
</Target>
After copy the target xml will look:
<Target>
<Second>
<FirstName>Name1</FirstName>
</Second>
<Second>
<FirstName>Name2</FirstName>
</Second>
</Target>
I'm looking for an easy linq to xml solution. The problem is, that I don't know how to update repetitive elements in target xml based on repetitive elements from source xml.
thanks.
You can do that using the following code:
var source = "<Source><First><Name>Name1</Name></First><First><Name>Name2</Name></First></Source>";
var sourceDocument = XDocument.Load(new StringReader(source));
var target = "<Target><Second><FirstName></FirstName></Second><Second><FirstName></FirstName></Second></Target>";
var targetDocument = XDocument.Load(new StringReader(target));
var sourceNameElements = sourceDocument.Descendants("First").Select(first => first.Element("Name")).ToList();
var targetNamesElements = targetDocument.Descendants("Second").Select(second => second.Element("FirstName")).ToList();
for (var i = 0; i < sourceNameElements.Count; ++i)
{
targetNamesElements[i].SetValue(sourceNameElements[i].Value);
}
Console.WriteLine(targetDocument.ToString());
I don't know the easiest way to solve this ,this is best way I can think out,and you must ensure Name.count is larger than FirstName.count:
var sourceXml =XElement.Parse(source);
var targetXml = XElement.Parse(target);
var i = 0;
var nameArray = (from name in sourceXml.Descendants("Name")
select name.Value).ToArray();
foreach (var fName in targetXml.Descendants("FirstName"))
{
fName.Value = nameArray[i++];
}
Below is my response generated from a webservice.
I want to do such that I want only PresentationElements node from this response.
Any help how can I achieve this query?
<?xml version="1.0"?>
<GetContentResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ExtensionData />
<GetContentResult>
<ExtensionData />
<Code>0</Code>
<Value>Success</Value>
</GetContentResult>
<PresentationElements>
<PresentationElement>
<ExtensionData />
<ContentReference>Product View Pack</ContentReference>
<ID>SHOPPING_ELEMENT:10400044</ID>
<Name>View Pack PE</Name>
<PresentationContents>
<PresentationContent>
<ExtensionData />
<Content>View Pack</Content>
<ContentType>TEXT</ContentType>
<Language>ENGLISH</Language>
<Medium>COMPUTER_BROWSER</Medium>
<Name>Name</Name>
</PresentationContent>
<PresentationContent>
<ExtensionData />
<Content>Have more control of your home's security and lighting with View Pack from XFINITY Home.</Content>
<ContentType>TEXT</ContentType>
<Language>ENGLISH</Language>
<Medium>COMPUTER_BROWSER</Medium>
<Name>Description</Name>
</PresentationContent>
<PresentationContent>
<ExtensionData />
<Content>/images/shopping/devices/xh/view-pack-2.jpg</Content>
<ContentType>TEXT</ContentType>
<Language>ENGLISH</Language>
<Medium>COMPUTER_BROWSER</Medium>
<Name>Image</Name>
</PresentationContent>
<PresentationContent>
<ExtensionData />
<Content>The View Pack includes:
2 Lighting / Appliance Controllers
2 Indoor / Outdoor Cameras</Content>
<ContentType>TEXT</ContentType>
<Language>ENGLISH</Language>
<Medium>COMPUTER_BROWSER</Medium>
<Name>Feature1</Name>
</PresentationContent>
</PresentationContents>
</PresentationElement>
</PresentationElements>
</GetContentResponse>
You can use XPath extensions
var xdoc = XDocument.Parse(response);
XElement presentations = xdoc.XPathSelectElement("//PresentationElements");
You may use the System.Xml.Linq.XDocument:
//Initialize the XDocument
XDocument doc = XDocument.Parse(yourString);
//your query
var desiredNodes = doc.Descendants("PresentationElements");
Pretty easy, have you tried:
XDocument xml = XDocument.Load("... xml");
var nodes = (from n in xml.Descendants("PresentationElements")
select n).ToList();
You could also project each individual node to an anonymous type using something like:
select new
{
ContentReference = (string)n.Element("ContentReference").Value,
.... etc
}
<World>
<Animals>
<Tab>
<Dogs id ="1">
<Dog1></Dog1>
<Dog2></Dog2>
<Dog3></Dog3>
</Dogs>
<Dogs id ="2"></Dogs>
<Dogs id ="3"></Dogs>
</Tab>
</Animals>
</World>
How do I get all elements under tag where id == 1?
My Linq query. (doesn't work) why?
XDocument xml= XDocument.Load(xml.xml);
var elements = from e in xml.Descendants("Animals").Descendants("Tab").Elements("Dogs")
where e.Attribute("id").toString().Equals("1")
select c;
Could you check it please?
Thanks!
var result = xdoc.Descendants("World")
.Descendants("Animals")
.Descendants("Tab")
.Elements("Dogs")
.Where(n => n.Attribute("id").Value == "1");
Output:
<Dogs id="1">
<Dog1></Dog1>
<Dog2></Dog2>
<Dog3></Dog3>
</Dogs>
Or use XPath:
xml.XPathSelectElements("/World/Animals/Tab/Dogs[#id=1]")
or
xml.XPathSelectElements("//Dogs[#id=1]")
which would find all Dogs wherever they occurred.
From your sample data I think you want
//from e in xml.Descendants("Animals").Descendants("Tab").Elements("Dogs")
from e in xml.Descendants("Animals").Elements("Tab").Descendants("Dogs")
And in the same line, Descendants("Animals") could be Elements("Animals") if you want to enforce the structure.
For the rest your query looks OK.