计算之前的节点 returns 个意外结果
Counting previous nodes returns unexpected results
我想使用逐项列表而不是硬中断,请参见示例:
<para>line1<?linebreak?>
line2<?linebreak?>
line3</para>
但是,我在递归模板中遇到了奇怪的行为,导致无法正确处理第二行。我已经创建了简化的测试用例——不再是递归的。如果以这种方式使用 count(preceding::processing-instruction('linebreak')) = 0
表达式,则不会返回任何内容,但我希望返回第二行。
<line>line1</line><node>
line2<?linebreak?>
line3</node>
line2
<node>
元素在这里用于调试目的。它确认我处理了预期的数据。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:template match="para[processing-instruction('linebreak')]">
<xsl:call-template name="getLine">
<xsl:with-param name="node" select="./node()"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="getLine">
<xsl:param name="node"/>
<line>
<xsl:copy-of
select="$node/self::processing-instruction('linebreak')[not(preceding::processing-instruction('linebreak'))]/preceding::node()"
/>
</line>
<xsl:call-template name="getSecondLine">
<xsl:with-param name="node"
select="$node/self::processing-instruction('linebreak')[not(preceding::processing-instruction('linebreak'))]/following::node()"
/>
</xsl:call-template>
</xsl:template>
<xsl:template name="getSecondLine">
<xsl:param name="node"/>
<node>
<xsl:copy-of select="$node"/>
</node>
<xsl:copy-of
select="$node/self::processing-instruction('linebreak')[count(preceding::processing-instruction('linebreak')) = 0]/preceding::node()"
/>
</xsl:template>
</xsl:stylesheet>
在 Saxon HE/EE 9.6.0.7 中测试(在 Oxygen XML Editor 18 中)。
第一个换行符的处理工作正常:
<line>
<xsl:copy-of
select="$node/self::processing-instruction('linebreak')
[not(preceding::processing-instruction('linebreak'))]
/preceding::node()"/>
</line>
尽管仅针对此示例;在更复杂的数据上,您会得到错误的结果,因为您应该使用 preceding-sibling
轴而不是 preceding
轴。
但是代码可以大大简化,我会把 select
表达式写成:
select="$node[self::processing-instruction('linebreak')][1]
/preceding-sibling::node()"
第二个换行符的处理看起来很混乱。您正在传递参数
$node/self::processing-instruction('linebreak')
[not(preceding::processing-instruction('linebreak'))]
/following::node()"
有效
select="$node[self::processing-instruction('linebreak')][1]
/following-sibling::node()"
选择三个节点
line2<?linebreak?>line3
(加上空格),您在 <node>
元素中输出,生成
<node>line2<?linebreak?>line3</node>
(再次忽略空格)
然后你做
select="$node/self::processing-instruction('linebreak')
[count(preceding::processing-instruction('linebreak'))=0]
/preceding::node()"
这里$node/self::processing-instruction('linebreak')
选择这三个节点中的第二个,也就是第二条换行处理指令。前面(或前面的兄弟)处理指令的计数是 1,因为你正在处理的是第二个。
我不太确定您在想什么,但我怀疑您的错误是将 "preceding" 和 "following" 视为相对于节点在 [= 中的位置进行选择22=] 序列,而不是相对于原始源代码树中的其他节点。我建议阅读 XPath 参考书中描述各种轴的部分。
我想使用逐项列表而不是硬中断,请参见示例:
<para>line1<?linebreak?>
line2<?linebreak?>
line3</para>
但是,我在递归模板中遇到了奇怪的行为,导致无法正确处理第二行。我已经创建了简化的测试用例——不再是递归的。如果以这种方式使用 count(preceding::processing-instruction('linebreak')) = 0
表达式,则不会返回任何内容,但我希望返回第二行。
<line>line1</line><node>
line2<?linebreak?>
line3</node>
line2
<node>
元素在这里用于调试目的。它确认我处理了预期的数据。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:template match="para[processing-instruction('linebreak')]">
<xsl:call-template name="getLine">
<xsl:with-param name="node" select="./node()"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="getLine">
<xsl:param name="node"/>
<line>
<xsl:copy-of
select="$node/self::processing-instruction('linebreak')[not(preceding::processing-instruction('linebreak'))]/preceding::node()"
/>
</line>
<xsl:call-template name="getSecondLine">
<xsl:with-param name="node"
select="$node/self::processing-instruction('linebreak')[not(preceding::processing-instruction('linebreak'))]/following::node()"
/>
</xsl:call-template>
</xsl:template>
<xsl:template name="getSecondLine">
<xsl:param name="node"/>
<node>
<xsl:copy-of select="$node"/>
</node>
<xsl:copy-of
select="$node/self::processing-instruction('linebreak')[count(preceding::processing-instruction('linebreak')) = 0]/preceding::node()"
/>
</xsl:template>
</xsl:stylesheet>
在 Saxon HE/EE 9.6.0.7 中测试(在 Oxygen XML Editor 18 中)。
第一个换行符的处理工作正常:
<line>
<xsl:copy-of
select="$node/self::processing-instruction('linebreak')
[not(preceding::processing-instruction('linebreak'))]
/preceding::node()"/>
</line>
尽管仅针对此示例;在更复杂的数据上,您会得到错误的结果,因为您应该使用 preceding-sibling
轴而不是 preceding
轴。
但是代码可以大大简化,我会把 select
表达式写成:
select="$node[self::processing-instruction('linebreak')][1]
/preceding-sibling::node()"
第二个换行符的处理看起来很混乱。您正在传递参数
$node/self::processing-instruction('linebreak')
[not(preceding::processing-instruction('linebreak'))]
/following::node()"
有效
select="$node[self::processing-instruction('linebreak')][1]
/following-sibling::node()"
选择三个节点
line2<?linebreak?>line3
(加上空格),您在 <node>
元素中输出,生成
<node>line2<?linebreak?>line3</node>
(再次忽略空格)
然后你做
select="$node/self::processing-instruction('linebreak')
[count(preceding::processing-instruction('linebreak'))=0]
/preceding::node()"
这里$node/self::processing-instruction('linebreak')
选择这三个节点中的第二个,也就是第二条换行处理指令。前面(或前面的兄弟)处理指令的计数是 1,因为你正在处理的是第二个。
我不太确定您在想什么,但我怀疑您的错误是将 "preceding" 和 "following" 视为相对于节点在 [= 中的位置进行选择22=] 序列,而不是相对于原始源代码树中的其他节点。我建议阅读 XPath 参考书中描述各种轴的部分。