-1

I have an XPath expression that returns nodes whose indexes are dependent upon/relative to their neighboring nodes. It works great in online tests (I tried it with two sites: http://www.freeformatter.com/xpath-tester.html and http://www.xpathtester.com), but in my test app in .NET it only works... well, partially.

Sample XML:

<Root>
    <IN1>
        <IN1_2>
            <IN1_2_1>100</IN1_2_1>
        </IN1_2>
    </IN1>
    <IN2>
        <IN2_2>100.1</IN2_2>
    </IN2>
    <IN1>
        <IN1_2>
            <IN1_2_1>200</IN1_2_1>
        </IN1_2>
    </IN1>
    <IN2>
        <IN2_2>200.1</IN2_2>
    </IN2>
    <IN2>
        <IN2_2>200.2</IN2_2>
    </IN2>
</Root>

The XPath queries:

  1. //IN1[2]/following-sibling::IN2[count(preceding-sibling::IN1)=2][1]//IN2_2
  2. //IN1[2]/following-sibling::IN2[count(preceding-sibling::IN1)=2][2]//IN2_2

The idea is to be able to index the IN2 nodes relative to the specified preceding IN1 node, i.e. for the first IN1 node the following IN2[1] would return the 100.1 child, and for the second IN1 node the following IN2[1] (i.e. same index as above) would return the 200.1 child. (And of course IN2[2] would return the 200.2 child, etc.)

So the first XPath works everywhere as expected and returns <IN2_2>200.1</IN2_2>. The second returns <IN2_2>200.2</IN2_2>, also as expected, but only in the online tests; it returns nothing in my test app!! (XmlDocument.SelectNodes returns an empty list)

The test app is an utterly simple WinForms app written in VS 2013 referencing .NET 4.5. The code basically creates the XmlDocument with the specified XML and calls SelectNodes with the above XPath.

I made absolutely sure it is the very same XML and XPath in both scenarios -- I stopped at a breakpoint on the SelectNodes call, and copy-pasted the XmlDocument.InnerXml value and the string I'm passing to it directly from the debugger into the aforementioned online "XPath tester" sites.

Just purely as a sanity check, I tried this XPath: //IN2[3]//IN2_2 and it worked fine (returned that elusive node with 200.2 value) in my test app.

I don't have any special XML-related packages or anything else "unusual" installed that would mess with this. (Besides, the first one, with index [1], works fine!)

Running out of options... Not sure how else to get this done (maybe there is another XPath I could use, but I can't figure it out.) They should both work. Is this maybe some weird known issue (bug?) with .NET?

Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
taiji123
  • 366
  • 5
  • 12
  • I would really appreciate it if whoever -1'd it would explain why? It is a real issue, where XML/XPath engines exhibit different behavior, and it actually got me stuck! If the question was inappropriate, I'd like to know why so that I can avoid repeating that mistake (if there was one) in the future. – taiji123 Mar 01 '16 at 14:33

1 Answers1

0

OMG I got it!!

I guess asking (my first) question on SO gave me an extra boost :-), and I really went to town on that XPath, trying things I haven't before.

Here's the version that seems to be working everywhere:

(//IN1[2]/following-sibling::IN2[count(preceding-sibling::IN1)=2])[2]//IN2_2

(here's the original, for easier reference):

//IN1[2]/following-sibling::IN2[count(preceding-sibling::IN1)=2][2]//IN2_2

I've no idea why it worked without the "extra" grouping/the parentheses in the online test sites -- or conversely, why it didn't work in .NET without those parentheses...

Unfortunately I don't know enough about XML to decide which is the correct/better XPath syntax. I only know that this last one works in both scenarios!

Hopefully this might help someone facing the same issue.

taiji123
  • 366
  • 5
  • 12