草庐IT

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

coder 2024-07-03 原文

我正在尝试使用 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/

有关xml - XSLT:检查元素是否较早遍历的更多相关文章

  1. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  2. ruby-on-rails - 在 Ruby 中循环遍历多个数组 - 2

    我有多个ActiveRecord子类Item的实例数组,我需要根据最早的事件循环打印。在这种情况下,我需要打印付款和维护日期,如下所示:ItemAmaintenancerequiredin5daysItemBpaymentrequiredin6daysItemApaymentrequiredin7daysItemBmaintenancerequiredin8days我目前有两个查询,用于查找maintenance和payment项目(非排他性查询),并输出如下内容:paymentrequiredin...maintenancerequiredin...有什么方法可以改善上述(丑陋的)代

  3. ruby-on-rails - 如何从 format.xml 中删除 <hash></hash> - 2

    我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为

  4. ruby - 检查 "command"的输出应该包含 NilClass 的意外崩溃 - 2

    为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar

  5. ruby - 检查数组是否在增加 - 2

    这个问题在这里已经有了答案:Checktoseeifanarrayisalreadysorted?(8个答案)关闭9年前。我只是想知道是否有办法检查数组是否在增加?这是我的解决方案,但我正在寻找更漂亮的方法:n=-1@arr.flatten.each{|e|returnfalseife

  6. ruby - 检查方法参数的类型 - 2

    我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)

  7. ruby - 检查字符串是否包含散列中的任何键并返回它包含的键的值 - 2

    我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案

  8. ruby-on-rails - Ruby 检查日期时间是否为 iso8601 并保存 - 2

    我需要检查DateTime是否采用有效的ISO8601格式。喜欢:#iso8601?我检查了ruby​​是否有特定方法,但没有找到。目前我正在使用date.iso8601==date来检查这个。有什么好的方法吗?编辑解释我的环境,并改变问题的范围。因此,我的项目将使用jsapiFullCalendar,这就是我需要iso8601字符串格式的原因。我想知道更好或正确的方法是什么,以正确的格式将日期保存在数据库中,或者让ActiveRecord完成它们的工作并在我需要时间信息时对其进行操作。 最佳答案 我不太明白你的问题。我假设您想检查

  9. ruby - 检查日期是否在过去 7 天内 - 2

    我的日期格式如下:"%d-%m-%Y"(例如,今天的日期为07-09-2015),我想看看是不是在过去的七天内。谁能推荐一种方法? 最佳答案 你可以这样做:require"date"Date.today-7 关于ruby-检查日期是否在过去7天内,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/32438063/

  10. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

随机推荐