我和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>
不是唯一的子项。 最佳答案
您可以定义一个键,以根据每个场景中最近的pb
元素将每个场景中的非pb
元素收集到组中。
<xsl:key name="elByPb" match="*[not(self::pb)]"
use="concat(generate-id(..), '|',
generate-id(preceding-sibling::pb[1]))" />
现在要处理场景,请为第一个
line-group
之前的元素创建一个pb
,然后为每个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|"
关于xml - XSLT将线性结构转换为非线性,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24127128/