一、XSLT 解决方案:
我想要的是使用 XSLT 样式表将其类属性包含的所有元素的内容x
放入一个<x>
元素中。所以输出应该是这样的:
1 <x>234</x> 5 <x>6</x> 7 <x>8</x>
这种转变:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kFollowing" match=
"span[contains(concat(' ', @class, ' '),
' x ')
]"
use="generate-id(preceding-sibling::span
[not(contains(concat(' ', @class, ' '),
' x '))
][1]
)
"/>
<xsl:template match=
"span[contains(concat(' ', @class, ' '), ' x ')
and
not(contains(concat(' ', preceding-sibling::span[1]/@class, ' '),
' x '
)
)
]"
>
<x>
<xsl:apply-templates mode="inGroup" select=
"key('kFollowing',
generate-id(preceding-sibling::span [not(contains(concat(' ', @class, ' '), ' x ')
)
][1]
)
)
"/>
</x>
</xsl:template>
<xsl:template match=
"span[contains(concat(' ', @class, ' '), ' x ')
and
contains(concat(' ', preceding-sibling::span[1]/@class, ' '),
' x '
)
]
"/>
</xsl:stylesheet>
当应用于提供的 XML 文档时(包装到单个顶部元素html
中以形成良好的格式):
<html>
<span>1</span>
<span class="x">2</span>
<span class="x y">3</span>
<span class="x">4</span>
<span>5</span>
<span class="x">6</span>
<span>7</span>
<span class="x">8</span>
</html>
产生想要的正确结果:
1<x>234</x>5<x>6</x>7<x>8</x>
然后是“理想”的添加:
或者,理想情况下,
1 <x>2<y>3</y>4</x> 5 <x>6</x> 7 <x>8</x>
但是当我解决了这个问题时,这是一个需要解决的问题。)
只需将此模板添加到上述解决方案中:
<xsl:template mode="inGroup" match=
"span[contains(concat(' ', @class, ' '),
' y '
)
]">
<y><xsl:value-of select="."/></y>
</xsl:template>
当将如此修改的解决方案应用于同一个 XML 文档时,再次产生了(新的)想要的结果:
1<x>2<y>3</y>4</x>5<x>6</x>7<x>8</x>
二、XSLT 2.0 解决方案:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:my="my:my" exclude-result-prefixes="my xs"
>
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/*">
<xsl:for-each-group select="span" group-adjacent=
"contains(concat(' ',@class,' '), ' x ')">
<xsl:sequence select=
"if(current-grouping-key())
then
my:formatGroup(current-group())
else
data(current-group())
"/>
</xsl:for-each-group>
</xsl:template>
<xsl:function name="my:formatGroup" as="node()*">
<xsl:param name="pGroup" as="node()*"/>
<x>
<xsl:apply-templates select="$pGroup"/>
</x>
</xsl:function>
<xsl:template match=
"span[contains(concat(' ',@class, ' '), ' y ')]">
<y><xsl:apply-templates/></y>
</xsl:template>
</xsl:stylesheet>
当这个 XSLT 2.0 转换应用于同一个 XML 文档(上图)时,就会产生想要的“理想”结果:
1<x>2<y>3</y>4</x>5<x>6</x>7<x>8</x>