XMLReader для чтения следующему брату неизвестного типа - PullRequest
0 голосов
/ 08 мая 2018

Я понимаю, как мы можем использовать пример кода, подобный следующему ..

public class Sample
{
    public static void Main()
    {
        using (XmlReader reader = XmlReader.Create("books.xml"))
        {
            reader.ReadToFollowing("book");
            do
            {
                Console.WriteLine("Name ", reader.GetAttribute("Name"));
            } while (reader.ReadToNextSibling("book"));
        }
    }
}

, и это будет читать каждый брат типа "книга". Таким образом, в структуре XML, как эта ниже, это будет прекрасно работать ..

<Section>
       <book Name="Titan Quest 1"/>
       <book Name="Titan Quest 2"/>
       <book Name="Adventure Willy"/>
       <book Name="Mr. G and the Sandman"/>
       <book Name="Terry and Me"/>
</Section>

Но допустим, что ваши братья и сестры не всегда имеют тип книги. Внутри раздела у нас могут быть book, cd, dvd или vhs, поэтому xml может выглядеть примерно так

<Section>
       <cd Name="Titan Quest 1"/>
       <book Name="Titan Quest 2"/>
       <vhs Name="Adventure Willy"/>
       <cd Name="Mr. G and the Sandman"/>
       <dvd Name="Terry and Me"/>
</Section>

Я хочу написать метод, который даст мне атрибут Name независимо от того, какой это тип брата. Используя приведенный выше код, я получу только [Titan Quest 2]. Можно ли это сделать? Спасибо!

Ответы [ 2 ]

0 голосов
/ 08 мая 2018

Используя этот код с XDocument , вы получите все значения из атрибутов:

 var document = XDocument.Load("test.xml");

 var bookValues = document.XPathSelectElement("Section")
       .Descendants()
       .Select(x => x.Attribute("Name").Value);

Или используя XmlReader для получения всех значений атрибута:

List<String> values = new List<string>();
using (var xmlreader = XmlReader.Create("test.xml"))
{
    xmlreader.ReadToDescendant("Section");
    while (xmlreader.Read())
    {
        if (xmlreader.IsStartElement())
        {
            values.Add(xmlreader.GetAttribute("Name"));
        }
    }
}
0 голосов
/ 08 мая 2018

Попробуйте следующий код. Будет работать с обоими типами книг. Я использовал комбинацию xmlreader и XElement:

Вот мой xml

<test>
   <Section>
       <book Name="Titan Quest 1"/>
       <book Name="Titan Quest 2"/>
       <book Name="Adventure Willy"/>
       <book Name="Mr. G and the Sandman"/>
       <book Name="Terry and Me"/>
   </Section>
   <Section>
       <cd Name="Titan Quest 1"/>
       <book Name="Titan Quest 2"/>
       <vhs Name="Adventure Willy"/>
       <cd Name="Mr. G and the Sandman"/>
       <dvd Name="Terry and Me"/>
   </Section>
</test>

Вот код

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            List<List<KeyValuePair<string, string>>> books = new List<List<KeyValuePair<string, string>>>();

            using (XmlReader reader = XmlReader.Create(FILENAME))
            {
                while (!reader.EOF)
                {
                    if (reader.Name != "Section")
                    {
                        reader.ReadToFollowing("Section");
                    }
                    if (!reader.EOF)
                    {
                        XElement section = (XElement)XElement.ReadFrom(reader);
                        List<KeyValuePair<string, string>> book = new List<KeyValuePair<string, string>>();
                        books.Add(book);
                        foreach (XElement b in section.Elements())
                        {
                            book.Add(new KeyValuePair<string, string>(b.Name.LocalName, (string)b.Attribute("Name")));
                        }
                    }
                }
            }

        }
    }
}

Вот результаты

enter image description here

...