Линк в XML Обход документов - PullRequest
2 голосов
/ 26 апреля 2010

У меня есть XML-документ, подобный этому:

<?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> 

Как настроить запросы LINQ для выполнения таких действий, как: 1. Получить все страны 2. Получить все государства в стране 3. Получить все города в государстве определенной страны?

Я попробовал, и я немного растерялся, когда использовал Elements ["NodeName"], Descendants и т. Д. Я знаю, что я не самый умный парень в XML. Является ли формат файла XML правильным даже для простого обхода?

Ответы [ 3 ]

4 голосов
/ 26 апреля 2010

Чтобы загрузить документ из файла:

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

Чтобы получить названия всех стран:

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

Чтобы получить все штаты, которые находятся внутри страны "США":

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

Чтобы получить все города в США / Калифорнии:

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);

Вы также можете посмотреть запросы XPath (вам нужно using System.XML.XPath):

IEnumerable<string> cities = document
    .XPathSelectElements("/demographics/country[@value='USA']/state[@value='California']/city")
    .Select(element => element.Value);
1 голос
/ 26 апреля 2010
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);

Результат будет иметь countries, states и cities типа IEnumerable<string>.

Также стоит отметить, что выполнение (то есть разбор) будет отложено до тех пор, пока вы фактически не перечислите значения в этих IEnumerable<string> переменных. Иногда это может вызвать непредвиденные проблемы с производительностью. Например, если вы все равно планируете отображать все данные и привязываете их к какому-либо элементу управления пользовательского интерфейса, пользовательский интерфейс может стать вялым, поскольку понимает, что ему все-таки нужно проанализировать это. (Он может даже заблокировать поток пользовательского интерфейса вместо вашего рабочего потока? Не уверен.) Чтобы исправить это, добавьте .ToList() в конец, чтобы получить неотложенные List<string> s вместо.

1 голос
/ 26 апреля 2010

Как это:

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