这是我的 XML:
<?xml version="1.0"?>
<foo>
<a>
first
<b>x</b>
<c>y</c>
</a>
<b>second</b>
<bar>hey</bar>
</foo>
这是我的 XSL:
<?xml version="1.0"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/foo">
<xsl:apply-templates select="bar" />
</xsl:template>
<xsl:template match="bar">
[<xsl:value-of select="preceding-sibling::text()"/>]
</xsl:template>
</xsl:stylesheet>
我期待这个:
[first x y second]
但是,它并没有按预期工作。简而言之,我有兴趣(递归地)连接当前节点的所有兄弟节点的所有文本。
您选择的兄弟节点本身不是文本节点,因此您不能在
text()
轴之后立即使用 preceding-sibiling::
节点测试。相反,您必须选择这些兄弟姐妹的文本后裔。
您可能还想省略纯空白文本,例如
<b>
和 <c>
元素之间的文本:
[<xsl:for-each select="preceding-sibling::*//text()
[normalize-space(.)!='']"> <!-- filter out whitespace-only -->
<xsl:if test="position()>1">
<xsl:text> </xsl:text>
</xsl:if>
<xsl:value-of select="normalize-space(.)"/>
</xsl:for-each>]
如果您希望文本以一个空格分隔,则必须显式插入该文本并使用
normalize-space
函数删除尾随和前导空格。
(XSLT 1.0)
你可以使用这样的东西:
<?xml version="1.0"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="text"/>
<xsl:template match="/foo">
<xsl:apply-templates select="bar" />
</xsl:template>
<xsl:template match="bar">
<xsl:text>[</xsl:text>
<xsl:for-each select="preceding-sibling::*">
<xsl:value-of select="normalize-space(text())"/>
<xsl:value-of select="' '"/>
<xsl:apply-templates select="*" mode ="r"/>
</xsl:for-each>
<xsl:text>]</xsl:text>
</xsl:template>
<xsl:template match="*" mode="r">
<xsl:value-of select="normalize-space(text())"/>
<xsl:value-of select="' '"/>
<xsl:apply-templates select="*" mode="r"/>
</xsl:template>
</xsl:stylesheet>