我有一个包含元素的 XML a
,其属性@ref
包含至少一个指针,并且可以包含任意数量的由空格分隔的指针:<a ref="#p1 #p2"/>
. 在 XSLT 1.0 样式表中,我需要将模板应用于文档中所有且仅b
引用的那些元素a/@ref
。
所以,我认为这个想法是定义一个<xsl:key name="k1" match="a" use="my:refs(@ref)"/>
函数,将 的值@ref
拆分为其组成部分,然后有一个<xsl:template match="b[key('k1', @xml:id)]"/>
. 如果我正确解释规格:
use 属性是指定键值的表达式;对于与模式匹配的每个节点,都会对表达式进行一次评估。如果结果是一个节点集,那么对于节点集中的每个节点,与模式匹配的节点都有一个指定名称的键,其值为节点集中节点的字符串值;
我需要提供一个函数来@use
返回由(减去前导'#')node-set
的值组成的字符串。a/@ref
我的解决方案是定义<xsl:key name="k1" match="a" use="str:tokenize(@ref, '# ')/>
和<xsl:template match="a[key('k1', @xml:id)">
.
当我使用 Xalan 作为处理器时,这给了我想要的结果。但是,Saxon 9.6.0.7 抱怨循环键定义。
现在我有点困惑:我的解决方案是否有效?如果是这样,撒克逊人为什么抱怨?还有其他/更好的(/真实的)解决方案吗?[看评论]。
编辑:附加问题:如何在 XSLT 2.0 中获得结果?仅仅tokenize(@ref, '#')
在键定义中使用是不够的,因为有空格,而对于normalize-space(tokenize(@ref, '#'))
Saxon 会给出相同的错误 XTDE0640。
谢谢,达里奥
示例 XML:
<root>
<b xml:id="#p1">P1</b>
<b xml:id="#p2">P2</b>
<b xml:id="#pn">Pn</b>
<a ref="#p2" />
<a ref="#p1 #pn" />
</root>
输出应该是
P1
P2
Pn
(不需要特别的顺序)。