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

如何在层级复杂的XML中根据Var/Value获取对应Supplier/Name值?

问题描述

处理结构怪异的XML文档(缺少ID、命名模糊,嵌套层级超10层),需求:

  • 找到Var/Value为CLR-111的节点
  • 向上查找对应的Supplier/Name节点值(预期返回ACME)

尝试用XmlDocument.SelectSingleNode无法正确向上定位节点,纠结选择LINQ还是XmlDocument实现。

示例XML

<?xml version="1.0" encoding="utf-8"?>
<Uni>
  <Job ID="Job1">
    <Manufacturing ID="MPG-1">
        <Factory>
            <SKUGroups ID="SKU-72">
                <Supplier>
                  <Name>ACME</Name>
                  <Details address="123 Bobs Road" Zip="90210" />
                </Supplier>
                <Type>Paint</Type>
                <Var>
                  <Name>ColorID</Name>
                  <Value>CLR-111</Value>
                </Var>
                <Supplier>
                  <Name>TomInc</Name>
                  <Details address="555 Jayne Lane" Zip="65986" />
                </Supplier>
                <Type>Tire</Type>
                <Var>
                  <Name>ColorID</Name>
                  <Value>CLR-2222</Value>
                </Var>
            </SKUGroups>
        </Factory>
    </Manufacturing>
  </Job>
</Uni>

现有代码

XmlDocument doc = new XmlDocument();
doc.PreserveWhitespace = true;
doc.Load(myPath);
XmlNode blaa = doc.SelectSingleNode("descendant::SKUGroups[Var/Value='CLR-111']/Var/Name");

解决方案

方案一:XmlDocument(优化XPath)

核心是调整XPath逻辑,直接定位目标Var节点的前置Supplier:

简化XPath查询

XmlDocument doc = new XmlDocument();
doc.Load(myPath);

// 直接获取目标Var节点之前的最后一个Supplier的Name
XmlNode supplierName = doc.SelectSingleNode("descendant::Var[Value='CLR-111']/preceding-sibling::Supplier[last()]/Name");

if (supplierName != null)
{
    string result = supplierName.InnerText; // 结果为ACME
}

分步导航(可读性更强)

如果XPath表达式过于复杂,可拆分步骤:

XmlDocument doc = new XmlDocument();
doc.Load(myPath);

// 1. 定位到Value为CLR-111的Var节点
XmlNode targetVar = doc.SelectSingleNode("descendant::Var[Value='CLR-111']");
if (targetVar == null) return;

// 2. 找到该Var节点之前的最后一个Supplier节点
XmlNode supplier = targetVar.SelectSingleNode("preceding-sibling::Supplier[last()]");
if (supplier == null) return;

// 3. 获取Name值
string result = supplier.SelectSingleNode("Name").InnerText;

方案二:LINQ to XML(推荐)

LINQ to XML的节点导航更直观,适合复杂层级的文档,逻辑清晰易维护:

XDocument doc = XDocument.Load(myPath);

// 找到Value为CLR-111的Var节点
var targetVar = doc.Descendants("Var")
                   .FirstOrDefault(v => v.Element("Value")?.Value == "CLR-111");

if (targetVar == null) return;

// 获取该Var节点之前的最后一个Supplier的Name值
string result = targetVar
    .ElementsBeforeSelf("Supplier")
    .LastOrDefault()?
    .Element("Name")?
    .Value; // 结果为ACME

方案对比

  • XmlDocument:适合熟悉XPath的场景,代码简洁,但复杂结构下XPath可读性差,调试难度高。
  • LINQ to XML:链式调用逻辑直观,节点导航灵活,维护成本低,尤其适合嵌套层级深的文档,优先推荐。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 14:12:26