我有以下XML:
<entry>
<form type="variant">
<form type="hyperlemma">
<orth>wordA</orth>
</form>
<orth>wordB</orth>
<gramGrp>
<gram>vb</gram>
<gram>inf</gram>
</gramGrp>
<cit>
<form type="lemma">
<orth>wordC</orth>
</form>
</cit>
<form type="graphical_variant">
<form type="hyperlemma">
<orth>wordD</orth>
</form>
<orth>wordE</orth>
<cit>
<orth>∅</orth>
</cit>
</form>
</form>
</entry>
<form type="variant">
的子节点 - 即<orth>wordB</orth>
和<cit>
- 应该在第一个<form type="graphical_variant">
之前新添加。{/ p >
所需的输出是
<entry>
<form type="variant">
<form type="hyperlemma">
<orth>wordA</orth>
</form>
<gramGrp>
<gram>vb</gram>
<gram>inf</gram>
</gramGrp>
<form type="graphical_variant">
<orth>wordB</orth>
<cit>
<form type="lemma">
<orth>wordC</orth>
</form>
</cit>
</form>
<form type="graphical_variant">
<form type="hyperlemma">
<orth>wordD</orth>
</form>
<orth>wordE</orth>
<cit>
<orth>∅</orth>
</cit>
</form>
</form>
</entry>
应用此XSLT,模板1和2正在进行复制
<!--TEMPLATE1-->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<!--TEMPLATE2-->
<xsl:template match="form[@type='graphical_variant']">
<form type="graphical_variant">
<xsl:apply-templates select="../orth" />
<!--in case there are several <cit> elements-->
<xsl:for-each select="../cit">
<xsl:apply-templates select="." />
</xsl:for-each>
</form>
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<!--TEMPLATE3-->
<xsl:template match="form[@type='variant']/cit" />
<!--TEMPLATE4-->
<xsl:template match="form[@type='variant']/orth"/>
但是一旦我尝试使用模板3和4从<form type="variant">
删除这些复制的元素,它们也会从新创建的元素<form type="graphical_variant">
中删除。
这可能是一个愚蠢的问题,但为什么会这样呢?通过引用form[@type='variant']
(template3),我认为<cit>
只会被删除。如果有人能解释我做错了什么,我会很高兴 - 甚至可能提供解决方案!
我忘了提到:它是XSLT 2.0。
答案 0 :(得分:2)
您的方法存在问题:当您这样做时:
<xsl:apply-templates select="../orth" />
您正在将模板应用于作为当前节点的兄弟节点的orth
元素 - 即<form type="variant">
元素的子元素。只有匹配这些orth
元素的模板 - 它是您的TEMPLATE4,并且该模板为空。
同样的事情发生在你的:
<xsl:for-each select="../cit">
<xsl:apply-templates select="." />
</xsl:for-each>
这只是一种尴尬的说法:
<xsl:apply-templates select="../cit" />
将空TEMPLATE3应用于这些节点。
如何解决此问题:
有三种方法可以解决这个问题:
而不是应用模板,复制节点到您想要的位置 它们:
<!--TEMPLATE1-->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<!--TEMPLATE2-->
<xsl:template match="form[@type='graphical_variant']">
<form type="graphical_variant">
<xsl:copy-of select="../orth" />
<xsl:copy-of select="../cit" />
</form>
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<!--TEMPLATE3-->
<xsl:template match="form[@type='variant']/cit" />
<!--TEMPLATE4-->
<xsl:template match="form[@type='variant']/orth"/>
如果要复制节点,请应用不同的模板(使用模式)。
在应用模板时更具选择性(这,恕我直言,是 优选的方法):
XSLT 2.0
<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:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="form[@type='variant']">
<xsl:copy>
<!-- remove orth and cit from here -->
<xsl:apply-templates select="@*|node() except (orth|cit)"/>
</xsl:copy>
</xsl:template>
<xsl:template match="form[@type='graphical_variant']">
<form type="graphical_variant">
<!-- add orth and cit here -->
<xsl:apply-templates select="../orth" />
<xsl:apply-templates select="../cit" />
</form>
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:0)
<xsl:apply-templates select="." />
在这里,它匹配示例底部的空模板。
简单但不是最佳解决方案
<xsl:apply-templates select="." mode="noignore" />
然后使用mode =&#34; noignore&#34;制作符合您所需元素的内容。并实际上复制它们而不是抑制。