I am trying to use a list of possible values in an XPath condition to find a node in XML, but XPathSelectElement throws a System.Xml.XPath.XPathException 'an invalid token'.
Here is a samle code in .Net Framework 4.7.2.
First it looks for a single value 'data2' and it works, then it looks for 'data2' or 'xxx' and it fails.
using System;
using System.Xml.Linq;
using System.Xml.XPath;
public class Program
{
public static void Main()
{
XDocument doc = new XDocument(
new XElement("Root",
new XElement("El", "data1"),
new XElement("El", "data2")
)
);
Console.WriteLine(doc.ToString());
var found = doc.Root.XPathSelectElement("El[text()=('data2')]");
Console.WriteLine("\r\nFound element:");
Console.WriteLine(found.ToString());
var found2 = doc.Root.XPathSelectElement("El[text()=('data2','xxx')]");
Console.WriteLine("\r\nFound element2:");
Console.WriteLine(found2.ToString());
}
}
Output:
<Root>
<El>data1</El>
<El>data2</El>
</Root>
Found element:
<El>data2</El>
Run-time exception (line 23): 'El[text()=('data2','xxx')]' has an invalid token.
I tried 2 online XPath validators with an absolute version of the same XPath expression /*/El[text()=('data2','xxx')]
. It works on https://www.freeformatter.com/xpath-tester.html, but fails with "XPath parse error" on https://www.atatus.com/tools/xpath-validator.
Is El[text()=('data2','xxx')]
a valid XPath expression?
I know that it is possible to replace the expression with El[text()='data2' or text()='xxx']
, but I receive the XPath from outside and want to avoid converting it if possible.
The issue is that your more complex expression uses the XPath 2.0 ,
operator to construct a sequence which is a data structure in XPath 2.0 and later but not in XPath 1.0.
/*/El[text()=('data2','xxx')]
In XPath 2.0, the expression ('data2')
defines a string, which is the same thing as a sequence of one string, and the expression ('data2', 'xxx')
defines a sequence of two strings.
In XPath 1.0, the expression ('data2')
defines a string, and the expression ('data2', 'xxx')
is invalid.
You will either need to upgrade your XPath processor to version 2 or later, or else you will, as you suspected, need to use a different XPath expression for your XPath 1 processor, such as e.g.
/*/El[text()='data2' or text()='xxx']