如何使用XSLT将所有这些XML标签连接成同名的较大标签?
我这个转换XML:
如何使用XSLT将所有这些XML标签连接成同名的较大标签?
<root>
<contrib contrib-type="author">
<name>
<last-name>Kottke</last-name>
<first-name>Leo</first-name>
</name>
</contrib>
<contrib contrib-type="author">
<name>
<last-name>McKee</last-name>
<first-name>Andy</first-name>
</name>
</contrib>
<contrib contrib-type="author">
<name>
<last-name>Hedges</last-name>
<first-name>Michael</first-name>
</name>
</contrib>
</root>
...这个XSL:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes" method="xml"/>
<xsl:strip-space elements="*"/>
<!-- identity rule -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<!-- Authors -->
<xsl:template match="contrib[@contrib-type='author']">
<Authors>
<xsl:if test="position() != last()">
<xsl:value-of select = "concat(name/first-name, ' ', name/last-name, ', ')" />
</xsl:if>
<xsl:if test="position() = last()">
<xsl:value-of select = "concat('and ', name/first-name, ' ', name/last-name, '.')" />
</xsl:if>
</Authors>
</xsl:template>
</xsl:stylesheet>
...并正在此输出:
<root>
<Authors>Leo Kottke, </Authors>
<Authors>Andy McKee, </Authors>
<Authors>and Michael Hedges.</Authors>
</root>
然而,我想所有的
Author
标签连接成一个更大的 Author
标签,使输出将类似于此:
<root>
<Authors>Leo Kottke, Andy McKee, and Michael Hedges.</Authors>
</root>
待办事项我需要以某种方式使用 for-each
循环?
否xsl:for-each
需要。只需从contrib
比赛添加模板/*
(或/root
)和删除Authors
:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes" method="xml"/>
<xsl:strip-space elements="*"/>
<!-- identity rule -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/root">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<Authors>
<xsl:apply-templates select="contrib[@contrib-type='author']"/>
</Authors>
</xsl:copy>
</xsl:template>
<!-- Authors -->
<xsl:template match="contrib[@contrib-type='author']">
<xsl:if test="position() != last()">
<xsl:value-of select = "concat(name/first-name, ' ', name/last-name, ', ')" />
</xsl:if>
<xsl:if test="position() = last()">
<xsl:value-of select = "concat('and ', name/first-name, ' ', name/last-name, '.')" />
</xsl:if>
</xsl:template>
</xsl:stylesheet>
简单的东西一点点
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/root">
<xsl:variable name="authors">
<xsl:for-each select="contrib/name">
<xsl:text>, </xsl:text>
<xsl:value-of select="first-name"/>
<xsl:text> </xsl:text>
<xsl:value-of select="last-name"/>
</xsl:for-each>
</xsl:variable>
<root>
<authors><xsl:value-of select="substring($authors,3)"/></authors>
</root>
</xsl:template>
</xsl:stylesheet>
感谢@Jim的帮助!然而,名字的数量是未知的大小(不总是只有3),并且'
我的答案限制3次发生。至于变化的深度,只需将选择改为'.// contrib/name'。 – 2012-08-08 20:28:27
对不起,我误解了'
感谢@DevNull的帮助!然而,除了'Authors'之外,我还有许多其他这样的标签进行转换,并且将这些代码附加到其余的部分是相冲突的,并且导致* only *'Authors'输出... – 2012-08-08 20:07:12
啊,所以我改变了' '到'',现在它工作正常。我并不确定我在那里弄清楚了什么,但是似乎将Authors转换应用于所有属性会使所有不符合条件的节点都为零。再次感谢@DevNull! –
2012-08-08 20:28:04
很好的答案,+1。 – ABach 2012-08-09 00:32:16