我有以下文档结构:
<?xml version="1.0"?>
<catalog>
<navigationRoot>
<!-- more elements-->
<navigation id="123" type="level0">
<!-- more elements-->
<navigationNodes>
<navigationNode>
<!-- more elements-->
</navigationNode>
<navigationNode>
<!-- more elements-->
</navigationNode>
<!--...-->
</navigationNodes>
<children>
<navigation idref="196439"/>
<navigation idref="196459"/>
<!--...-->
</children>
<!-- more elements-->
</navigation>
<navigation id="196439" type="level1">
<!-- more elements-->
<navigationNodes>
<navigationNode>
<!-- more elements-->
</navigationNode>
<navigationNode>
<!-- more elements-->
</navigationNode>
<!--...-->
</navigationNodes>
<children>
<navigation idref="19643261"/>
<navigation idref="196463463"/>
<!--...-->
</children>
<!-- more elements-->
</navigation>
<navigation id="196459" type="level1">
<!-- more elements-->
<navigationNodes>
<navigationNode>
<!-- more elements-->
</navigationNode>
<navigationNode>
<!-- more elements-->
</navigationNode>
<!--...-->
</navigationNodes>
<children>
<navigation idref="19644361"/>
<navigation idref="19643467"/>
<!--...-->
</children>
<!-- more elements-->
</navigation>
</navigationRoot>
</catalog>
我需要在"导航 id=..."元素。此外,我必须给出"导航 idref=..."元素 另一个属性"类型",等于父元素的 level++。例如,在本文档中,在"导航 id=123"节点中,子节点应放置在"navigationNode"元素上方,并且具有"level1"的类型,如下所示:
<navigation id="123" type="level0">
<!-- more elements-->
<children>
<navigation idref="196439" type="level1"/>
<navigation idref="196459" type="level1"/>
<!--...-->
</children>
<navigationNodes>
<navigationNode>
<!-- more elements-->
</navigationNode>
<navigationNode>
<!-- more elements-->
</navigationNode>
<!--...-->
</navigationNodes>
<!-- more elements-->
</navigation>
我该如何实现?
四个步骤:
- 身份转换。
- 设计一个模板以在
children/navigation
上插入新@type
。在此解决方案中,仅当存在具有@idref
中给出的@id
的任何元素时,才会添加该属性(您可以考虑xml:id
并改用id()
)。您也可以将其缩小到navigation
。 - 然后,在匹配
children
上,复制它,应用children/navigation
,并附加任何以下navigationNodes
。所以children
实际上会在navigation
之前被"移动".我天真地认为每个navigation
只有一个children
. - 最后,忽略已在步骤 3 中复制的所有
navigationNodes
。
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="children/navigation[@idref]">
<xsl:variable name="type" select="//*[@id = current()/@idref]/@type"/>
<xsl:copy>
<xsl:if test="$type">
<xsl:attribute name="type">
<xsl:value-of select="$type"/>
</xsl:attribute>
</xsl:if>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="children">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
<xsl:copy-of select="preceding-sibling::navigationNodes"/>
</xsl:template>
<xsl:template match="navigationNodes"/>
做!希望这有帮助。