【问题标题】:C# how can I get all elements name from a xml fileC#如何从xml文件中获取所有元素名称
【发布时间】:2010-10-25 06:44:56
【问题描述】:

我想从一个 xml 文件中获取所有元素名称,例如 xml 文件是,

<BookStore>
  <BookStoreInfo>
    <Address />
    <Tel />
    <Fax />
  <BookStoreInfo>
  <Book>
    <BookName />
    <ISBN />
    <PublishDate />
  </Book>
  <Book>
   ....
  </Book>
</BookStore>

我想获取元素的名称“BookName”。 "ISBN" 和 "PublishDate" 仅包含这些名称,不包括 "BookStoreInfo" 及其子节点的名称

试了好几种方法都不行,怎么办?

【问题讨论】:

    标签: c# xml


    【解决方案1】:

    好吧,使用 XDocument 和 LINQ-to-XML:

    foreach(var name in doc.Root.DescendantNodes().OfType<XElement>()
            .Select(x => x.Name).Distinct())
    {
        Console.WriteLine(name);
    }
    

    不过,类似的路线还有很多。

    【讨论】:

    • 非常感谢。我不熟悉 LINQ-XML。但它工作得很好。还有一件事,我更新了上面的问题。我怎样才能只在 元素下获取子节点的名称。
    • 如果您的意思是在“书”下(根据更新的问题) - 类似于:doc.Root.Element("Book").DescendantNodes()...
    • 是的,我就是这个意思。代码正在运行,再次感谢您!
    • @MarcGravell 我们可以使用这种方法获取整个节点集合吗,我的意思是具有特定名称的整个节点
    • @Chintan_Patel 在下面指出,您可以使用 GetElementsByTagName 方法在一行中完成
    【解决方案2】:

    使用 XPath

    XmlDocument xdoc = new XmlDocument(); 
    xdoc.Load(something);
    XmlNodeList list = xdoc.SelectNodes("//BookStore");
    

    为您提供一个包含名为 BookStore 的文档中所有节点的列表

    【讨论】:

      【解决方案3】:

      我同意 Adam 的观点,理想的条件是拥有一个定义 xml 文档内容的模式。但是,有时这是不可能的。这是一个简单的方法,用于迭代 xml 文档的所有节点并使用字典来存储唯一的本地名称。我喜欢跟踪每个本地名称的深度,所以我使用一个 int 列表来存储深度。请注意,XmlReader“在内存上很容易”,因为它不像 XmlDocument 那样加载整个文档。在某些情况下,它几乎没有什么区别,因为 xml 数据的大小很小。在以下示例中,使用 XmlReader 读取一个 18.5MB 的文件。使用 XmlDocument 加载此数据的效率低于使用 XmlReader 读取和采样其内容的效率。

      string documentPath = @"C:\Docs\cim_schema_2.18.1-Final-XMLAll\all_classes.xml";
      
      Dictionary<string, List<int>> nodeTable = new Dictionary<string, List<int>>();
      using (XmlReader reader = XmlReader.Create(documentPath))
      {
          while (!reader.EOF)
          {
              if (reader.NodeType == XmlNodeType.Element)
              {
                  if (!nodeTable.ContainsKey(reader.LocalName))
                  {
                      nodeTable.Add(reader.LocalName, new List<int>(new int[] { reader.Depth }));
                  }
                  else if (!nodeTable[reader.LocalName].Contains(reader.Depth))
                  {
                      nodeTable[reader.LocalName].Add(reader.Depth);
                  }
              }
              reader.Read();
          }
      }
      Console.WriteLine("The node table has {0} items.",nodeTable.Count);
      foreach (KeyValuePair<string, List<int>> kv in nodeTable)
      {
          Console.WriteLine("{0} [{1}]",kv.Key, kv.Value.Count);
          for (int i = 0; i < kv.Value.Count; i++)
          {
              if (i < kv.Value.Count-1)
              {
                  Console.Write("{0}, ", kv.Value[i]);
              }
              else
              {
                  Console.WriteLine(kv.Value[i]);
              }
          }
      }
      

      【讨论】:

        【解决方案4】:

        这样做的纯粹主义者的方式(公平地说,正确的方式)是有一个模式契约定义并以这种方式阅读它。话虽如此,你可以做这样的事情......

        List<string> nodeNames = new List<string>();
        
        foreach(System.Xml.XmlNode node in doc.SelectNodes("BookStore/Book"))
        {
            foreach(System.Xml.XmlNode child in node.Children) 
            {
                if(!nodeNames.Contains(child.Name)) nodeNames.Add(child.Name);
            }
        }
        

        诚然,这是获取Book 节点的子节点的不同节点名称列表的基本方法,但您没有在环境方式中指定太多其他内容(如果您有 3.5,则可以使用例如,LINQ to XML 使它更漂亮),但无论您的环境如何,这都应该可以完成工作。

        【讨论】:

          【解决方案5】:

          如果您使用的是 C# 3.0,则可以执行以下操作:

          var data = XElement.Load("c:/test.xml"); // change this to reflect location of your xml file
          
          var allElementNames = 
              (from e in in data.Descendants()
              select e.Name).Distinct();
          

          【讨论】:

          • 没有 C# 3.5 这样的东西;不过,它使用 C# 3.0 和 .NET 3.5。
          • 很好的答案。你如何计算每个标签出现的次数?
          【解决方案6】:

          您可以尝试使用XPATH

          XmlDocument doc = new XmlDocument();
          doc.LoadXml("xml string");
          
          XmlNodeList list = doc.SelectNodes("//BookStore/Book");
          

          【讨论】:

            【解决方案7】:

            如果 BookStore 是您的根元素,那么您可以尝试以下代码

            XmlDocument doc = new XmlDocument();
                    doc.Load(configPath);
                    XmlNodeList list = doc.DocumentElement.GetElementsByTagName("Book");
                    if (list.Count != 0)
                    {
                        for (int i = 0; i < list[0].ChildNodes.Count; i++)
                        {
                            XmlNode child = list[0].ChildNodes[i];
            
                        }
                    }
            

            【讨论】:

              【解决方案8】:

              我在这里找到的一个在线工具可以很好地提取这些元素的名称 - 只需上传 XML 文件,然后它们会将名称打印为结果网页。

              http://taporware.ualberta.ca/~taporware/xmlTools/listxml.shtml

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2013-09-12
                • 1970-01-01
                • 2013-09-08
                • 1970-01-01
                • 1970-01-01
                • 2013-01-22
                • 2023-03-10
                相关资源
                最近更新 更多