c#遍历嵌套层次很多的xml

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c#遍历嵌套层次很多的xml相关的知识,希望对你有一定的参考价值。

网上的代码都是原文件只有两层从根目录开始遍历一下就可以了,但工作中需要嵌套十几层的话一层一层的遍历太过困难了吧,能不能像html那样指定标签访问啊

可使用XPATH语法来实现
XmlDocument dom = new XmlDocument();
var nodes = dom.SelectNodes("//a/b/c/d"); /就是一层,这是获取多个
var node = dom.SelectSingleNode("//k/j/t"); 只取一个追问

也就是不管怎么也必须知道从根目录到最底那层的层次结构才可以吧,这个我承认比遍历简单多了,但是这个
var nodes =dom.SelectNodes("//a/b/c/d"); 怎么写

e的值

获得第2个c中的第3个d中e的值

追答

//xml/a/c/d/e
这是全路径
你可以写成
//e 那这个XML文档中所有E节点全找出来。

参考技术A C# XML提供了带属性取值的实现,就类似于javascript 按ById 或jQuery按Id、class来定位某个结点。

C# 提取XML带属性的方法如下:
foreach (XmlNode item in xnl) // xnl是指定的xml文档某处的层次列表。

Console.WriteLine(item.Attributes["Name"].Value);
追问

查了下foreach用法,但是xnl要得到不还是要遍历全部层找到想要结点这一层的层次列表吗?

e的值

就拿这个来说怎么不遍历全部得到第2个e的值

追答

假设test.xml文件层次如下:

<?xml version="1.0" encoding="utf-8" ?>
<a>
  <b></b>
  <c></c>
  <d>
    <e name="FirstE" value="第一个E的值" />
    <e name="SecondE" value="第二个E的值" />
  </d>
</a>

则,用C#提取第二个e的代码如下:

static void Main(string[] args)
        

            XmlDocument doc = new XmlDocument();
            doc.Load("test.xml");
            XmlNodeList xnl = doc.SelectNodes("/a/d/e");

            foreach (XmlNode item in xnl)
            
                if (item.Attributes["name"].Value == "SecondE") 
                    Console.WriteLine(item.Attributes["value"].Value);
                    break;
                
                
            
            Console.ReadKey(true);
        

追问

    <a>

         <b>

            <c>

                <f></f><f></f>

            </c>

           <c>

                <e>123</e><e>456</e><e><f>要的是</f></e><f>不要这</f>

          </c>

        </b>

    </a>

    不还是主目录下一层就没了吗,我把格式改了改你看看怎么找到第2个c中e下面包裹的f的内容吧

遍历xml文件并将内容存储在Textfield c#中

【中文标题】遍历xml文件并将内容存储在Textfield c#中【英文标题】:Iterate through xml file and store content inside Textfield c# 【发布时间】:2017-12-09 11:56:46 【问题描述】:

我有一个 Xml 文件,我想在其中循环每个模块节点,每个模块节点递增 1。这是我的 xml 文件的示例:

<PersonDetails>
  <PersonTitle>Teacher</PersonTitle>
  <Keystage3>
    <Subject>
      <subjectName>maths</subjectName>
      <subjectId>qq1</subjectId>
      <subjectvalue>20</subjectvalue>
      <subjectscore />
    </Subject>
    <Subject>
      <subjectName>science</subjectName>
      <subjectId>sla1s</subjectId>
      <subjectvalue>25</subjectvalue>
      <subjectscore />
    </Subject>
  </Keystage3>
</PersonDetails>

我想遍历 xml 文件并获取两者的所有主题数据 &lt;Subject&gt; 节点并将每个值存储在一个变量中。

我有一段代码从特定节点获取值并输出 它在文本字段上。

这是我目前的代码:

public partial class Form1 : Form

    private string subName, subId, subvalue;

    public XmlDocument Doc;

    public Form1()
    
        InitializeComponent();
    

    private void button1_Click(object sender, EventArgs e)
    

        XmlTextReader reader = new XmlTextReader("data.xml");
        XmlNodeType type;

        while (reader.Read()) 

            type = reader.NodeType;

            if(type == XmlNodeType.Element)
            

                    if (reader.Name == "subjectName")
                    
                        reader.Read();
                        textBox1.Text = reader.Value;
                    
                    if (reader.Name == "subjectId")
                    
                        reader.Read();
                        textBox2.Text = reader.Value;
                    
                    if (reader.Name == "subjectvalue")
                    
                        reader.Read();
                        textBox3.Text = reader.Value;
                   


            
        
        reader.Close();


    

我怎样才能使收到的输出类似于:

maths,qq1,20
science,sla1s,25

【问题讨论】:

非常不幸的是,主题节点会像这样递增,而不是将数字作为属性或子元素。我认为您无法控制该 xml 的生成方式? 我已经定制了它,以便每次写入主题节点时,值都会增加 1。我怎样才能使每个主题节点都可以在节点内有一个属性来显示数字? 我不知道您是如何创建 XML 但任何 XML API 都将支持属性。 【参考方案1】:

使用一些 LINQ-Magic,您可以执行以下操作:

XElement root = XElement.Load("data.xml");
        var subjects = from subject in root.Descendants()
                          where subject.Name.LocalName.Contains("Subject")
                          select new
                          
                              SubjectName = subject.Element("subjectName").Value,
                              SubjectId = subject.Element("subjectId").Value,
                              SubjectValue = subject.Element("subjectvalue").Value
                          ;

foreach (var subject in subjects)

    Console.WriteLine(subject);

    //you can use subject like this:
    string subjectName = subject.SubjectName;
    string subjectId = subject.SubjectId;
    string subjectValue = subject.SubjectValue;

这将打印:

 SubjectName = maths, SubjectId = qq1, SubjectValue = 20 
 SubjectName = science, SubjectId = sla1s, SubjectValue = 25 

包括:

using System;
using System.Data;
using System.Linq;
using System.Windows.Forms;
using System.Xml.Linq;

【讨论】:

@user7388968 您能否提供更多信息(行、异常类型、堆栈跟踪)。您可能需要使用 VS2017 和 .net 4.6.1。但它绝对适合我。 进一步按照您的代码是否可以在动态创建的输入框中输出值? @user7388968 你可以创建一些文本框,但管理布局会很困难。我建议使用 DataTable,您应该能够通过 Google 搜索找到一些基本示例。【参考方案2】:

您可以使用XDocument 来执行它。如果您想将节点值存储为一个集合,您可以像这样为SubjectNode 创建一个类;

        public class SubjectNode
        
            public string SubjectName  get; set; 
            public string SubjectId  get; set; 
            public string SubjectValue  get; set; 
        

然后你可以这样检索数据;

        var xdoc = XDocument.Load("data.xml");
        var keystageNode = xdoc.Descendants("Keystage3").FirstOrDefault();
        var iterateNode = keystageNode.FirstNode;
        var subjectNodes = new List<SubjectNode>();
        while (iterateNode != null)
        
            var node = (XElement)iterateNode.NextNode;
            subjectNodes.Add(new SubjectNode
            
                SubjectName = node.Element("subjectName").Value,
                SubjectId = node.Element("subjectId").Value,
                SubjectValue = node.Element("subjectvalue").Value
            );
            iterateNode = iterateNode.NextNode;
        

【讨论】:

如果可能的话,请您解释一下为什么要对 node.Value 执行 nodeValue + 1。 我理解你的问题,你想增加subjectvalue +1。我说的对吗? 我想读取 节点的所有子节点,该节点递增 1 并将值存储在文本字段中,而不是保存到 xml。 按照您的代码,我尝试运行它,但是它只显示每个元素的最后一个值,因此 textBox1 显示 science , textBox2 显示 sla1s , textBox3 显示 25 。可以更改此代码,使其显示来自第一个 的数据,然后显示来自 的数据吗?抱歉问了太多问题,我对 xml 节点很陌生。 因此,您希望在文本框中依次显示“主题”节点。我对吗 ?实际上,这是另一个问题。因为要执行它,您应该与主线程分开调用文本框。

以上是关于c#遍历嵌套层次很多的xml的主要内容,如果未能解决你的问题,请参考以下文章

C#:循环遍历嵌套结构的成员对象

C#实现二叉树的各种遍历

使用freemarker的嵌套xml标签遍历

C# s asi

C#中 xml文件遍历?

通过 ASP.NET MVC 在 C# 视图中遍历匿名对象的嵌套 LINQ 查询