提问人:Cyberdrac 提问时间:12/2/2022 最后编辑:Cyberdrac 更新时间:12/2/2022 访问量:158
XML Find,然后从上一个元素返回一个值
XML Find then return a value from previous element
问:
我正在处理一个构造奇怪的 XMl 文档,缺少 ID 和模棱两可的名称等。希望我的示例XML文档能为您描绘出一幅合适的画面。真正的文档是巨大的,有时嵌套 10 层或更多层深,真正的眼睛酸痛。
我需要做的是在名为 Supplier/Name 的节点中找到特定值。但要找到这个,我需要先在 Var/Value 中找到一个值,然后再查找。在我的示例中,我需要找到 Var/Value CLR-111。
我不知道最好是在 LINQ 中还是使用 XML 文档来执行此操作??我发现的壁橱是使用上一个节点的 XMLNode。但我不确定如何先找到位置,然后跳上两个。
简单的部分是找到元素,但不知道如何查找两个元素。这就是我轰炸的地方。
我需要返回的是 ACME。
<?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");
答:
0赞
AceGambit
12/2/2022
#1
您将需要搜索 CLR-111 节点(可能使用递归),一旦找到它,您就可以爬上树以返回该节点。node.ParentNode.ParentNode
Var
到达节点后,您可以使用它在 XmlDoc 中向后走动。Var
node.PreviousSibling
例如:
var clrXmlTextElement = ... // whatever the XmlText object element of the <Value>CLR-111</Value> node is when you find it.
var valueNode = clrNode.ParentNode; // <Value>CLR-111</Value>
var varNode = valueNode.ParentNode; // <Var>
var typeNode = varNode.PreviousSibling; // <Type>Paint</Type>
var supplierNode = typeNode.PreviousSibling; // <Supplier>
var supplierName = GetSupplierName(supplierNode); // ACME
string GetSupplierName(XmlNode supplierNode)
{
foreach (XmlElement xmlElement in supplierNode.ChildNodes)
{
if (xmlElement.Name == "Name")
{
return xmlElement.InnerText;
}
}
return "Error: no <Name> tag found in <Supplier> node.";
}
0赞
jdweng
12/2/2022
#2
我从不倒退。永远向前。我喜欢收集所有数据,然后使用字典查找值。
下面使用的是 Xml linq。我转换而不是使用值,所以如果项目为空,我不会得到异常
请参阅下面的代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication2
{
class Program
{
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
List<Supplier> suppliers = new List<Supplier>();
foreach(XElement job in doc.Descendants("Job"))
{
string jobId = (string)job.Attribute("ID");
XElement manufacturing = job.Element("Manufacturing");
string manufacturingId = manufacturing == null ? "" : (string)manufacturing.Attribute("ID");
foreach(XElement skuGroup in job.Descendants("SKUGroups"))
{
string skuGroupId = (string)skuGroup.Attribute("ID");
Supplier supplier = null;
foreach(XElement element in skuGroup.Elements())
{
switch(element.Name.LocalName)
{
case "Supplier":
supplier = new Supplier();
suppliers.Add(supplier);
supplier.jobId = jobId;
supplier.manufacturingId = manufacturingId;
supplier.skuGroupId = skuGroupId;
supplier.name = (string)element.Element("Name");
XElement details = element.Element("Details");
supplier.address = details == null ? "" : (string)details.Attribute("address");
supplier.zip = details == null ? "" : (string)details.Attribute("Zip");
break;
case "Type":
supplier.type = (string)element;
break;
case "Var":
supplier.varName = (string)element.Element("Name");
supplier.value = (string)element.Element("Value");
break;
}
}
}
}
Dictionary<string, Supplier> dict = suppliers.GroupBy(x => x.value).ToDictionary(x => x.Key, y => y.FirstOrDefault());
Supplier CLR_2222 = dict["CLR-2222"];
}
}
public class Supplier
{
public string jobId { get; set; }
public string manufacturingId { get; set; }
public string skuGroupId { get; set; }
public string name { get; set; }
public string address { get; set; }
public string zip { get; set; }
public string type { get; set; }
public string varName { get; set; }
public string value { get; set; }
}
}
评论
0赞
Cyberdrac
12/2/2022
非常感谢您抽出宝贵时间向我展示这个。我花了最后一个小时学习这个,它也给了我一些提示,我知道我会遇到其他问题。你是对的,最好从时间开始,然后慢慢来。
0赞
jdweng
12/2/2022
如果您有多个键,请将字典更改为以下内容:Dictionary<string, List<Supplier>> dict = suppliers。GroupBy(x => x.value)。ToDictionary(x => x.Key, y => y.ToList());还要看看我在哪里使用了 Descendants(不是子级,返回多个子级)和 Element(只返回一个直接子级)。
评论