You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

XML解析问题:如何将交易数据归属到对应父节点下

问题:XML解析时交易归属错误

我在读取、解析XML文件时遇到问题:程序通过OpenFileDialog选择XML文件并读取所有节点,目前存在的问题是,XML中有ID为145、175的两个父节点,每个父节点下各有4条交易,但程序会将全部8条交易都归属到这两个父节点下。

我的代码片段

Stream myStream = null; 
OpenFileDialog openFileDialog1 = new OpenFileDialog(); 
openFileDialog1.InitialDirectory = "path_of_my_File"; 
openFileDialog1.Filter = "xml files (*.xml)|*.xml"; 
openFileDialog1.FilterIndex = 2; 
openFileDialog1.RestoreDirectory = true; 

if (openFileDialog1.ShowDialog() == DialogResult.OK) { 
    try { 
        if ((myStream = openFileDialog1.OpenFile()) != null) { 
            string path = openFileDialog1.FileName; 
            XmlReader xmlFile; 
            xmlFile = XmlReader.Create(path, new XmlReaderSettings()); 
            DataSet ds = new DataSet(); 
            ds.ReadXml(xmlFile); 

            int i = 0; 
            DataTable dt = new DataTable(); 
            dt.Columns.Add("ID", typeof(string)); 
            dt.Columns.Add("Date", typeof(string)); 
            dt.Columns.Add("Transaction", typeof(string)); 
            dt.Columns.Add("Value1", typeof(string)); 
            dt.Columns.Add("Value2", typeof(string)); 
            dt.Columns.Add("Value3", typeof(string)); 

            XmlDocument xmldoc = new XmlDocument(); 
            xmldoc.Load(path); 
            XmlNodeList nodeList = xmldoc.SelectNodes("/statement/retailers/retailer"); 

            foreach (XmlNode node in nodeList) { 
                XmlNodeList nodeList2 = xmldoc.SelectNodes("/statement/retailers/retailer/terminals/terminal/transactions"); 
                DataRow dtrow = dt.NewRow(); 
                dtrow["ID"] = node.Attributes["ID"].Value; 
                dt.Rows.Add(dtrow); 

                foreach (XmlNode node2 in nodeList2) { 
                    dtrow = dt.NewRow(); 
                    dtrow["Date"] = node2["transaction"].Attributes["date"].Value; 
                    dtrow["Transaction"] = node2["transaction"].Attributes["transaction"].Value; 
                    dtrow["Value1"] = node2["transaction"].Attributes["Value1"].Value; 
                    dtrow["Value2"] = node2["transaction"].Attributes["Value2"].Value; 
                    dtrow["Value3"] = node2["transaction"].Attributes["Value3"].Value; 
                    dt.Rows.Add(dtrow); 
                } 
            } 
            dataGridView2.DataSource = dt; 
        } 
    } catch (Exception ex) { 
        MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message); 
    } 
}

XML结构示例

<root> 
    <factory name ="145"> 
        <id name = "xxx" value1 ="b" value2 ="b" value3 ="b" > 
        </factory> 
    <factory name ="175"> 
        <id name = "xxxxxxxxxxxx" value1 ="c" value2 ="c" value3 ="c" > 
        </factory> 
</root>

请问如何修改代码,让每个父节点只对应归属自己的4条交易?


解决方案:修正交易节点的选择范围

问题出在你获取交易节点的方式上——每次循环父节点时,你都用xmldoc.SelectNodes()从整个XML文档里查询所有交易节点,这就导致每个父节点都会绑定所有的8条交易。

你需要做的是基于当前遍历的父节点来查询它下面的交易节点,而不是从根节点重新查询。具体修改步骤如下:

  1. 调整交易节点的查询路径
    把获取交易节点的代码从:
XmlNodeList nodeList2 = xmldoc.SelectNodes("/statement/retailers/retailer/terminals/terminal/transactions");

改成:

// 从当前父节点node出发,用相对路径查询下属交易
XmlNodeList nodeList2 = node.SelectNodes("./terminals/terminal/transactions");

这里的./表示从当前节点开始查找,这样就能只获取当前父节点下的交易了。

  1. 优化数据行的逻辑(可选)
    你当前的代码会先添加一条只有ID的空行,再添加交易行。如果想让数据更规整,可以给每条交易都带上父节点ID,修改后的交易循环部分如下:
foreach (XmlNode node2 in nodeList2) {
    dtrow = dt.NewRow();
    dtrow["ID"] = node.Attributes["ID"].Value; // 每条交易关联对应父节点ID
    dtrow["Date"] = node2["transaction"].Attributes["date"].Value;
    dtrow["Transaction"] = node2["transaction"].Attributes["transaction"].Value;
    dtrow["Value1"] = node2["transaction"].Attributes["Value1"].Value;
    dtrow["Value2"] = node2["transaction"].Attributes["Value2"].Value;
    dtrow["Value3"] = node2["transaction"].Attributes["Value3"].Value;
    dt.Rows.Add(dtrow);
}

这样就不会出现单独的空ID行,数据展示更清晰。

  1. 清理冗余代码
    你代码里创建了DataSet ds但完全没用到,可以把这部分代码删掉,减少不必要的资源消耗。

修改后的核心循环代码如下:

XmlDocument xmldoc = new XmlDocument();
xmldoc.Load(path);
XmlNodeList nodeList = xmldoc.SelectNodes("/statement/retailers/retailer");

foreach (XmlNode node in nodeList) {
    // 从当前父节点获取下属交易
    XmlNodeList nodeList2 = node.SelectNodes("./terminals/terminal/transactions");

    foreach (XmlNode node2 in nodeList2) {
        DataRow dtrow = dt.NewRow();
        dtrow["ID"] = node.Attributes["ID"].Value;
        dtrow["Date"] = node2["transaction"].Attributes["date"].Value;
        dtrow["Transaction"] = node2["transaction"].Attributes["transaction"].Value;
        dtrow["Value1"] = node2["transaction"].Attributes["Value1"].Value;
        dtrow["Value2"] = node2["transaction"].Attributes["Value2"].Value;
        dtrow["Value3"] = node2["transaction"].Attributes["Value3"].Value;
        dt.Rows.Add(dtrow);
    }
}
dataGridView2.DataSource = dt;

这样修改后,每个父节点只会加载自己下面的4条交易,不会再出现所有交易重复绑定的问题了。

内容的提问来源于stack exchange,提问作者DRastislav

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:34:43