我想在<album>
中添加带逗号和空格的元素,如果它不是父<album>
中的最后一个<recording>
。
我有一个<recording>
的类似模板,它按预期工作。但是,我无法获得<album>
标点符号的第二个模板才能正常工作。
我相信它对现有的第一个模板有所作为......
输入XML
<sample>
<collection>
<recording>
<artist>Radiohead</artist>
<album>OK Computer</album>
</recording>
<recording>
<artist>Tori Amos</artist>
<album>Boys For Pele</album>
<album>To Venus And Back</album>
</recording>
</collection>
示例XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="collection">
<xsl:copy>
<xsl:for-each select="recording">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
<xsl:if test="position()!=last()">
<xsl:element name="x">, </xsl:element>
</xsl:if>
</xsl:for-each>
</xsl:copy>
</xsl:template>
<xsl:template match="recording">
<xsl:copy>
<xsl:for-each select="album">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
<xsl:if test="position()!=last()">
<comma>, </comma>
</xsl:if>
</xsl:for-each>
</xsl:copy>
</xsl:template>
但我的输出是
<sample>
<collection>
<recording>
<artist>Radiohead</artist>
<album>OK Computer</album>
</recording><x>, </x>
<recording>
<artist>Tori Amos</artist>
<album>Boys For Pele</album>
<album>To Venus And Back</album>
</recording>
</collection>
而不是我想要的(注意<x>
,在第二个<album>
中的第一个<recording>
之后
<sample>
<collection>
<recording>
<artist>Radiohead</artist>
<album>OK Computer</album>
</recording><x>, </x>
<recording>
<artist>Tori Amos</artist>
<album>Boys For Pele</album><x>, </x>
<album>To Venus And Back</album>
</recording>
</collection>
</sample>
答案 0 :(得分:1)
将您的第二个(匹配集合)模板更改为
<xsl:template match="collection">
<xsl:copy>
<xsl:for-each select="recording">
<xsl:apply-templates select="."/>
<xsl:if test="position()!=last()">
<xsl:element name="x">, </xsl:element>
</xsl:if>
</xsl:for-each>
</xsl:copy>
</xsl:template>
并将录制模板修改为
<xsl:template match="recording">
<xsl:copy>
<xsl:apply-templates select="(node() | @*) except album"/>
<xsl:for-each select="album">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
<xsl:if test="position()!=last()">
<x>, </x>
</xsl:if>
</xsl:for-each>
</xsl:copy>
</xsl:template>
删除xsl:copy
元素并将其替换为xsl:apply-templates
元素,并将其他录制子项的调用移至录制模板。
最初,您正在循环记录元素并将模板应用于内容节点。因此,您永远不会允许录制模板匹配任何内容。通过将模板应用于当前上下文节点,我们正在使用录制节点本身而不是其内容,以允许录制模板匹配。
此外,在录制模板中,您要添加逗号元素而不是 x 元素。我已将这些更改为上面的 x 元素,因为这是您似乎想要的。
此外,甚至不需要您的第一个xsl:for-each
。如果我们将位置测试从集合模板移动到录制模板,我们可以简化集合模板以避免xsl:for-each
:
<xsl:template match="collection">
<xsl:copy>
<xsl:apply-templates select="recording"/>
</xsl:copy>
</xsl:template>
<xsl:template match="recording">
<xsl:copy>
<xsl:apply-templates select="(node() | @*) except album"/>
<xsl:for-each select="album">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
<xsl:if test="position()!=last()">
<x>, </x>
</xsl:if>
</xsl:for-each>
</xsl:copy>
<xsl:if test="position()!=last()">
<xsl:element name="x">, </xsl:element>
</xsl:if>
</xsl:template>
我们甚至可以对相册做同样的事情,同时删除xsl:for-each
个元素
<xsl:template match="collection">
<xsl:copy>
<xsl:apply-templates select="recording"/>
</xsl:copy>
</xsl:template>
<xsl:template match="recording">
<xsl:copy>
<xsl:apply-templates select="(node() | @*) except album"/>
<xsl:apply-templates select="album"/>
</xsl:copy>
<xsl:if test="position()!=last()">
<xsl:element name="x">, </xsl:element>
</xsl:if>
</xsl:template>
<xsl:template match="album">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
<xsl:if test="position()!=last()">
<x>, </x>
</xsl:if>
</xsl:template>
以上所有内容都将复制完全为空白的元素之间的文本节点,这可能是不可取的。将以下内容添加到样式表的顶部将阻止:
<xsl:strip-space elements="*"/>
本文中的所有示例均使用OP的原始示例以及其他xsl:strip-space
元素和<xsl:output method="xml" indent="yes"/>
使用 Saxon-HE 9.7.0.2J 进行测试,产生的结果相当于OP所需的输出直到缩进( x 元素出现在它们自己的行上)。
答案 1 :(得分:0)
我要做的是创建一个与recording
或album
匹配的模板,如果它不是同类中的第一个,请输出<x>, </x>
。
XML输入
<sample>
<collection>
<recording>
<artist>Radiohead</artist>
<album>OK Computer</album>
</recording>
<recording>
<artist>Tori Amos</artist>
<album>Boys For Pele</album>
<album>To Venus And Back</album>
</recording>
</collection>
</sample>
XSLT 2.0
<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="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="recording|album">
<xsl:variable name="count">
<xsl:number/>
</xsl:variable>
<xsl:if test="$count > 1"><x>, </x></xsl:if>
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
XML输出
<sample>
<collection>
<recording>
<artist>Radiohead</artist>
<album>OK Computer</album>
</recording>
<x>, </x>
<recording>
<artist>Tori Amos</artist>
<album>Boys For Pele</album>
<x>, </x>
<album>To Venus And Back</album>
</recording>
</collection>
</sample>