简体   繁体   English

C#如何从xml文件中获取所有元素名称

[英]C# how can I get all elements name from a xml file

I'd like to get all the element name from a xml file, for example the xml file is, 我想从xml文件中获取所有元素名称,例如xml文件是,

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

I would like to get the element's name of "BookName". 我想得到元素的名称“BookName”。 "ISBN" and "PublishDate " and only those names, not include " BookStoreInfo" and its child node's name “ISBN”和“PublishDate”只有那些名称,不包括“BookStoreInfo”及其子节点的名称

I tried several ways, but doesn't work, how can I do it? 我尝试了几种方法,但是不起作用,我该怎么办呢?

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

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

There are lots of similar routes, though. 但是,有很多类似的路线。

Using XPath 使用XPath

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

gives you a list with all nodes in the document named BookStore 为您提供一个列表,其中包含名为BookStore的文档中的所有节点

I agree with Adam, the ideal condition is to have a schema that defines the content of xml document. 我同意Adam,理想的条件是拥有一个定义xml文档内容的模式。 However, sometimes this is not possible. 但是,有时这是不可能的。 Here is a simple method for iterating all of the nodes of an xml document and using a dictionary to store the unique local names. 这是一个简单的方法,用于迭代xml文档的所有节点,并使用字典来存储唯一的本地名称。 I like to keep track of the depth of each local name, so I use a list of int to store the depth. 我喜欢跟踪每个本地名称的深度,所以我使用int列表来存储深度。 Note that the XmlReader is "easy on the memory" since it does not load the entire document as the XmlDocument does. 请注意,XmlReader“很容易在内存中”,因为它不像XmlDocument那样加载整个文档。 In some instances it makes little difference because the size of the xml data is small. 在某些情况下,它没有什么区别,因为xml数据的大小很小。 In the following example, an 18.5MB file is read with an XmlReader. 在以下示例中,使用XmlReader读取18.5MB文件。 Using an XmlDocument to load this data would have been less effecient than using an XmlReader to read and sample its contents. 使用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]);
        }
    }
}

The purists way of doing this (and, to be fair, the right way) would be to have a schema contract definition and read it in that way. 纯粹主义者这样做的方式(并且,公平地,正确的方式)将是具有模式契约定义并以这种方式阅读它。 That being said, you could do something like this... 话虽这么说,你可以做这样的事......

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

This is, admittedly, a rudimentary method for obtaining the list of distinct node names for the Book node's children, but you didn't specify much else in the way of your environment (if you have 3.5, you could use LINQ to XML to make this a little prettier, for example), but this should get the job done regardless of your environment. 不可否认,这是获取Book节点子节点的不同节点名称列表的基本方法,但是您没有在环境中指定其他许多名称(如果您有3.5,则可以使用LINQ to XML进行制作)这有点漂亮,例如),但无论您的环境如何,这都应该完成工作。

If you're using C# 3.0, you can do the following: 如果您使用的是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();

If BookStore is ur root element then u can try following code 如果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];

            }
        }

You can try doing it using XPATH . 您可以尝试使用XPATH进行操作

XmlDocument doc = new XmlDocument();
doc.LoadXml("xml string");

XmlNodeList list = doc.SelectNodes("//BookStore/Book");

An online tool I find here can extract those elements 's names beautifully - just uploading the XML file and they print the names as a result webpage. 我在这里找到的在线工具可以很好地提取这些元素的名称 - 只需上传XML文件,然后将这些名称打印为结果网页。

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

在此输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM