我需要合并两个兄弟姐妹
<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>
没有给出正确的输出。你能建议吗
答案 0 :(得分:1)
您当前的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 Grouping。这意味着要定义一个键,如下所示:
<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 Grouping)。
答案 1 :(得分:0)
您的示例可以通过以下方式简单处理:
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>