我需要将混合的"标签和文本"XML拆分为两个"纯"部分:一部分只有数据标签(任何不是<b>
、<i>
或<sup>
格式标签的标签);另一部分只有"文本"(//text()
和格式标签)。
输入示例:
<root>
Nonono <i>nonon</i> <data1/> <b>nono</b>
<data2>nononono <i>no</i>nononon</data2>.
<data3>blablabla<data4/></data3>
</root>
输出示例:
<root>
<myTags>
<data1/>
<data2>nononono <i>no</i>nononon</data2>
<data3>blablabla<data4/></data3>
</myTags>
<myText>
Nonono <i>nonon</i> <b>nono</b>
nononono <i>no</i>nononon . blablabla
</myText>
</root>
使用一个更现实的输入进行编辑,
Nonono <i>nonon</i> <data1/> <b>nono <data66/> </b>
必须输出
<data1/><data66/>
这种情况表达了一个稍微复杂的问题。它可以发生在任何级别。
在我的 XSLT 的xsl:transform
核心下方(那行不通!
<xsl:template match="/">
<root>
<myTags><xsl:call-template name="copyOnlyTags"/></myTags>
<myText><xsl:call-template name="copyOnlyTextAndFormat"/></myText>
</root>
</xsl:template>
<!-- LIB -->
<xsl:template name="copyOnlyTags">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:for-each select="node()[not(self::text())]">
<xsl:choose>
<xsl:when test="count(*)=0"> <!-- terminal -->
<xsl:copy-of select="."/>
</xsl:when>
<xsl:otherwise> <!-- recurrence -->
<xsl:call-template name="copyOnlyTags"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:copy>
</xsl:template>
<xsl:template name="copyOnlyTextAndFormat">
<xsl:for-each select="node()">
<xsl:choose>
<xsl:when test="self::text()">
<xsl:value-of select="."/>
</xsl:when>
<xsl:when test="name()='i' or name()='sup' or name()='sub' or name()='b'">
<xsl:copy-of select="."/><!-- suppose only text into -->
</xsl:when>
<xsl:otherwise> <!-- recurrence -->
<xsl:call-template name="copyOnlyTextAndFormat"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>
XSLT 不是告诉处理器你想要它做什么,而是说明你想要得到什么结果。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" />
<xsl:template match="root">
<xsl:copy>
<myTags>
<xsl:apply-templates select="node()" mode="data" />
</myTags>
<myText>
<xsl:apply-templates select="node()" mode="format" />
</myText>
</xsl:copy>
</xsl:template>
<!-- unless stated otherwise, we want no output -->
<xsl:template match="node()" mode="data" />
<xsl:template match="node()" mode="format" />
<!-- DATA MODE: data elements should be copied -->
<xsl:template match="*[starts-with(name(), 'data')]" mode="data">
<xsl:copy-of select="." />
</xsl:template>
<!-- DATA MODE: format elements should be passed silently -->
<xsl:template match="*[not(starts-with(name(), 'data'))]" mode="data">
<xsl:apply-templates select="node()" mode="data" />
</xsl:template>
<!-- FORMAT MODE: format elements and text nodes should be copied -->
<xsl:template match="text() | *[not(starts-with(name(), 'data'))]" mode="format">
<xsl:copy>
<xsl:apply-templates select="node()" mode="format" />
</xsl:copy>
</xsl:template>
<!-- FORMAT MODE: data elements should be passed silently -->
<xsl:template match="*[starts-with(name(), 'data')]" mode="format">
<xsl:apply-templates select="node()" mode="format" />
</xsl:template>
</xsl:stylesheet>
为
<root>
Nonono <i>nonon</i> <data1/> <b>nono</b>
<data2>nononono <i>no</i>nononon</data2>.
<data3>blablabla<data4/></data3>
</root>
输出为
<root>
<myTags>
<data1/>
<data2>nononono <i>no</i>nononon</data2>
<data3>blablabla<data4/></data3>
</myTags>
<myText>
Nonono <i>nonon</i> <b>nono</b>
nononono <i>no</i>nononon.
blablabla
</myText>
</root>
为
<root>
Nonono <i>nonon</i> <data1/> <b>nono <data66/> </b>
</root>
它产生
<root>
<myTags>
<data1/>
<data66/>
</myTags>
<myText>
Nonono <i>nonon</i> <b>nono </b>
</myText>
</root>