身份模板和优先级在 XSL 中创建重复节点 [英] Identity template and priority creating duplicate nodes in XSL
问题描述
所以我有以下 XML 输入:
So I have the following XML input:
<parent>
<para> text 1 <NodeTypeA id="1">element1</NodeTypeA> text2 <Xref ref="1"/> text3</para>
<para>text 4</para>
<para><NodeTypeA id="2">elt2</NodeTypeA></para>
<para>text5 <Xref red="2"/>text6 <Xref ref="3"/>text7</para>
</parent>
我正在尝试提取外部参照节点并将平行节点一分为二,感谢 这个答案,这是有效的.但是,在我的 XSL 代码中,我需要一个身份模板,并在我的模板中设置一些优先级.
I'm trying to extract the Xref node and split the para nodes in two, and thanks to this answer, this works. However, in my XSL code, I need to have a identity template, and some priority in my templates.
这是我的完整代码:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="@*|node()" priority="0">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="para[Xref]" priority="1">
<xsl:apply-templates select="node()[1]"/>
</xsl:template>
<xsl:template match="para/node()[not(self::Xref)]" priority="1">
<xsl:param name="group" select="."/>
<xsl:apply-templates select="following-sibling::node()[1]">
<xsl:with-param name="group" select="$group | ."/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="para/node()[not(self::Xref) and not(following-sibling::Xref)][last()]" priority="1">
<xsl:param name="group" select="."/>
<para>
<xsl:copy-of select="$group | ."/>
</para>
</xsl:template>
<xsl:template match="para/Xref" priority="1">
<xsl:param name="group"/>
<xsl:if test="$group">
<para>
<xsl:copy-of select="$group"/>
</para>
</xsl:if>
<xsl:copy-of select="."/>
<xsl:apply-templates select="following-sibling::node()[1]"/>
</xsl:template>
</xsl:stylesheet>
问题是不包含外部参照节点的平行节点在我的输出中加倍,而包含外部参照节点的平行节点转换得很好.这是我得到的 XML 输出:
The problem is that the para nodes that do NOT contain a Xref node are doubled in my output while those containing an Xref node are transformed just fine. Here's the XML output I get:
<?xml version="1.0"?>
<parent>
<para> text 1 <NodeTypeA id="1">element1</NodeTypeA> text2 </para>
<Xref ref="1" />
<para> text3</para>
<para><para>text 4</para></para>
<para><para><NodeTypeA id="2">elt2</NodeTypeA></para></para>
<para>text5 </para>
<Xref red="2" />
<para>text6 </para>
<Xref ref="3" />
<para>text7</para>
</parent>
为什么添加身份模板和一些优先级会破坏这一点,我该如何解决?
Why does adding an identity template and some priority break this, and how can i fix it ?
PS:我使用的是 XSLT 1
PS: I'm using XSLT 1
推荐答案
如果我已经正确理解了问题——描述相当混乱,
In case I have understood correctly the problem -- the description is rather confusing,
这是一种解决方案:
<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="kPrecedingXref" match="node()[not(self::Xref)]"
use="generate-id(following-sibling::Xref[1])"/>
<xsl:template match="node()|@*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="para[Xref]">
<xsl:apply-templates select="Xref"/>
<para>
<xsl:apply-templates
select="node()[not(self::Xref) and not(following-sibling::Xref)]"/>
</para>
</xsl:template>
<xsl:template match="para/Xref">
<para>
<xsl:apply-templates select="key('kPrecedingXref', generate-id())"/>
</para>
<xsl:call-template name="identity"/>
</xsl:template>
</xsl:stylesheet>
当此转换应用于提供的 XML 文档时:
<parent>
<para> text 1 <NodeTypeA id="1">element1</NodeTypeA> text2 <Xref ref="1"/> text3</para>
<para>text 4</para>
<para><NodeTypeA id="2">elt2</NodeTypeA></para>
<para>text5 <Xref red="2"/>text6 <Xref ref="3"/>text7</para>
</parent>
产生了想要的、正确的结果:
<parent>
<para> text 1 <NodeTypeA id="1">element1</NodeTypeA> text2 </para>
<Xref ref="1"/>
<para> text3</para>
<para>text 4</para>
<para>
<NodeTypeA id="2">elt2</NodeTypeA>
</para>
<para>text5 </para>
<Xref red="2"/>
<para>text6 </para>
<Xref ref="3"/>
<para>text7</para>
</parent>
这篇关于身份模板和优先级在 XSL 中创建重复节点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!