简体   繁体   中英

Parsing XML stream using LINQ

I found a lot of examples and questions on this topic but what ever I try the result is blank.

From the xml I need to get out the first 'listing' element from there I need just the DisplayName and Address info.

样本图片

var listings = from c in xdoc.Elements("listing") select c;

You are missing the namespace in your query. The name of the node is not listing it is namespace + listing

So you need to get the namespace of the wp element or use the local name property:

var listings  = from c in xdoc.Descendants()
                where c.Name.LocalName == "listing"
                select c;

or you need to get the namespace and add it to the query

XNamespace ns = // namespace name here
var listings  = from c in xdoc.Descendants(ns + "listing") select c;

listing will be defined as some variation of IEnumerable<XElement> . The exact type will vary depending on which query you used, but the important part is it will derive from IEnumerable<> .

The other problem is your use of the Elements() method. Elements() will only search the children of node defined by xdoc . Descendants() will also look in the child of the children and all other child nodes.


UPDATE 1 - Added more details on getting specific nodes from XML

Getting the address and displayname is basically the same process, in fact you can just add it to the original query or use a different query (it all depends on how you want to use it later - will you ever need the other elements of wp:listing or just the displayname and address ?

If you might need others, then it seems logical to do it as a different query so you can query your result later. Readability also comes into play as nesting multiple queries inside of each other can make it difficult to read in my opinion.

Getting Address is the hardest part. You need to decide how you want it... do you want a XElement with all of the address parts as child nodes? Or do you want to construct a new object? Or do you just need a concatenated string?

But the general query would be something like this:

var result = from listing in listings
             select new
             {
                 Name = listing.Element(ns + "displayname").Value,
                 Address = listing.Element(ns + "address")
             };

This would give you an IEnumerable<'a'> with a defined as an anonymous type consisting of a Name property (as a String) and an Address property (as an XElement). If you want something else, you have to replace Address = listing.Element(ns + "address") with appropriate line(s) of code.

If you just need another anonymous type, then you need to put a nested query in that line:

Address = from part in listing.Elements(ns + "address")
          select new
          {
              FullStreet = part.Element(ns + "fullstreet").Value,
              HouseNumber = part.Element(ns + "house").Value,
              Street = part.Element(ns + "street").Value,
              StreetType = part.Element(ns + "streettype").Value,
              // continue for all Elements you need/want
          };

Or you could just create an Address class and call the constructor or a factory method in the query and pass the XElement or the address parts.

尝试使用Descendants代替Elements

 var listings = from c in xdoc.Descendants("listing") select c;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM