Justin
Justin

Reputation: 1503

XPathSelectElements always returns Expression must evaluate to a node-set

I am new to using LINQ and am trying to select a node from an XML document that i've transformed.

here is the raw code:

// 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 + "']");

Note: earlier in the code settings.ShredNode is set to "DocRouteDetail"

at first i thought it was a problem with the complexity of the xpath statement i am using however i've tried every combination i can think of and even rolled it back to absolute basics in the VS debugger:

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

in all cases it returns back null and it generates an exception returning "Expression must evaluate to a node-set."

this is happening in .NET framework 4.0 in c#.

i have checked and the xdoc.Root variable is not null and my xml looks like the following (full document slimmed down for security reasons):

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

it should have returned the 2 parmRouteTemplateKey elements.

Upvotes: 0

Views: 1734

Answers (2)

har07
har07

Reputation: 89285

As pointed by @pjotr, your XPath attempt is not valid. You can try to combine 2 XPaths using union operator (|) like this instead :

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

Upvotes: 0

voidengine
voidengine

Reputation: 2579

It's not the XPathSelectElements's fault, your XPath query is invalid - namely the part with the | operator. The other basic queries you're mentioning do work. If they really don't, then there's some another error outside the code you've posted.

I'd write it as

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

that way it selects what you need.

Upvotes: 1

Related Questions