使用XSLT检测节点及其后续兄弟之间的空间或文本

时间:2012-04-16 19:00:22

标签: xslt

我有一个XML文档,其中包含以下示例摘录:

<p>
    Some text <GlossaryTermRef href="123">term 1</GlossaryTermRef><GlossaryTermRef href="345">term 2</GlossaryTermRef>.
</p>

我使用XSLT使用以下模板将其转换为XHTML:

<xsl:template match="GlossaryTermRef">
    <a href="#{@href}" class="glossary">
        <xsl:apply-templates select="node()|text()"/>
    </a>
</xsl:template>

这很有效,但是我需要在两个GlossaryTermRef元素之间插入一个空格,如果它们彼此相邻?

有没有办法检测当前节点和后续兄弟之间是否有空格或文本?我不能总是插入空格GlossaryTermRef项,因为它后面可能跟一个标点符号。

3 个答案:

答案 0 :(得分:3)

我自己设法解决这个问题,修改模板如下:

<xsl:template match="GlossaryTermRef">
    <a href="#{@href}" class="glossary">
        <xsl:apply-templates select="node()|text()"/>
    </a>
    <xsl:if test="following-sibling::node()[1][self::GlossaryTermRef]">
        <xsl:text> </xsl:text>
    </xsl:if>
</xsl:template>

有人可以建议更好的方法,或者看到此解决方案有任何问题吗?

答案 1 :(得分:2)

首先,“node()| text()”是“node()”的longwinded等价物。也许你的意思是“* | node()”,它会选择元素和文本子项而不是注释或PI。

您的解决方案可能与任何解决方案一样好。另一种方法是使用分组:

<xsl:for-each-group select="node()" group-adjacent="boolean(self::GlossaryTermRef)">
  <xsl:choose>
    <xsl:when test="current-grouping-key()">
      <xsl:for-each select="current-group()">
        <xsl:if test="position() gt 1"><xsl:text> </xsl:text></xsl:if>
        <xsl:apply-templates select="."/>
      </xsl:for-each>
    </xsl:when>
    <xsl:otherwise>
     <xsl:apply-templates select="current-group()"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:for-each-group>

Naah,这根本不是很好。

我的下一次尝试是使用兄弟递归(其中父对象在第一个子节点上应用模板,并且每个子节点对紧接着的兄弟节点都应用模板),但我不认为这将是一个改善。

答案 2 :(得分:0)

这个怎么样?你觉得怎么样?

<xsl:template match="GlossaryTermRef">
<a href="#{@href}" class="glossary">
<xsl:apply-templates select="node()|text()"/>
</a>
</xsl:template>