2014-04-03 72 views
0

我是使用LINQ的新手,并试图从我已转换的XML文档中选择一个节点。XPathSelectElements总是返回表达式必须评估为节点集

这里是原始代码:

// 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被设置为“DocRouteDetail”

起初我还以为是与中的XPath的复杂性问题我使用的语句,但是我已经尝试过每一个组合我能想到的,甚至在与调试滚回来绝对基础:

xdoc.Root.XPathSelectElements(".") 
xdoc.Root.XPathSelectElements("//DocRouteDetail") 
etc 
在所有情况下

它返回NUL l并且它会生成一个异常,返回“Expression必须评估为节点集”。

这发生在C#中的.NET Framework 4.0中。

我已经检查和xdoc.Root变量不为空,我的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元素。

回答

1

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

我把它写成

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

这样,它选择你所需要的。

+0

嘿pjotr,谢谢,这确实选择。在阅读你的文章后,我注意到我的前面的后面的语句是无效的......我忘了:: node(),你的例子确实解决了这个问题。不知道为什么我在试图使用以下/之前,当我可以再次回到孩子。 – Justin

+0

我遇到了这个解决方案的一个新问题,然而,当我尝试使用以下代码创建不同元素名称的列表时,selectelements可行: 列表 elToConsider = xe .GroupBy(el => el.Name.ToString ()) .Select(grp => grp.First()。Name.ToString()) .ToList (); 我收到一个xpath异常: XPath表达式评估为意外的类型System.Xml.Linq.XText。 – Justin

+0

这个标准实际上并没有工作,在重写我的select distinct后,我发现它实际上是将“TEAM”作为选定元素而不是节点(parmRouteTemplateKey)返回。我也将它从*改为node()xdoc.Root.XPathSelectElement(“//”+ settings.ShredNode +“[1]/parent :: node()// child :: node()[name()!= '“+ settings.ShredNode +”'而不是(text())]“); – Justin

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);