我有一个包含元素a
的XML,其属性@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属性是指定键值的表达式;该 对于与模式匹配的每个节点,将对expression进行一次计算。如果 结果是一个节点集,然后对于节点集中的每个节点,该节点 匹配模式有一个指定名称的键,其值为 节点集中节点的字符串值;
我需要向@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, '#'))
撒克逊将给出相同的错误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
(无需特定订单)。