想象一下一个XML树,其中的节点具有多个深度
<?xml version="1.0" encoding="UTF-8"?>
<root>
<ELEM2>
<ELEM3/>
</ELEM2>
<ELEM2>
<ELEM3/>
</ELEM2>
<ELEM2>
<ELEM3/>
</ELEM2>
</root>
我想知道每个元素在整棵树中的唯一位置。
所需的输出:
<?xml version="1.0"?>
<root position="1"/>
<ELEM2 position="2"/>
<ELEM3 position="3"/>
<ELEM2 position="4"/>
<ELEM3 position="5"/>
<ELEM2 position="6"/>
<ELEM3 position="7"/>
因此,基本上,我想查看所有元素列表中的位置,并使用该索引进行查找。
尝试1:position()
:我尝试像这样使用position()
:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="*">
<xsl:copy>
<xsl:attribute name="position">
<xsl:value-of select="position()"/>
</xsl:attribute>
</xsl:copy>
<xsl:apply-templates select="node()"/>
</xsl:template>
</xsl:stylesheet>
这给了我重复的位置属性:
<?xml version="1.0"?>
<root position="1"/>
<ELEM2 position="2"/>
<ELEM3 position="2"/>
<ELEM2 position="4"/>
<ELEM3 position="2"/>
<ELEM2 position="6"/>
<ELEM3 position="2"/>
因此,我不能在当前节点集中使用position()
,因为该位置仅限于树中的当前分支。
尝试2:preceding::
:
然后我像这样使用preceding::
进行了查看:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="*">
<xsl:copy>
<xsl:attribute name="position">
<xsl:value-of select="count(preceding::*)"/>
</xsl:attribute>
</xsl:copy>
<xsl:apply-templates select="node()"/>
</xsl:template>
</xsl:stylesheet>
但是不幸的是我得到了:
<?xml version="1.0"?>
<root position="0"/>
<ELEM2 position="0"/>
<ELEM3 position="0"/>
<ELEM2 position="2"/>
<ELEM3 position="2"/>
<ELEM2 position="4"/>
<ELEM3 position="4"/>
因此,preceding::
:在父级兄弟姐妹的轴上一直计数兄弟姐妹,直到根。
尝试3:preceding-sibling::
:
甚至不值得。这只会浏览其他兄弟元素的位置,这意味着我将为每个ELEM3元素获得相同的位置。
尝试4:generate-id()
:
如果我们放宽@position属性反映节点号的限制,则此方法稍有不同。只要生成的值是唯一的,这对我的设置就无关紧要。
这将生成唯一的@position属性。不幸的是,这些ID仅在同一运行中被保证是相同的。这意味着我不能将其用于测试和CI /测试设置。
尝试5:在给定列表中查找当前节点?
我在考虑是否可以通过某种方式通过XPATH提供元素列表:*
或ELEM2|ELEM3
。现在,如果我可以接下current()
节点并在列表中找到它的位置。
这可能吗?
限制:
答案 0 :(得分:2)
使用<xsl:number count="*" level="any"/>
:
答案 1 :(得分:1)
或者简单地:
count(ancestor::*) + count(preceding::*) +1
这是一个完整的转换(仅10行):
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="*">
<xsl:copy>
<xsl:attribute name="position" select="count(ancestor::*) + count(preceding::*) +1"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
应用于提供的XML文档:
<root>
<ELEM2>
<ELEM3/>
</ELEM2>
<ELEM2>
<ELEM3/>
</ELEM2>
<ELEM2>
<ELEM3/>
</ELEM2>
</root>
产生了所需的正确结果:
<root position="1">
<ELEM2 position="2">
<ELEM3 position="3"/>
</ELEM2>
<ELEM2 position="4">
<ELEM3 position="5"/>
</ELEM2>
<ELEM2 position="6">
<ELEM3 position="7"/>
</ELEM2>
</root>