如何在 C# 中获取 XML 的所有子节点

Posted

技术标签:

【中文标题】如何在 C# 中获取 XML 的所有子节点【英文标题】:How to get all child nodes of an XML in C# 【发布时间】:2015-11-18 09:01:02 【问题描述】:

我有一个这样的 XML 文档:

<Columns>
  <Column>
    <Name>A</Name>
    <Width>100</Width>
  </Column>
</Columns>

<Columns>

</Columns>

<Columns>
  <Column>
    <Name>C</Name>
    <Width>300</Width>
  </Column>
  <Column>
    <Name>C1</Name>
    <Width>310</Width>
  </Column>
</Columns>

我正在获取他们的名称和宽度文本并将它们存储为一个列表。

var man = new XmlNamespaceManager(xdoc.NameTable);
man.AddNamespace("ns", "http://schemas.microsoft.com/project");
List <string> lstText = new List<string>();
List <List<string>> lst = new List<List<string>>();
XmlNodeList xnList = xdoc.SelectNodes("/ns:Columns/ns:Column", man);

foreach (XmlNode xn in xnList)
        
           lstText.Add(xn["Name"].InnerText));
           lstText.Add(xn["Width"].InnerText));
        
lst.Add(lstText);

所以,我只能得到这些值:A 和 100,C 和 300。 我也想买C1和310。我怎样才能得到它们?

编辑:某些列没有列,某些列有 1 个或多个列。在这个示例中,我的 List 有 3 个元素:

lst[0][0] = A, 100
lst[1][0] = null
lst[2][0] = C, 300, lst[2][1] = C1, 310

【问题讨论】:

您希望将所有元素都加载到字典之类的集合中吗? 对不起。我更新了问题。你有什么想法吗? 好的。我会尽快发布代码。 【参考方案1】:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;

public class MainClass

public static void Main()

    XmlDocument mDocument = new XmlDocument();
    XmlNode mCurrentNode;

    mDocument.Load("XPathQuery.xml");
    mCurrentNode = mDocument.DocumentElement;


    XmlNodeList nodeList = mCurrentNode.SelectNodes("*");
    DisplayList(nodeList);


static void DisplayList(XmlNodeList nodeList)

    foreach (XmlNode node in nodeList)
    
        RecurseXmlDocumentNoSiblings(node);
    


static void RecurseXmlDocumentNoSiblings(XmlNode root)

    if (root is XmlElement)
    
        Console.WriteLine(root.Name);
        if (root.HasChildNodes)
            RecurseXmlDocument(root.FirstChild);
    
    else if (root is XmlText)
    
        string text = ((XmlText)root).Value;
        Console.WriteLine(text);
    
    else if (root is XmlComment)
    
        string text = root.Value;
        Console.WriteLine(text);
        if (root.HasChildNodes)
            RecurseXmlDocument(root.FirstChild);
    

static void RecurseXmlDocument(XmlNode root)

    if (root is XmlElement)
    
        Console.WriteLine(root.Name);
        if (root.HasChildNodes)
            RecurseXmlDocument(root.FirstChild);
        if (root.NextSibling != null)
            RecurseXmlDocument(root.NextSibling);
    
    else if (root is XmlText)
    
        string text = ((XmlText)root).Value;
        Console.WriteLine(text);
    
    else if (root is XmlComment)
    
        string text = root.Value;
        Console.WriteLine(text);
        if (root.HasChildNodes)
            RecurseXmlDocument(root.FirstChild);
        if (root.NextSibling != null)
            RecurseXmlDocument(root.NextSibling);
    

【讨论】:

如果我们只想对“列”节点执行此操作,我们会怎么做? 参考java2s.com/Tutorial/CSharp/0540__XML/SelectAllChildNodes.htm和java2s.com/Tutorial/CSharp/0540__XML/…【参考方案2】:
    public readonly Dictionary<string, int> XmlValues = new Dictionary<string, int>();
    public void Analyze(XmlDocument xml)
    
        RecurseXmlDocument(xml.LastChild);
    

    void RecurseXmlDocument(XmlNode root)
    
        switch (root.NodeType)
        
            case XmlNodeType.Element:
                if (root.HasChildNodes)
                    RecurseXmlDocument(root.FirstChild);
                if (root.NextSibling != null)
                    RecurseXmlDocument(root.NextSibling);
                break;

            case XmlNodeType.Text:
                DictionayHelper.AddValue(XmlValues, root.Value);
                break;
        
    

【讨论】:

【参考方案3】:

使用 System.Xml.Linq:

const string name = "Name";
var xml = XDocument.Load(@"P:\athToYour\columns.xml");
var columns = xml.Descendants(name).Select(x => new

    Name = x.Value,
    Width = x.ElementsAfterSelf("Width").FirstOrDefault().Value
)
.ToDictionary(x=> x.Name, x=> x.Width);
columns.Dump();

【讨论】:

【参考方案4】:

你可以这样做;如果需要,可以将其减少到 2 行。

                var xDoc = XDocument.Load(@"c:\XPathQuery.xml");
        //this query gets Names and widths
        var widths = xDoc.Descendants().Where(x => x.Name.LocalName.Equals("Name")).Select(x => new  Name = x.Value, Width = x.ElementsAfterSelf().First().Value ).ToList();

        //if you want to loop through the collection, you can do like this.
        foreach (var width in widths)
        
            var name = width.Name;
            var value = width.Width;
        

【讨论】:

以上是关于如何在 C# 中获取 XML 的所有子节点的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C# 中将子节点添加到肥皂信封?

如何在c#中使用xelement获取xml节点值

在c#的winform 下怎么读取 xml文件中的数据?

wpf中的treeview如何增加2级节点?在C#中如何添加?

如何将XML子节点添加到父节点c#

C#里treeview如何向指定NAME节点添加子节点?