XSLT:查找节点在给定节点集中的位置
XSLT: find position of node in a given nodeset
想象一棵 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::
:计算 parents 兄弟轴上的兄弟姐妹,直到根。
尝试 3:preceding-sibling::
:
甚至不值得。这只会查看其他同级元素的位置,这意味着我将为每个 ELEM3 元素获得相同的位置。
尝试 4:generate-id()
:
如果我们放宽@position 属性反映节点编号的限制,则此方法略有不同。只要生成的值是唯一的,这在我的设置中并不重要。
这将生成唯一的@position 属性。不幸的是,id 只能保证在相同的 运行 中是相同的。这意味着我不能将其用于测试和我们的 CI/test 设置。
尝试 5:在给定列表中查找当前节点?
我在想是否可以通过 XPATH 以某种方式提供元素列表,如下所示:*
或 ELEM2|ELEM3
。现在,如果我可以获取 current()
节点并找到它在列表中的位置。
这可能吗?
限制:
- 我正在使用 XSLT 1/xsltproc
- 生成的@position 属性必须是唯一的
- 生成的@position 属性必须相对稳定并且不会在 运行s 或平台之间改变
使用<xsl:number count="*" level="any"/>
:
或者干脆:
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>
想象一棵 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::
:计算 parents 兄弟轴上的兄弟姐妹,直到根。
尝试 3:preceding-sibling::
:
甚至不值得。这只会查看其他同级元素的位置,这意味着我将为每个 ELEM3 元素获得相同的位置。
尝试 4:generate-id()
:
如果我们放宽@position 属性反映节点编号的限制,则此方法略有不同。只要生成的值是唯一的,这在我的设置中并不重要。
这将生成唯一的@position 属性。不幸的是,id 只能保证在相同的 运行 中是相同的。这意味着我不能将其用于测试和我们的 CI/test 设置。
尝试 5:在给定列表中查找当前节点?
我在想是否可以通过 XPATH 以某种方式提供元素列表,如下所示:*
或 ELEM2|ELEM3
。现在,如果我可以获取 current()
节点并找到它在列表中的位置。
这可能吗?
限制:
- 我正在使用 XSLT 1/xsltproc
- 生成的@position 属性必须是唯一的
- 生成的@position 属性必须相对稳定并且不会在 运行s 或平台之间改变
使用<xsl:number count="*" level="any"/>
:
或者干脆:
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>