在XPath变量时查找元素

时间:2013-02-17 21:56:15

标签: c# xml linq xpath

我正在尝试编写一个算法,该算法将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中是否有“查找”选项,我还没有看到过?

UPDATE:

上面的简单示例适用于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>

UPDATE:

lazyberezovsky帮助极大地向我展示了后代应该如何运作。注意XML中的命名空间。学过的知识。发现另一个。有类似问题的文章..

Search XDocument using LINQ without knowing the namespace

使用以下代码段解决...

var xdoc = XDocument.Parse(xml);
var name = (from p in xdoc.Descendants() where p.Name.LocalName == "FirstName" select p.Value).FirstOrDefault();

3 个答案:

答案 0 :(得分:1)

当您使用后代查找第一次出现的元素时,您不需要知道 文件结构。以下代码适用于您的两种情况:

var xdoc = XDocument.Load(path_to_xml);
var name = (string)xdoc.Descendants("FirstName").FirstOrDefault();

与XPath相同

var name = (string)xdoc.XPathSelectElement("//FirstName[1]");

答案 1 :(得分:0)

在不知道XML文档的所有可能排列的情况下(顺便说一下这是非常不寻常的)我认为没有人希望能给你任何有价值的建议。

答案 2 :(得分:0)

“只需​​要找到第一个匹配项,而不是任何特定的顺序。”我认为Descendants会欺骗。看看这个:

string xml = @"<?xml version=""1.0""?>
             <PERSONS>
                  <PERSON>
                      <Name>
                         <FirstName>BOB</FirstName>
                      </Name>
                  </PERSON>
             </PERSONS>";
XDocument doc = XDocument.Parse(xml);
Console.WriteLine(string.Join(",", doc.Descendants("FirstName").Select(e =>(string)e)));

xml = @"<?xml version=""1.0""?>
            <PERSON>
               <Name>
                   <FirstName>BOB</FirstName>
               </Name>
            </PERSON>";
doc = XDocument.Parse(xml);
Console.WriteLine(string.Join(",", doc.Descendants("FirstName").Select(e =>(string)e)));