1

我想知道在 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

4

3 回答 3

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']
于 2012-06-08T19:47:58.943 回答
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="; "/>
于 2012-06-08T22:25:31.307 回答
0

一种方法是对 XML 进行准备性扫描,以将其通过管道传输到更好的结构中。

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

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

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

于 2012-06-08T18:51:03.687 回答