我需要合并两个兄弟姐妹
<table>
<tbody>
<tr>
<td> table data</td>
</tr>
</tbody>
<tbody>
<tr>
<td> table data</td>
</tr>
</tbody>
</table>
预期输出:
<table>
<tbody>
<tr>
<td> table data</td>
</tr>
<tr><td> table data</td>
</tr>
</tbody>
</table>
我的XSLT代码是:
<xsl:template match="/">
<xsl:for-each-group select="*" group-adjacent="boolean(self::tbody)">
<tbody>
<xsl:value-of select="."/>
</tbody>
</xsl:for-each-group>
</xsl:template>
没有给出正确的输出。你能建议
您当前的XSLT
有很多问题- 您的模板与文档节点匹配,在您的情况下,该节点是
table
元素的父,而不是table
元素本身。当您尝试将tbody
元素分组时,您的模板应匹配table
元素 -
xsl:value-of
仅返回节点的文本值。您应该在此处使用xsl:copy-of
(或与身份模板结合使用xsl:apply-templates
)。您还应该选择组中的所有项目,而不仅仅是当前项目。 - 您尚未考虑除
tbody
以外的节点下发生的情况
所以,您的XSLT应该看起来像这样....
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="html" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="table">
<table>
<xsl:for-each-group select="*" group-adjacent="boolean(self::tbody)">
<xsl:choose>
<xsl:when test="current-grouping-key()">
<tbody>
<xsl:apply-templates select="current-group()/*"/>
</tbody>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()" />
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</table>
</xsl:template>
</xsl:stylesheet>
注意,如果您使用的是XSLT 3.0,则可以用以下方式替换身份模板:
<xsl:mode on-no-match="shallow-copy"/>
另一方面,如果您实际上仅使用XSLT 1.0,则需要进行Muenchian分组。这意味着定义这样的键:
<xsl:key name="table" match="table/*" use="boolean(self::tbody)" />
然后,而不是使用xsl:for-each-group
,而是这样做(尽管这将对所有tbody
元素进行分组,而不仅仅是相邻的元素)
<xsl:for-each select="*[generate-id() = generate-id(key('table', boolean(self::tbody))[1])]">
尝试此XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:key name="table" match="table/*" use="boolean(self::tbody)" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="table">
<table>
<xsl:for-each select="*[generate-id() = generate-id(key('table', boolean(self::tbody))[1])]">
<xsl:choose>
<xsl:when test="self::tbody">
<tbody>
<xsl:apply-templates select="key('table', true())/*"/>
</tbody>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="key('table', false())" />
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>
当然,毕竟,在这种情况下,Michael.hor257k的答案要简单得多。(尽管如果您确实陷入XSLT 1.0,那么绝对值得阅读Muenchian分组。
您的示例可以简单地通过:
来处理XSLT 1.0
<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="/table">
<xsl:copy>
<tbody>
<xsl:copy-of select="tbody/*"/>
</tbody>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>