分隔xslt的输出(在非平凡的情况下)

时间:2012-06-08 18:22:52

标签: xml xslt delimiter

我想知道在xsl转换中分隔xml输出的最佳方法。 “position()!= last()”并不总是有效,因为它会对输入做出假设。

这个玩具示例展示了:

  <xsl:template match="/">
    <html>
      <body>
        <xsl:for-each select="//cd">
          <xsl:if test="title !='Unchain my heart'">
            <xsl:value-of select="title" />
            <xsl:if test="position() != last()">
              <xsl:text>; </xsl:text>  <!-- sometimes the delimiter will end if last element is a duplicate; -->
            </xsl:if>
          </xsl:if>
        </xsl:for-each>
      </body>
    </html>
  </xsl:template>

将导致

... Pavarotti Gala Concert; The dock of the bay; Picture book; Red; 

请注意落后的分号。

有什么想法吗?

(此示例中的xml数据http://www.w3schools.com/xsl/tryxslt.asp?xmlfile=cdcatalog&xsltfile=cdcatalog

3 个答案:

答案 0 :(得分:2)

您可以做的一件事是使用following::轴查看您是否在最后一个标题中。

示例:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="/">
        <html>
            <body>
                <xsl:apply-templates select="catalog/cd/title[. != 'Unchain my heart']"/>
            </body>
        </html>
    </xsl:template>

    <xsl:template match="title">
        <xsl:value-of select="."/>
        <xsl:if test="following::cd/title[. != 'Unchain my heart']">
            <xsl:text>; </xsl:text>
        </xsl:if>
    </xsl:template>

</xsl:stylesheet>

如果你想保留它,你仍然可以在xsl:for-each中使用它。

此外,如果您使用的是XSLT 2.0,则可以使用separator上的xsl:value-of属性。

示例:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="/">
        <html>
            <body>
                <xsl:value-of select="catalog/cd/title[. != 'Unchain my heart']" separator="; "/>
            </body>
        </html>
    </xsl:template>

</xsl:stylesheet>

另外,如果你试图删除“Unchain my heart”标题,请尝试将其放入谓词而不是xsl:if(这没有错,只是效率较低而且需要更多代码才能执行同样的事情)。

示例:

//cd[title != 'Unchain my heart']

title[. != 'Unchain my heart']

答案 1 :(得分:2)

将其更改为:

    <xsl:for-each select="//cd[title !='Unchain my heart']">
        <xsl:value-of select="title" />
        <xsl:if test="position() != last()">
          <xsl:text>; </xsl:text>
        </xsl:if>
    </xsl:for-each>

或在XSLT 2.0中,

<xsl:value-of select="//cd/title[. !='Unchain my heart']" separator="; "/>

答案 2 :(得分:0)

一种方法是对XML进行预备扫描,以将其转换为更好的结构。

这里的概念是您创建自己的XML,然后将其评估为节点集(与源XML分开)。这是通过EXSLT的node-set()方法'

实现的

我刚刚敲了这个XMLPlayground会话 - 希望它有所帮助。如您所见,没有尾随冒号。

http://www.xmlplayground.com/054Mj7