开发者

Linq to XML Document Traversal

I have an xml document like this:

<?xml version="1.0" encoding="utf-8" ?>
<demographics>
    <country id="1" value="USA">
        <state id ="1" value="California">
            <city>Long Beach</city>
            <city>Los Angeles</city>
            <city>San Diego</city>
        </state>
        <state id ="2" value="Arizona">
            <city>Tucson</city>
            <city>Phoenix</city>
            <city>Tempe</city>
        </state>
    </country>
    <country id="2" value="Mexico">
        <state id ="1" value="Baja California">
            <city>Tijuana</city>
            <city>Rosarito</city>            
        </state>
    </country>
</demographics> 

How do I setup LINQ queries for doing things like: 1. Get All Countries 2. Get All States in a Country 3. Get All Cities inside a state of a paricular country ?

I gave it a try and I am kind of conf开发者_开发问答used when to use Elements["NodeName"] and Descendants etc. I know I am not the brightest XML guy around. Is the format of the XML file even correct for simple traversal?


To load the document from a file:

XDocument document = XDocument.Load("input.xml");

To get all the countries' names:

IEnumerable<string> countries = document
    .Descendants("country")
    .Select(element => element.Attribute("value").Value);

To get all the states that are inside the country "USA":

IEnumerable<string> states = document
    .Descendants("country")
    .Where(element => element.Attribute("value").Value == "USA")
    .Elements("state")
    .Select(element => element.Attribute("value").Value);

To get all the cities inside USA/California:

IEnumerable<string> cities = document
    .Descendants("country")
    .Where(element => element.Attribute("value").Value == "USA")
    .Elements("state")
    .Where(element => element.Attribute("value").Value == "California")
    .Elements("city")
    .Select(element => element.Value);

You might also want to look at XPath queries (you need using System.XML.XPath):

IEnumerable<string> cities = document
    .XPathSelectElements("/demographics/country[@value='USA']/state[@value='California']/city")
    .Select(element => element.Value);


Like this:

var countries = document.Root.Elements("country");
var states    = country.Elements("state");
var cities    = state.Elements("city");


var doc = XDocument.Load("myxml.xml");


var countries = doc.Descendants("country")
                   .Attributes("value")
                   .Select(a => a.Value);

var states    = doc.Descendants("country")
                   .Single(country => country.Attribute("value").Value == "USA")
                   .Elements("state")
                   .Attributes("value")
                   .Select(a => a.Value);

var cities    = doc.Descendants("state")
                   .Single(state => state.Attribute("value").Value == "California")
                   .Elements("city")
                   .Select(e => e.Value);

The result will have countries, states, and cities as type IEnumerable<string>.

Also worth noting that execution (i.e. parsing) will be delayed until you actually enumerate the values in those IEnumerable<string> variables. This can sometimes cause unintended performance issues. For example, if you're planning to display all the data anyway, and you databind it to some UI control, the user interface can get sluggish as it realizes that it does need to parse this after all. (It might even block the UI thread, instead of your worker thread? Not sure.) To fix this, add .ToList() to the end, to get non-deferred List<string>s instead.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜