我正在使用XSLT对一些相当复杂的XML执行转换。为了实现我需要的输出,我必须创建一个嵌套的for循环,如下所示:
源XML
<root>
<element1>
<child>
<aaa></aaa>
<bbb></bbb>
</child>
</element1>
<element2/>
<element3/>
<element3/>
<element3/>
</root>
XSLT
<xsl:for-each select="element3">
<!-- Do some stuff -->
<xsl:for-each select="../element1/child/*">
<!-- Do some more stuff -->
</xsl:for-each>
</xsl:for-each>
问题
我在这里尝试做的是在我的嵌套循环中(在../element1/child/*
上) - 我想知道:
<bbb>
那么这个位置(我认为)将是'1'element3
上) - 所以,例如,如果我在<element3>
的第三个实例上然后循环../element1/child/*
并专注于{ {1}} - 我将追求的两个值是'2'和'0'。理想情况下,我希望能够将这些值分配给变量。我尝试使用如下所示的<aaa>
符号,但这似乎不起作用。
position()
如果有人对如何实现这一点有任何想法,将不胜感激!我正在使用XSLT 2.0,但如果需要,我可以使用XSLT 1.0开放解决方案。提前谢谢。
答案 0 :(得分:7)
您应该尝试将输入修改为:
<root>
<element1>
<child>
<aaa>1a</aaa>
<bbb>2a</bbb>
</child>
</element1>
<element2/>
<element3>3a</element3>
<element3>3b</element3>
<element3>3c</element3>
</root>
然后看看你得到了什么:
<xsl:template match="/">
<test>
<xsl:for-each select="root/element3">
<xsl:variable name="parent-position" select="position()" />
<xsl:variable name="parent-value" select="." />
<xsl:for-each select="../element1/child/*">
<item value="{.}" parent-value="{$parent-value}" parent-position="{$parent-position}" position="{position()}"/>
</xsl:for-each>
</xsl:for-each>
</test>
</xsl:template>
答案 1 :(得分:0)
我已经为您的输入添加了一些id属性,因此您可以看到哪个节点正在处理,因此我的输入如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<element1 id="e1-1">
<child>
<aaa id="e1-a"></aaa>
<bbb id="e1-b"></bbb>
</child>
</element1>
<element2 id="e2-1"/>
<element3 id="e3-1"/>
<element3 id="e3-2"/>
<element3 id="e3-3"/>
</root>
此样式表执行我认为您尝试执行的操作 - 它处理每个element3
并处理每个../element1/child/*
的所有element3
个节点:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output indent="yes"/>
<xsl:template match="root">
<tests>
<xsl:apply-templates select="element3"/>
</tests>
</xsl:template>
<xsl:template match="element3">
<xsl:apply-templates select="../element1/child/*">
<xsl:with-param name="parent-pos" select="position() - 1"/>
<xsl:with-param name="parent-id" select="@id"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="element1/child/*">
<xsl:param name="parent-pos"/>
<xsl:param name="parent-id"/>
<xsl:variable name="current-pos" select="position()"/>
<test parent-id="{$parent-id}" current-id="{@id}" parent-pos="{$parent-pos}" current-pos="{$current-pos}"/>
</xsl:template>
</xsl:stylesheet>
结果是:
<tests>
<test parent-id="e3-1" current-id="e1-a" parent-pos="0" current-pos="1"/>
<test parent-id="e3-1" current-id="e1-b" parent-pos="0" current-pos="2"/>
<test parent-id="e3-2" current-id="e1-a" parent-pos="1" current-pos="1"/>
<test parent-id="e3-2" current-id="e1-b" parent-pos="1" current-pos="2"/>
<test parent-id="e3-3" current-id="e1-a" parent-pos="2" current-pos="1"/>
<test parent-id="e3-3" current-id="e1-b" parent-pos="2" current-pos="2"/>
</tests>
希望有所帮助
答案 2 :(得分:0)
您可以在内部使用添加的@position属性重建节点,并在重建树上循环。对于这个exsl:node-set(或其他专有衍生物)是必需的。
获取原始的source.xml(不变!)和此XSLT脚本:
<xsl:template match="/*">
<xsl:variable name="CopiedTree">
<xsl:call-template name="copy-with-position"/>
</xsl:variable>
<xsl:for-each select="exsl:node-set($CopiedTree)//element3">
<xsl:element name="E3">
<xsl:comment>Do some stuff</xsl:comment>
<xsl:variable name="E3pos" select="@position()" />
<xsl:for-each select="../element1/child/*">
<xsl:element name="E1C">
<xsl:attribute name="name"><xsl:value-of select="name()" /></xsl:attribute>
<xsl:attribute name="positions"><xsl:value-of select="concat($E3pos, ' - ', @position)" /></xsl:attribute>
<xsl:comment>Do some more stuff</xsl:comment>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:for-each>
</xsl:template>
<xsl:template name="copy-with-position">
<xsl:element name="{name()}">
<xsl:copy-of select="(@*)" />
<xsl:attribute name="position"><xsl:value-of select="position()" /></xsl:attribute>
<xsl:for-each select="./*">
<xsl:call-template name="copy-with-position">
<xsl:with-param name="position" select="position()" />
</xsl:call-template>
</xsl:for-each>
</xsl:element>
</xsl:template>
输出为:
<?xml version="1.0" encoding="UTF-8"?>
<E3>
<!--Do some stuff-->
<E1C name="aaa" positions="3 - 1">
<!--Do some more stuff-->
</E1C>
<E1C name="bbb" positions="3 - 2">
<!--Do some more stuff-->
</E1C>
</E3>
<E3>
<!--Do some stuff-->
<E1C name="aaa" positions="4 - 1">
<!--Do some more stuff-->
</E1C>
<E1C name="bbb" positions="4 - 2">
<!--Do some more stuff-->
</E1C>
</E3>
<E3>
<!--Do some stuff-->
<E1C name="aaa" positions="5 - 1">
<!--Do some more stuff-->
</E1C>
<E1C name="bbb" positions="5 - 2">
<!--Do some more stuff-->
</E1C>
</E3>