xml - XSLT:检查元素是否较早遍历

标签 xml xslt xpath xslt-2.0

我正在尝试使用 XSLT 从大型 XML 中呈现一些数据。 XML 数据实际上是一种图形数据,而不是分层的。和元素彼此相关,因此最终可能会出现循环引用(但是关系类型不同)。

我试图遍历一个元素的关系并访问每个相关元素等等。这样,有时我会到达一个我已经遍历过的元素。在这种情况下,我应该停止进一步遍历,否则我将在一个循环中运行。

我的问题是,我无法存储我已经遍历过的元素列表,也无法在每次开始遍历元素时进行查找,这样如果该元素在查找中,我就可以停止遍历。

简单地说,我想将元素保存在一个查找表中,并在遍历时将每个元素添加到其中。

有什么解决办法吗?

最佳答案

递归模板可以传递自己的参数,这些参数包含“先前”处理过的节点的节点集和要处理的节点队列。这是一个等同于修改状态变量的函数式编程。

示例输入:

<graph startNode="a">
    <graphNode id="a">
        <edge target="b" />
        <edge target="c" />
    </graphNode>
    <graphNode id="b">
        <edge target="c" />
    </graphNode>
    <graphNode id="c">
        <edge target="d" />
    </graphNode>
    <graphNode id="d">
        <edge target="a" />
        <edge target="b" />
    </graphNode>
</graph>

XSL 2.0 样式表:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="2.0">

    <xsl:output method="xml" indent="yes"/>

    <xsl:key name="graphNodeByID" match="graphNode" use="@id" />

    <xsl:template match="/graph">
        <results>
            <xsl:apply-templates select="key('graphNodeByID', @startNode)"
                     mode="process"/>            
        </results>
    </xsl:template>

    <xsl:template match="graphNode" mode="process">
        <xsl:param name="already-processed" select="/.." />
        <xsl:param name="queue" select="/.." />

        <!-- do stuff with context node ... -->
        <processing node="{@id}" />

        <!-- Add connected nodes to queue, excluding those already processed. -->
        <xsl:variable name="new-queue"
              select="($queue | key('graphNodeByID', edge/@target))
                        except ($already-processed | .)" />

        <!-- recur on next node in queue. -->
        <xsl:apply-templates select="$new-queue[1]" mode="process">
            <xsl:with-param name="already-processed"
                            select="$already-processed | ." />
            <xsl:with-param name="queue" select="$new-queue" />
        </xsl:apply-templates>
    </xsl:template>

</xsl:stylesheet>

输出(测试):

<results>
   <processing node="a"/>
   <processing node="b"/>
   <processing node="c"/>
   <processing node="d"/>
</results>

按照规定,没有节点被处理两次,即使图中包含循环。

关于xml - XSLT:检查元素是否较早遍历,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8605118/

相关文章:

.net - XPATH 查询以查找包含关键字的属性

java - Wowza 流媒体引擎 Eclipse server.xml

java - 如何将项目ID传递给另一个 Activity ?

variables - XSLT 中的条件变量选择

xml - xsl 获取深度嵌套元素

sql-server - 带有 xmlns 的 Xpath,它不起作用

xml - 谁检查 XML 命名空间是否唯一?

xml - XSLT 删除重复项

xml - xml 中的嵌套 for-each 循环

python - 如何使用 pandas 将多个 Xpath 转换为数据框?