能否在Schematron规则中获取完整XPath?抽象规则如何输出上下文?
在Schematron规则中获取元素的完整XPath
当然可以实现!Schematron本身没有直接提供获取完整XPath的内置功能,但我们可以通过自定义XPath表达式来生成目标元素的完整路径,完美适配你的抽象规则场景。
实现思路
核心是通过XPath的递归遍历逻辑,从目标元素(也就是你的$element参数)出发,向上遍历所有祖先节点,拼接每个节点的名称和必要的位置标识(避免同名节点导致路径歧义),最后组合成完整的XPath字符串。
具体修改方案
1. 更新抽象规则(带位置标识)
把原来输出元素内容的<sch:value-of>替换成生成带位置标识XPath的表达式,这能精准区分同层级的同名节点:
<sch:rule context="$element"> <sch:report test="true()"> <sch:value-of select="string-join( ancestor-or-self::*/concat( name(), '[', count(preceding-sibling::*[name() = name(current())]) + 1, ']' ), '/' )"/> </sch:report> </sch:rule>
2. 简化版(无位置标识)
如果你的XML结构中不会出现同层级同名节点,也可以用更简洁的版本,只保留节点名称路径:
<sch:rule context="$element"> <sch:report test="true()"> <sch:value-of select="string-join(ancestor-or-self::*/name(), '/')"/> </sch:report> </sch:rule>
3. 处理命名空间(可选)
如果你的XML使用了命名空间,需要在路径中加入前缀,可以调整表达式:
<sch:value-of select="string-join( ancestor-or-self::*/concat( prefix-from-QName(node-name()), ':', local-name(), '[', count(preceding-sibling::*[node-name() = node-name(current())]) + 1, ']' ), '/' )"/>
测试效果
用你提供的XML示例:
<xpath> <to> <search>Content</search> </to> </xpath>
- 带位置标识的规则输出:
xpath[1]/to[1]/search[1] - 简化版规则输出:
xpath/to/search
注意事项
- 位置标识的作用是区分同层级的同名节点,比如如果有多个
<search>节点,路径会明确指向第几个,避免歧义。 - 上述表达式基于XPath 2.0及以上,Schematron通常依赖XSLT 2.0+处理器(比如Saxon),所以大部分场景下都能正常运行。
内容的提问来源于stack exchange,提问作者RJ7
相关产品推荐
相关产品推荐

