我已经和XML
<main>
<div type='scene'>
<l>l1</l>
<sp>A speach</sp>
<l>l2</l>
<pb />
<l>l3</l>
<l>14</l>
</div>
</main>我的任务是将它转换为
<div class="line-group">
<l>l1</l>
<div class="speach">
A speach
</div>
<l>l2</l>
</div>
<div class="line-group">
<l>l3</l>
<l>l4</l>
</div>我知道可能有任意数量的<pb />,只有在没有连续的<pb />和在开始和结束时都没有<pb />的情况下,才能正确地实现此输出。
但是,我们可以使用这种方法将所有<pb />替换为</div><div class="line-group">,并在开始时使用<div class="line-group">,在结束时使用</div>。
我如何在XSLT中做到这一点?
我已经为所有其他标签提供了模板,我在示例中使用了sp来显示<l>不是唯一的子项。
发布于 2014-06-10 03:27:29
可以定义一个关键点,以便根据每个场景中最近的前一个pb元素的pb元素将这些非pb元素聚集到组中。
<xsl:key name="elByPb" match="*[not(self::pb)]"
use="concat(generate-id(..), '|',
generate-id(preceding-sibling::pb[1]))" />现在,要处理场景,您需要在第一个pb之前为元素创建一个line-group,然后在每个pb之后创建另一个元素
<xsl:template match="div[@type='scene']">
<xsl:copy>
<xsl:copy-of select="@*" />
<xsl:call-template name="line-group">
<xsl:with-param name="groupKey" select="concat(generate-id(), '|')" />
</xsl:call-template>
<xsl:apply-templates select="pb" />
</xsl:copy>
</xsl:template>
<xsl:template match="pb" name="line-group">
<xsl:param name="groupKey"
select="concat(generate-id(..), '|', generate-id())" />
<div class="line-group">
<xsl:apply-templates select="key('elByPb', $groupKey)" />
</div>
</xsl:template>在这里,我利用了这样一个事实,即空节点集的generate-id (根据定义)是空字符串,因此节中第一个pb之前的元素将在"id-of-parent|"上设置键值
发布于 2014-06-10 03:39:46
<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="div">
<xsl:for-each-group select="*" group-ending-with="pb">
<div class="line-group">
<xsl:apply-templates select="current-group()"/>
</div>
</xsl:for-each-group>
</xsl:template>
<xsl:template match="pb"></xsl:template>
<xsl:template match="l">
<xsl:copy>
<xsl:apply-templates select="@* | node()" />
</xsl:copy>
</xsl:template>
发布于 2014-06-10 04:31:59
可以使用disable-output-escape=‘yes’,但这不是一种优雅的方法。
<xsl:stylesheet version="1.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="div">
<root>
<xsl:text disable-output-escaping="yes"><div class="line-group"></xsl:text>
<xsl:apply-templates/>
<xsl:text disable-output-escaping="yes"></div></xsl:text>
</root>
</xsl:template>
<xsl:template match="pb">
<xsl:text disable-output-escaping="yes"></div></xsl:text> <xsl:text disable-output-escaping="yes"><div class="line-group"></xsl:text>
</xsl:template>
<xsl:template match="l">
<xsl:copy>
<xsl:apply-templates select="@* | node()" />
</xsl:copy>
</xsl:template>
https://stackoverflow.com/questions/24127128
复制相似问题