Разбор XML с Linq - PullRequest
       52

Разбор XML с Linq

0 голосов
/ 21 января 2011

У меня есть следующий XML-документ, который я хотел бы проанализировать в DataSet.

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> 
<Response Status="OK">
  <Item>
    <Field Name="ID">767147519</Field> 
    <Field Name="Name">Music</Field> 
    <Field Name="Path">Family\Music</Field> 
    <Field Name="Type">Playlist</Field> 
  </Item>
</Response>

Я хочу получить значения атрибутов для идентификатора, имени и пути.

Вот что я пытался сделать:

Dim loaded As XDocument = XDocument.Load(uriString)
Dim name = From c In loaded.Descendants("Item") Select c
For Each result In name
  Dim str1 = result.Attribute("ID").Value 'Returns Nothing and causes a validation error
  Dim str2 = result.Value ' Returns all the attribute values in one long string (ie "767147519MusicFamilyPlaylist")
Next

Любая помощь будет принята с благодарностью.

Спасибо

Мэтт

EDIT:

Следуя одному из приведенных ниже ответов, я пытался реализовать анонимный тип в моем Linq, однако я продолжаю сталкиваться с ошибкой

Ссылка на объект не установлена ​​на экземпляр объекта.

Мой обновленный код выглядит следующим образом:

Dim name = From c In loaded.Descendants("Item") Select c Select sID = c.Element("Field").Attribute("Name").Value, sName = c.Attribute("ID").Value.FirstOrDefault
Dim Id As String = String.Empty
For Each result In name
  Id = result.sID
Next

Я думаю, что эта ошибка означает, что атрибут ("ID") не может быть найден, поэтому я попытался несколько вариантов этого с похожими результатами.

Может ли кто-нибудь определить, куда я иду, и указать мне правильное направление.

Спасибо

Мэтт

Ответы [ 12 ]

0 голосов
/ 21 января 2011

Ваш запрос linq возвращает все элементы Item в документе:

Dim name = From c In loaded.Descendants("Item") Select c

Следующий код пытается получить атрибут 'ID' из элемента 'Item':

Dim str1 = result.Attribute("ID").Value

Однако атрибут 'ID' находится в дочернем элементе 'Field'.

Вам необходимо следующее:

// find all the Item elements
var items = loaded.Descendants("Item");
foreach(var item in items)
{
  // find all the Field child elements
  var fields = item.Descendants("Field");

  // find the field element which has an ID attribute, and obtain the element value  
  string id = fields.Where(field => field.Attribute("ID")!=null)
                    .Single()
                    .Value;

  // etc ...
}
0 голосов
/ 21 января 2011

Я хочу получить значения атрибутов для идентификатора, имени и пути.

Если вы не возражаете против использования чего-то другого, кроме XDocument, я бы просто использовал XmlDocument:

        XmlDocument doc = new XmlDocument();
        doc.Load(new XmlTextReader("XData.xml"));
        XmlNodeList items = doc.GetElementsByTagName("Item");
        foreach (XmlElement item in items.Cast<XmlElement>())
        {
            XmlElement[] fields = item.GetElementsByTagName("Field").Cast<XmlElement>().ToArray();
            string id = (from s in fields where s.Attributes["Name"].InnerText == "ID" select s).First().InnerText;
            string name = (from s in fields where s.Attributes["Name"].InnerText == "Name" select s).First().InnerText;
            string path = (from s in fields where s.Attributes["Name"].InnerText == "Path" select s).First().InnerText;

            //Do stuff with data.
        }

С точки зрения производительности это может быть ужасно.Вы также можете создать цикл для полей, а затем использовать переключатель на атрибуте имени, чтобы не проверять одно и то же поле более одного раза.Зачем вам вообще нужен linq для этого?


        XmlDocument doc = new XmlDocument();
        doc.Load(new XmlTextReader("XData.xml"));
        XmlNodeList items = doc.GetElementsByTagName("Item");
        foreach (XmlElement item in items.Cast<XmlElement>())
        {
            foreach (XmlNode field in item.GetElementsByTagName("Field"))
            {
                string name = field.Attributes["Name"].InnerText;
                switch (name)
                {
                    case "ID":
                        string id = field.InnerText;
                        //Do stuff with data.
                        break;
                    case "Path":
                        string path = field.InnerText;
                        //Do stuff with data.
                        break;
                    case "Name":
                        string name = field.InnerText;
                        //Do stuff with data.
                        break;
                    default:
                        break;
                }
            }
        }
...