[英]Construct an xml in XSLT by repeating all other elements except one element
I am new to XSLT and tried googling to find solution but couldn't. 我是XSLT的新手,并尝试使用Google搜索来寻找解决方案,但没有找到。 I need to construct an xml in XSLT by repeating all other elements except the repetitive element. 我需要通过重复除重复元素之外的所有其他元素来在XSLT中构造xml。
Input XML: Here element D is repetitive. 输入XML:这里的元素D是重复的。 It might occur more than once. 它可能会发生多次。 Depending on the number of times it appears, my output XML should contain the entire input XML multiple times except that element D is distributed. 根据它出现的次数,我的输出XML应该多次包含整个输入XML,除了元素D是分布式的。 It would be really helpful if the answer is generic for n number of repetitions of D. 如果答案是D的n次重复的泛型,那将非常有帮助。
<ABCD>
<A>
<B>
<C>
<D>d1</D>
<D>d2</D>
<D>d3</D>
</C>
</B>
</A>
</ABCD>
Output XML: 输出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>
Here is an XSLT 2.0 stylesheet tested with Saxon 9.5 HE: 这是经过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>
It work for any number of D
elements but you somehow need to decide which elements to operate on so I defined a variable in the code. 它适用于任意数量的D
元素,但您需要以某种方式决定要对哪些元素进行操作,因此我在代码中定义了一个变量。 But if needed you could also define a parameter to take the element name: 但是,如果需要,您还可以定义一个参数以采用元素名称:
<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>
If you simply want to take the elements that occur several times you could use 如果您只想采用多次出现的元素,则可以使用
<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>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.