我有一个XML文件,看起来像这样,我正试图用div包装彼此相邻的"Para_bb"节点。
<Para_a></Para_a>
<Para_a></Para_a>
<Para_bb></Para_bb>
<Para_bb></Para_bb>
<Para_bb></Para_bb>
<Para_bb></Para_bb>
<Para_a></Para_a>
<Para_bb></Para_bb>
<Para_bb></Para_bb>
<Para_a></Para_a>
<Para_a></Para_a>
<Para_bb></Para_bb>
我怎么能把它做成这样?
<p></p>
<p></p>
<div class="blackBox">
<Para_bb></Para_bb>
<Para_bb></Para_bb>
<Para_bb></Para_bb>
<Para_bb></Para_bb>
</div>
<p></p>
<div class="blackBox">
<Para_bb></Para_bb>
<Para_bb></Para_bb>
</div>
<p></p>
<p></p>
<div class="blackBox">
<Para_bb></Para_bb>
</div>
您可以定义如下键:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:key name="group" match="Para_bb[preceding-sibling::*[1][self::Para_bb]]" use="generate-id(preceding-sibling::Para_bb[not(preceding-sibling::*[1][self::Para_bb])][1])"/>
<xsl:template match="Root">
<body>
<xsl:apply-templates/>
</body>
</xsl:template>
<xsl:template match="Para_a">
<p>
<xsl:apply-templates/>
</p>
</xsl:template>
<xsl:template match="Para_bb[preceding-sibling::*[1][self::Para_bb]]"/>
<xsl:template match="Para_bb[not(preceding-sibling::*[1][self::Para_bb])]">
<div class="blackBox">
<xsl:copy-of select=". | key('group', generate-id())"/>
</div>
</xsl:template>
</xsl:stylesheet>
这改变了
<Root>
<Para_a></Para_a>
<Para_a></Para_a>
<Para_bb>1</Para_bb>
<Para_bb>2</Para_bb>
<Para_bb>3</Para_bb>
<Para_bb>4</Para_bb>
<Para_a></Para_a>
<Para_bb>5</Para_bb>
<Para_bb>6</Para_bb>
<Para_a></Para_a>
<Para_a></Para_a>
<Para_bb>7</Para_bb>
</Root>
进入
<body>
<p/>
<p/>
<div class="blackBox">
<Para_bb>1</Para_bb>
<Para_bb>2</Para_bb>
<Para_bb>3</Para_bb>
<Para_bb>4</Para_bb>
</div>
<p/>
<div class="blackBox">
<Para_bb>5</Para_bb>
<Para_bb>6</Para_bb>
</div>
<p/>
<p/>
<div class="blackBox">
<Para_bb>7</Para_bb>
</div>
</body>
XSLT1.0中实现这一点的一种方法是使用一个模板来匹配组中每个Para_bb元素的第一个出现
<xsl:template match="Para_bb[not(preceding-sibling::*[1][self::Para_bb])]">
然后,您将调用一个新模板,并指定一个模式,就在第一个元素上
<p>
<xsl:apply-templates select="." mode="div" />
</p>
然后,在与指定模式匹配的模板中,复制元素并选择下一个同级元素,但前提是它是另一个Para_bb
<xsl:template match="Para_bb" mode="div">
<xsl:call-template name="identity" />
<xsl:apply-templates select="following-sibling::*[1][self::Para_bb]" mode="div"/>
</xsl:template>
(其中被调用的命名模板是标准身份模板)
尝试此XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="Para_bb[not(preceding-sibling::*[1][self::Para_bb])]">
<div class="blackBox">
<xsl:apply-templates select="." mode="div" />
</div>
</xsl:template>
<xsl:template match="Para_bb" />
<xsl:template match="Para_a">
<p>
<xsl:apply-templates select="@*|node()"/>
</p>
</xsl:template>
<xsl:template match="Para_bb" mode="div">
<xsl:call-template name="identity" />
<xsl:apply-templates select="following-sibling::*[1][self::Para_bb]" mode="div"/>
</xsl:template>
<xsl:template match="@*|node()" name="identity">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>