经过一天的XSLT研究,我承认失败了!
这是我的意见:
<div class="a" >
<div class="b">b1</div>
<div class="c">b1c1</div>
<div class="d">b1d1</div>
<div class="d">b1d2</div>
<div class="b">b2</div>
<div class="c">b2c1</div>
<div class="d">b2d1</div>
<div class="d">b2d2</div>
<div class="d">b2d3</div>
<div class="b">b3</div>
<div class="c">b3c1</div>
<div class="d">b3d1</div>
</div>
这是我想要的输出:
<div class="a" >
<div class="b">b1
<div class="c">b1c1</div>
<div class="d">b1d1</div>
<div class="d">b1d2</div>
</div>
<div class="b">b2
<div class="c">b2c1</div>
<div class="d">b2d1</div>
<div class="d">b2d2</div>
<div class="d">b2d3</div>
</div>
<div class="b">b3
<div class="c">b3c1</div>
<div class="d">b3d1</div>
</div>
</div>
这是我正在使用的xslt:
<?xml version="1.0"?>
<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="*"/>
<!-- Identity template, copies everything as is -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- Override for target element -->
<xsl:template match="div[@class='a']">
<!-- Copy the element -->
<xsl:copy>
<!-- And everything inside it -->
<xsl:copy-of select="@*|node()"/>
<!-- Move nodes -->
<xsl:apply-templates select="div[@class='c']"/>
<xsl:apply-templates select="div[@class='d']"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
但它给了我错误的输出:
<div class="a">
<div class="b">b1</div>
<div class="c">b1c1</div>
<div class="d">b1d1</div>
<div class="d">b1d2</div>
<div class="b">b2</div>
<div class="c">b2c1</div>
<div class="d">b2d1</div>
<div class="d">b2d2</div>
<div class="d">b2d3</div>
<div class="b">b3</div>
<div class="c">b3c1</div>
<div class="d">b3d1</div>
<div class="c">b1c1</div>
<div class="c">b2c1</div>
<div class="c">b3c1</div>
<div class="d">b1d1</div>
<div class="d">b1d2</div>
<div class="d">b2d1</div>
<div class="d">b2d2</div>
<div class="d">b2d3</div>
<div class="d">b3d1</div>
</div>
我理解为什么它会给我这个输出,但我找不到修改它并获得正确输出的方法。
提前谢谢。
PullingHair
答案 0 :(得分:1)
看起来你正在通过前面的第一个“b”类对“c”和“d”类进行分组。要在XSLT 1.0中执行此操作,您可以定义一个键来捕获此分组。
<xsl:key name="b" match="div[@class!='b']" use="generate-id(preceding-sibling::div[@class='b'][1])" />
因此,不是选择模板中与“a”类匹配的所有子节点,而只选择“b”类
<xsl:apply-templates select="div[@class='b']" />
然后,在匹配“b”类的模板中,您可以使用该键来获取关联的“c”和“d”元素
<xsl:template match="div[@class='b']">
<xsl:copy>
<xsl:copy-of select="@*" />
<xsl:apply-templates select="key('b', generate-id())" />
</xsl:copy>
</xsl:template>
试试这个XSLT
<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="b" match="div[@class!='b']" use="generate-id(preceding-sibling::div[@class='b'][1])" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="div[@class='a']">
<xsl:copy>
<xsl:apply-templates select="@*|div[@class='b']" />
</xsl:copy>
</xsl:template>
<xsl:template match="div[@class='b']">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
<xsl:apply-templates select="key('b', generate-id())" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
在XSLT 2.0中,您可以使用xsl:for-each-group
代替
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="div[@class='a']">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:for-each-group select="div" group-starting-with="div[@class='b']">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
<xsl:apply-templates select="current-group()[position() > 1]" />
</xsl:copy>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>