XPathSelectElements始终返回Expression必须求值为节点集

时间:2014-04-03 19:34:25

标签: c# .net xml linq xpath

我是使用LINQ的新手,我正在尝试从我已经转换过的XML文档中选择一个节点。

这是原始代码:

// create a LINQ xml doc
XDocument xdoc = XDocument.Parse(xTransformedDoc.OuterXml);

// get sibling elements to the shredding element 
IEnumerable<XElement> xe = xdoc.Root.XPathSelectElements("//" + settings.ShredNode + "[1]/(following-sibling|preceding-sibling)[name() != '" + settings.ShredNode + "']");

注意:在代码settings.ShredNode的早期设置为&#34; DocRouteDetail&#34;

起初我认为这是我使用的xpath语句的复杂性的一个问题但是我已经尝试了我能想到的每一个组合,甚至将它转回到VS调试器中的绝对基础:

xdoc.Root.XPathSelectElements(".")
xdoc.Root.XPathSelectElements("//DocRouteDetail")
etc

在所有情况下它返回null并且它生成一个异常返回&#34;表达式必须求值为一个节点集。&#34;

这发生在c#的.NET framework 4.0中。

我已经检查过,xdoc.Root变量不是null,我的xml看起来如下(出于安全原因,整个文档变薄了):

<DocFWImport xmlns:dtfn2="urn:my-scripts2">
  <Header SendDateTime="2014-04-03T19:26:50" />
  <Request>
    <DocRouteDetail MessagePurpose="1002" ResourceKey="A" >
      <DocStop StopNumber="0" Type="0" LocationType="DEPOT">
      </DocStop>
      <DocStop StopNumber="1" Type="3" LocationType="CUSTOMER" >
      </DocStop>
      <DocStop StopNumber="2" Type="0" LocationType="DEPOT">
      </DocStop>
    </DocRouteDetail>
    <parmRouteTemplateKey>TEAM</parmRouteTemplateKey>
    <DocRouteDetail MessagePurpose="1002" ResourceKey="B" >
      <DocStop StopNumber="0" Type="0" LocationType="DEPOT">
      </DocStop>
      <DocStop StopNumber="1" Type="3" LocationType="CUSTOMER" >
      </DocStop>
      <DocStop StopNumber="2" Type="0" LocationType="DEPOT">
      </DocStop>
    </DocRouteDetail>
    <parmRouteTemplateKey>SINGLE</parmRouteTemplateKey>
    etc
  </Request>
</DocFWImport>

它应该返回2个parmRouteTemplateKey元素。

2 个答案:

答案 0 :(得分:1)

这不是XPathSelectElements的错误,您的XPath查询无效 - 即具有|运算符的部分。您提及的其他基本查询执行工作。如果他们真的没有,那么在你发布的代码之外还有一些错误。

我把它写成

//DocRouteDetail[1]/parent::*/child::*[name()!='DocRouteDetail']

这样就可以选择你需要的东西。

答案 1 :(得分:0)

正如@pjotr所指出的,您的XPath尝试无效。您可以尝试使用union运算符(|)组合2个XPath代替:

var xpath1 = "//" + settings.ShredNode 
                  + "[1]/following-sibling[name() != '" + settings.ShredNode + "']";
var xpath2 = "//" + settings.ShredNode 
                  + "[1]/preceding-sibling[name() != '" + settings.ShredNode + "']";
IEnumerable<XElement> xe = 
        xdoc.Root
            .XPathSelectElements(xpath1 + " | " + xpath2);