[英]xslt 1.0- Using xslt 1.0 how can I make the xslt work for multiple document elements
[英]Merge specific elements but keep document order using XSLT 1.0
给定以下文件:
<doc>
<a>a</a>
<b>1</b>
<b>2</b>
<b>3</b>
<c>c</c>
</doc>
我希望将其转换为:
<doc>
<a>a</a>
<b>1,2,3</b>
<c>c</c>
</doc>
到目前为止,我所拥有的(大部分来自SO上的另一篇文章):
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<xsl:template match="doc">
<xsl:copy>
<xsl:apply-templates select="*[not(self::b)]"/>
<b><xsl:apply-templates select="b/text()"/></b>
</xsl:copy>
</xsl:template>
<xsl:template match="b/text()">
<xsl:if test="position() > 1">,</xsl:if>
<xsl:value-of select="."/>
</xsl:template>
</xsl:stylesheet>
这将产生以下结果:
<doc><a>a</a><c>c</c><b>1,2,3</b></doc>
但是,我一直在努力寻找一种可以保持文档顺序完整的解决方案。 任何<b>
元素运行都应替换为包含原始元素文本(以逗号分隔的列表)的单个元素。 其他元素不应重新排序。
为什么不简单地做:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/doc">
<xsl:copy>
<xsl:copy-of select="a"/>
<b>
<xsl:for-each select="b">
<xsl:value-of select="."/>
<xsl:if test="position() !=last()">,</xsl:if>
</xsl:for-each>
</b>
<xsl:copy-of select="c"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
假设您知道传入XML的结构,并且可以分别枚举b
之前和之后的元素。 否则,您将必须执行以下操作:
<xsl:template match="/doc">
<xsl:copy>
<xsl:apply-templates select="*[not(self::b or preceding-sibling::b)]"/>
<b>
<xsl:for-each select="b">
<xsl:value-of select="."/>
<xsl:if test="position() !=last()">,</xsl:if>
</xsl:for-each>
</b>
<xsl:apply-templates select="*[not(self::b or following-sibling::b)]"/>
</xsl:copy>
</xsl:template>
您可以在其他模式下使用同级递归:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<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="b[not(preceding-sibling::*[1][self::b])]">
<xsl:copy>
<xsl:apply-templates select="." mode="merge"/>
</xsl:copy>
</xsl:template>
<xsl:template match="b[preceding-sibling::*[1][self::b]]"/>
<xsl:template match="b" mode="merge">
<xsl:value-of select="."/>
<xsl:variable name="next" select="following-sibling::*[1][self::b]"/>
<xsl:if test="$next">
<xsl:text>,</xsl:text>
<xsl:apply-templates select="$next" mode="merge"/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.