使用C# XPathNavigator执行XPath if-then-else表达式时为何报无效令牌错误?
这个问题我之前也碰到过!根源在于.NET原生的XPathExpression默认只支持XPath 1.0,而你写的if(//DovizCins = 'YTL') then '1' else '2'是XPath 2.0的条件语法,XPath 1.0根本不认识这种写法,所以才会抛出无效令牌的异常。
接下来给你两种解决方案:
方案一:用XPath 1.0的等效语法实现
XPath 1.0没有直接的三元运算符,但可以通过substring结合布尔值隐式转换来实现相同逻辑。把你的表达式改成下面这样就行:
var expression = "substring('12', 1 + boolean(not(//DovizCins = 'YTL')), 1)"; var nav = doc.CreateNavigator(); XPathExpression xp = XPathExpression.Compile(expression); var value = nav.Evaluate(xp); return value?.ToString() ?? string.Empty;
我给你拆解一下这个表达式的逻辑:
//DovizCins = 'YTL':检查XML中是否存在任意一个DovizCins节点的值等于YTLnot(...):对上面的结果取反,当没有匹配的节点时返回trueboolean(...):把结果转为布尔值,XPath中true会被隐式转成数字1,false转成0substring('12', 起始位置, 1):从字符串'12'里截取1个字符——如果条件成立(找到匹配节点),起始位置是1+0=1,取到'1';如果条件不成立,起始位置是1+1=2,取到'2'
方案二:启用XPath 2.0支持(需第三方库)
如果你一定要用XPath 2.0的原生语法,可以使用开源的Saxon-HE库(这是.NET生态中支持XPath 2.0/3.0最成熟的库)。
步骤如下:
- 通过NuGet安装
Saxon-HE包 - 修改代码为:
using Saxon.Api; using System.Xml.XPath; // 假设你的原始文档是XmlDocument类型的doc Processor processor = new Processor(); DocumentBuilder builder = processor.NewDocumentBuilder(); // 把XmlDocument转成Saxon能处理的XdmNode XdmNode saxonDoc = builder.Build(new XmlNodeWrapper(doc)); // 编译XPath 2.0表达式 XPathCompiler compiler = processor.NewXPathCompiler(); XPathExecutable executable = compiler.Compile("if(//DovizCins = 'YTL') then '1' else '2'"); // 执行并获取结果 XPathSelector selector = executable.Load(); selector.ContextItem = saxonDoc; XdmValue result = selector.Evaluate(); return result.ToString() ?? string.Empty;
一般来说,方案一足够解决你的需求,不需要额外引入第三方依赖。如果后续需要更复杂的XPath语法(比如循环、字符串处理函数等),再考虑方案二。
内容的提问来源于stack exchange,提问作者mesut
相关产品推荐
相关产品推荐

