选择以下一些同胞只有
问题描述:
节点我有下面的XML:选择以下一些同胞只有
<root>
<table>Table 1</table>
<foot>1.1</foot>
<foot>2.2</foot>
<p>...</p>
<p>...</p>
<table>Table X</table>
<foot>M.1</foot>
<foot>M.2</foot>
<p>...</p>
<p>...</p>
<table>Table 132</table>
<foot>A.A.E</foot>
<foot>234</foot>
<p>...</p>
<p>...</p>
</root>
我想将其转换为:
<root>
<table>
<text>Table 1</text>
<foot>1.1</foot>
<foot>2.2</foot>
</table>
<p>...</p>
<p>...</p>
<table>
<text>Table X</text>
<foot>M.1</foot>
<foot>M.2</foot>
</table>
<p>...</p>
<p>...</p>
<table>
<text>Table 132</text>
<foot>A.A.E</foot>
<foot>234</foot>
</table>
<p>...</p>
<p>...</p>
</root>
我有以下XSL代码:
<xsl:template match="table">
<xsl:element name="table">
<xsl:element name="text">
<xsl:apply-templates />
</xsl:element>
<xsl:for-each select="following-sibling::foot">
<xsl:element name="foot">
<xsl:apply-templates />
</xsl:element>
</xsl:for-each>
</xsl:element>
其中输出为:
<root>
<table>
<text>Table 1</text>
<foot>1.1</foot>
<foot>2.2</foot>
<foot>M.1</foot>
<foot>M.2</foot>
<foot>A.A.E</foot>
<foot>234</foot>
</table>
<p>...</p>
<p>...</p>
<table>
<text>Table X</text>
<foot>M.1</foot>
<foot>M.2</foot>
<foot>A.A.E</foot>
<foot>234</foot>
</table>
<p>...</p>
<p>...</p>
<table>
<text>Table 132</text>
<foot>A.A.E</foot>
<foot>234</foot>
</table>
<p>...</p>
<p>...</p>
</root>
如何只能选择foot
元件,其立即在关闭table
元素,只要将n
数foot
元素立即table
元以下。任何对此的帮助表示赞赏。
答
最简单的方法是使用XSL键。 (在这个答案的解决方案将在所有的XSLT版本。)
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:key name="foot" match="foot" use="generate-id(preceding-sibling::table[1])" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="table">
<xsl:copy>
<text><xsl:apply-templates select="@*|node()"/></text>
<xsl:copy-of select="key('foot', generate-id())" />
</xsl:copy>
</xsl:template>
<xsl:template match="foot" />
</xsl:transform>
的<xsl:key>
指标使用唯一的ID文档中的所有元素<foot>
(见spec)的前一个<table>
。
<xsl:template match="table">
然后在相同唯一ID的帮助下选择属于每个<table>
的<foot>
元素。
这样做的功能等同物是:
<xsl:template match="table">
<xsl:copy>
<text><xsl:apply-templates select="@*|node()"/></text>
<xsl:copy-of select="following-sibling::foot[
generate-id(preceding-sibling::table[1]) = generate-id(current())
]" />
</xsl:copy>
</xsl:template>
在这种变型中,XSL键将不需要。其结果是在这两种情况下:
<root>
<table>
<text>Table 1</text>
<foot>1.1</foot>
<foot>2.2</foot>
</table>
<p>...</p>
<p>...</p>
<table>
<text>Table X</text>
<foot>M.1</foot>
<foot>M.2</foot>
</table>
<p>...</p>
<p>...</p>
<table>
<text>Table 132</text>
<foot>A.A.E</foot>
<foot>234</foot>
</table>
<p>...</p>
<p>...</p>
</root>
注:
- 不要使用
<xsl:element name="text">
。你可以简单地写<text>
。<xsl:element>
适用于元件名称未预先确定的情况。 - 避免
<xsl:for-each>
。在大多数情况下,使用<xsl:template>
和<xsl:apply-templates>
是优越的。
答
基本上,这是一个分组问题。如果您使用的是XSLT 2.0,则可以利用其内置的分组功能:
<xsl:stylesheet version="2.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="/root">
<xsl:copy>
<xsl:for-each-group select="*" group-starting-with="table">
<table>
<text>
<xsl:value-of select="."/>
</text>
<xsl:copy-of select="current-group()[self::foot]"/>
</table>
<xsl:copy-of select="current-group()[not(self::table or self::foot)]"/>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
您可以使用XSLT 2.0吗? –
对不起。 XSLT 2.0是可以的。我应该指定它。 – Jagath