【发布时间】:2013-02-17 21:56:14
【问题描述】:
我正在尝试编写一个将 XML 作为输入的算法,并找到与特定元素关联的值,但 XML 正文中元素的位置会有所不同。我见过许多使用 XDocument.Descendants() 的示例,但大多数(如果不是全部)示例期望结构是一致的,并且后代是众所周知的。我想我需要递归 XML 才能找到这个值,但在朝着这个方向前进之前,请询问一般人群。
当元素的路径在每次调用中可能不同时,在 XDocument 中查找元素的最佳方法是什么?只需要找到第一次出现,而不是按任何特定顺序。可以通过变宽或深入找到第一次出现。
例如,如果我正在尝试查找元素“FirstName”,并且 Call one 的输入 XML 看起来像..
<?xml version="1.0"?>
<PERSON><Name><FirstName>BOB</FirstName></Name></PERSON>
下一个调用看起来像:
<?xml version="1.0"?>
<PERSONS><PERSON><Name><FirstName>BOB</FirstName></Name></PERSON></PERSONS>
你有什么推荐的? XDocument 中有没有我没见过的“查找”选项?
更新:
上面的简单示例适用于 XDocument.Descendents 的lazyberezovsky 答案,但真正的 XML 不能。我有问题的 XML...
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<To s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://localhost:52087/Service1.svc</To>
<Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://tempuri.org/IService1/GetDataUsingDataContract</Action>
</s:Header>
<s:Body>
<GetDataUsingDataContract xmlns="http://tempuri.org/">
<composite xmlns:a="http://schemas.datacontract.org/2004/07/WcfService2" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:BoolValue>false</a:BoolValue>
<a:Name>
<a:FirstName>BOB</a:FirstName>
</a:Name>
<a:StringValue i:nil="true" />
</composite>
</GetDataUsingDataContract>
</s:Body>
</s:Envelope>
更新:
lazyberezovsky 极大地帮助我向我展示了 Descendents 应该如何工作。注意 XML 中的名称空间。学过的知识。又发现了一个。有类似问题的文章..
Search XDocument using LINQ without knowing the namespace
使用以下sn-p解决...
var xdoc = XDocument.Parse(xml);
var name = (from p in xdoc.Descendants() where p.Name.LocalName == "FirstName" select p.Value).FirstOrDefault();
【问题讨论】:
-
对于这些示例,您可以只使用正则表达式来搜索文档文本。有什么不可行的原因吗?
-
你能提供一个你所指的正则表达式的例子吗?上面的示例是一个简单的问题示例,但我正在使用的 XML 具有可变名称空间,因此字符串解析即使不是不可能也变得困难。
-
@barrypicker 使用 Descendants 有什么问题?
-
@lazyberezovsky - 也许我只是错误地使用了 Descendents,但是当我尝试时,第一个调用会找到下一级元素。如果我按名称“FirstName”指定,如上面的示例所示,并且该元素不存在,我将得不到任何结果。如果我不指定名称,我会得到当前元素以下的所有元素,那么我需要更深入地了解。这就是我所说的需要递归结构的意思。我觉得这可能是我最好的选择...