Как обратиться к дочерним узлам из объекта XmlNode? - PullRequest
0 голосов
/ 22 июня 2019

Это мой тестовый XML-документ:

<?xml version="1.0" encoding="utf-8" ?>
<foos>
  <foo>
    <bar>
      <bazs>
        <baz>baz1</baz>
        <baz>baz2</baz>
        <baz>baz3</baz>
      </bazs>
    </bar>
  </foo>
  <!--there will be other foo nodes with same structure but different number of baz nodes-->
</foos>

В этом документе каждый узел <foo> имеет один узел <bar>, а каждый узел <bar> имеет список <baz> узлов.Я хочу достичь этих <baz> узлов от каждого <bar>.Это мой код:

using System;
using System.Xml;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            XmlDocument xmlDocument = new XmlDocument();
            xmlDocument.Load("test.xml");
            XmlNodeList fooNodes = xmlDocument.SelectNodes("/foos/foo");
            foreach(XmlNode fooNode in fooNodes)
            {
                XmlNode barNode = fooNode.SelectSingleNode("bar");

                var bazNodes1 = fooNode.SelectNodes("/bar/bazs/baz");

                var bazNodes2 = fooNode.SelectNodes("bar/bazs/baz");

                var bazNodes3 = barNode.SelectNodes("/bazs/baz");

                Console.WriteLine($"Method 1 returned {bazNodes1.Count} nodes.");
                Console.WriteLine($"Method 2 returned {bazNodes2.Count} nodes.");
                Console.WriteLine($"Method 3 returned {bazNodes3.Count} nodes.");
            }
            Console.Read();
        }
    }
}

, который выдает:

Method 1 returned 0 nodes.
Method 2 returned 3 nodes.
Method 3 returned 0 nodes.

Здесь я немного запутался с использованием / при адресации узлов.Хотя получение fooNodes из корня документа работает с /foos/foo как xpath, но я не могу получить bazNodes, используя /bar/bazs/baz от узла <foo>, что странно для меня.И я также застрял с получением bazNodes от узла <bar>, что я думаю, потому что я не знаю правильный синтаксис.Итак, мои вопросы:

  1. Когда я должен включать ведущие / при адресации узлов?
  2. Как я могу получить <baz> узлов от узла <bar> в этом примере?

Ответы [ 2 ]

1 голос
/ 23 июня 2019

Ответ на ваш первый вопрос: если вы хотите начать абсолютный путь, который выбирается из корневого узла, вам нужно будет добавить начальный "/". Ответ на ваш второй вопрос приведен в примере кода ниже. Кроме того, я рекомендую статью для справки.

using System;
using System.Xml;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            var xmlDoc = new XmlDocument();
            xmlDoc.Load("test.xml");

            XmlNodeList fooNodes1 = xmlDoc.SelectNodes("/foos/foo/bar/bazs/*"); // starts an absolute path that selects from the root
                                                                            // foos element.
            Console.WriteLine($"Method 1 returned {fooNodes1.Count} nodes."); 

            XmlNodeList fooNodes2 = xmlDoc.SelectNodes("/foos/foo");    // "/foo" the document element(<foo>) of this document.

            foreach (XmlNode fooNode in fooNodes2)
            { 
                var bazNodes2 = fooNode.SelectNodes("./bar/bazs/baz");  // "." indicates the current node.
                var bazNodes3 = fooNode.SelectNodes("bar/bazs/baz"); // selects all baz elements that are children of an bazs element, 
                                                                 // which is itself a child of the root bar element.
                var bazNodes4 = fooNode.SelectNodes("bar/bazs/*");   // "*" selects any element in the path.
                var bazNodes5 = fooNode.SelectNodes("bar/*/baz");   
                var bazNodes6 = fooNode.SelectNodes("//bazs/*");     // selects any elements that are children of an bazs element, 
                                                                 // regardless of where bazs appear in the current context.
                var bazNodes7 = fooNode.SelectNodes("bar//baz");     // selects all the baz elements that are under an bar element, 
                                                                 // regardless of where they appear in the current context.
                var bazNodes8 = fooNode.SelectNodes("//bazs/baz");   // selects all the bazs elements that are children of an baz element, 
                                                                 // regardless of where they appear in the document.
                var bazNodes9 = fooNode.SelectNodes("//baz");        // starts a relative path that selects baz element anywhere.

                XmlNode barNode = fooNode.SelectSingleNode("bar");

                var bazNodes10 = barNode.SelectNodes("bazs/*");     // selects all nodes which are contained by a root bazs element.

                Console.WriteLine($"Method 2 returned {bazNodes2.Count} nodes.");
                Console.WriteLine($"Method 3 returned {bazNodes3.Count} nodes.");
                Console.WriteLine($"Method 4 returned {bazNodes4.Count} nodes.");
                Console.WriteLine($"Method 5 returned {bazNodes5.Count} nodes.");
                Console.WriteLine($"Method 6 returned {bazNodes6.Count} nodes.");
                Console.WriteLine($"Method 7 returned {bazNodes7.Count} nodes.");
                Console.WriteLine($"Method 8 returned {bazNodes8.Count} nodes.");
                Console.WriteLine($"Method 9 returned {bazNodes9.Count} nodes.");
                Console.WriteLine($"Method 10 returned {bazNodes10.Count} nodes.");
            }

            Console.Read();
        }
    }
}
1 голос
/ 22 июня 2019

Вы можете сделать с xml сериализатором

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

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            XmlReader reader = XmlReader.Create(FILENAME);
            XmlSerializer serializer = new XmlSerializer(typeof(Foos));
            Foos foos = (Foos)serializer.Deserialize(reader);
        }
    }
    [XmlRoot(ElementName = "foos")]
    public class Foos
    {
        [XmlElement("foo")]
        public List<Foo> foo { get; set; }  
    }
    [XmlRoot("foo")]
    public class Foo
    {
        [XmlElement("bar")]
        public Bar bar { get; set; }
    }
    [XmlRoot("bar")]
    public class Bar
    {
        [XmlArray("bazs")]
        [XmlArrayItem("baz")]
        public List<string> baz { get; set; }
    }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...