我是XSLT的新手,并尝试谷歌搜索找到解决方案,但不能。我需要通过重复除重复元素之外的所有其他元素在XSLT中构造一个xml。
输入XML:这里元素D是重复的。它可能不止一次发生。根据它出现的次数,我的输出XML应该多次包含整个输入XML,除了元素D是分布式的。 如果答案对于D个重复次数是通用的,那将是非常有用的。
<ABCD>
<A>
<B>
<C>
<D>d1</D>
<D>d2</D>
<D>d3</D>
</C>
</B>
</A>
</ABCD>
输出XML:
<ABCD>
<A>
<B>
<C>
<D>d1</D>
</C>
</B>
</A>
<A>
<B>
<C>
<D>d2</D>
</C>
</B>
</A>
<A>
<B>
<C>
<D>d3</D>
</C>
</B>
</A>
</ABCD>
答案 0 :(得分:1)
以下是使用Saxon 9.5 HE测试的XSLT 2.0样式表:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs">
<xsl:variable name="nodes" as="node()*" select="//D"/>
<xsl:output indent="yes"/>
<xsl:template match="/*">
<xsl:copy>
<xsl:apply-templates select="$nodes" mode="copy"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*" mode="copy">
<xsl:variable name="ancestors" select="ancestor::*[position() ne last()]"/>
<xsl:variable name="anchor" select="."/>
<xsl:apply-templates select="$ancestors[1]">
<xsl:with-param name="ancestors" select="$ancestors"/>
<xsl:with-param name="anchor" select="$anchor"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="*">
<xsl:param name="ancestors"/>
<xsl:param name="anchor"/>
<xsl:choose>
<xsl:when test=". is $anchor">
<xsl:copy-of select="."/>
</xsl:when>
<xsl:when test=". intersect $ancestors">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates select="($ancestors[2], $anchor)[1]">
<xsl:with-param name="ancestors" select="$ancestors[position() gt 1]"/>
<xsl:with-param name="anchor" select="$anchor"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:when>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
它适用于任意数量的D
元素,但您需要决定操作哪些元素,因此我在代码中定义了一个变量。但是如果需要,您还可以定义一个参数来获取元素名称:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs">
<xsl:param name="name" select="'D'"/>
<xsl:variable name="nodes" as="node()*" select="//*[local-name() eq $name]"/>
<xsl:output indent="yes"/>
<xsl:template match="/*">
<xsl:copy>
<xsl:apply-templates select="$nodes" mode="copy"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*" mode="copy">
<xsl:variable name="ancestors" select="ancestor::*[position() ne last()]"/>
<xsl:variable name="anchor" select="."/>
<xsl:apply-templates select="$ancestors[1]">
<xsl:with-param name="ancestors" select="$ancestors"/>
<xsl:with-param name="anchor" select="$anchor"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="*">
<xsl:param name="ancestors"/>
<xsl:param name="anchor"/>
<xsl:choose>
<xsl:when test=". is $anchor">
<xsl:copy-of select="."/>
</xsl:when>
<xsl:when test=". intersect $ancestors">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates select="($ancestors[2], $anchor)[1]">
<xsl:with-param name="ancestors" select="$ancestors[position() gt 1]"/>
<xsl:with-param name="anchor" select="$anchor"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:when>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
如果您只想拍摄多次出现的元素,可以使用
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs">
<xsl:key name="name" match="*" use="node-name(.)"/>
<xsl:variable name="nodes" as="node()*" select="//*[key('name', node-name(.))[2]]"/>
<xsl:output indent="yes"/>
<xsl:template match="/*">
<xsl:copy>
<xsl:apply-templates select="$nodes" mode="copy"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*" mode="copy">
<xsl:variable name="ancestors" select="ancestor::*[position() ne last()]"/>
<xsl:variable name="anchor" select="."/>
<xsl:apply-templates select="$ancestors[1]">
<xsl:with-param name="ancestors" select="$ancestors"/>
<xsl:with-param name="anchor" select="$anchor"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="*">
<xsl:param name="ancestors"/>
<xsl:param name="anchor"/>
<xsl:choose>
<xsl:when test=". is $anchor">
<xsl:copy-of select="."/>
</xsl:when>
<xsl:when test=". intersect $ancestors">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates select="($ancestors[2], $anchor)[1]">
<xsl:with-param name="ancestors" select="$ancestors[position() gt 1]"/>
<xsl:with-param name="anchor" select="$anchor"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:when>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>