【问题标题】:How to address child nodes from an XmlNode object?如何从 XmlNode 对象寻址子节点?
【发布时间】:2019-06-22 07:24:48
【问题描述】:

这是我的测试 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>

在本文档中,每个&lt;foo&gt; 节点都有一个&lt;bar&gt; 节点,每个&lt;bar&gt; 节点都有一个&lt;baz&gt; 节点列表。我想从每个&lt;bar&gt; 访问这些&lt;baz&gt; 节点。这是我的代码:

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 ,但我无法从 &lt;foo&gt; 节点使用 /bar/bazs/baz 获取 bazNodes ,这对我来说很奇怪。而且我还坚持从&lt;bar&gt; 节点获取bazNodes,我认为这是因为我不知道正确的语法。所以我的问题是:

  1. 在寻址节点时,我应该在什么时候包含前导 /?
  2. 在此示例中,如何从 &lt;bar&gt; 节点获取 &lt;baz&gt; 节点?

【问题讨论】:

    标签: c# xml xml-parsing


    【解决方案1】:

    第一个问题的答案是,如果要启动从根节点选择的绝对路径,则需要包含前导“/”。第二个问题的答案请参考下面的示例代码。另外,我推荐article供参考。

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

    【讨论】:

      【解决方案2】:

      你可以用 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; }
          }
      
      }
      

      【讨论】:

      • 非常有趣的例子。但没有回答我的第一个问题。 1+虽然。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-06
      • 1970-01-01
      • 2018-11-19
      相关资源
      最近更新 更多