草庐IT

xml - XSLT:处理所有后续兄弟直到满足特定条件而无需重新处理已处理的节点

coder 2024-06-30 原文

考虑以下 XML 结构:

<a>
    <t>abc</t>
</a>
<a type="start"></a>
<b>
    <t>ignore</t>
</b>
<a></a>    
<a>
    <t>1</t>
</a>
<a>
    <t>2</t>
</a>
<a>
    <t>3</t>
</a>
<b>
    <t>ignore</t>
</b>
<a>
    <t>4</t>
</a>
<a type="end"></a>
<a>
    <t>def</t>
</a>

我需要获取属性值为 startend 的 a 标签之间的所有 a 标签的内容总和

我尝试使用以下 XSL:

<xsl:template match="a">
    <xsl:choose>
        <xsl:when test="@type='start'">
            <merged>
                <xsl:call-template name="getMergedText">
                    <xsl:with-param name="text" select="''"/>
                <xsl:call-template>
            </merged>
        </xsl:when>
        <xsl:otherwise>
            <single>
                <xsl:value-of select="t"/>
            </single>
        </xsl:otherwise>
    <xsl:choose>
</xsl:template>

<xsl:template name="getMergedText">
    <xsl:param name="text"/>

    <xsl:choose>
        <xsl:when test="following-sibling::a[1]/@type='end'">
            <xsl:value-of select="$text"/>
        </xsl:when>
        <xsl:when test="following-sibling::a[1]/t">
            <xsl:variable name="text.update">
                <xsl:value-of select="$text"/>
                <xsl:value-of select="following-sibling::a[1]/t"/>
            </xsl:variable>
            <xsl:for-each select="following-sibling::a[1]">
                <xsl:call-template name="getMergedText">
                    <xsl:with-param name="text" select="$text.update"/>
                <xsl:call-template>
            </xsl:for-each>
        </xsl:when>
        <xsl:otherwise>
            <xsl:for-each select="following-sibling::a[1]">
                <xsl:call-template name="getMergedText">
                    <xsl:with-param name="text" select="$text"/>
                <xsl:call-template>
            </xsl:for-each>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

所需的输出是:

<single>abc</single>
<merged>1234</merged>
<single>def</single>

我得到的输出是:

<single>abc</single>
<merged>1234</merged>
<single>1</single>
<single>2</single>
<single>3</single>
<single>4</single>
<single>def</single>

如何避免重新处理已由 getMergedText 模板处理的 a 节点?

提前致谢!

注意:我正在使用 XSLT 1.0。 XML 中可以有多个开始-结束节点对的实例,在这些对之前、之后和之间可以有任意数量的节点。

最佳答案

这里最有效的方法可能是我听说过的被描述为“兄弟递归”的方法,使用尾递归模板来模拟“while 循环”类型的结构。顶部模板从处理 first a 元素开始,然后每个模板做的最后一件事是将适当的模板应用到 next 一个元素。

<xsl:template match="---whatever matches the parent element of the a's---">
  <xsl:apply-templates select="a[1]" />
</xsl:template>

<xsl:template match="a[@type = 'start']">
  <!-- edge case - start followed immediately by end shouldn't generate
       a "merged" element -->
  <xsl:if test="not(following-sibling::a[1][@type = 'end'])">
    <merged>
      <xsl:apply-templates mode="merge" select="following-sibling::a[1]" />
    </merged>
  </xsl:if>
  <!-- continue with the a after the "end" -->
  <xsl:apply-templates select="
      following-sibling::a[@type = 'end'][1]/following-sibling::a[1]" />
</xsl:template>

<xsl:template match="a">
  <single><xsl:value-of select="t"/></single>
  <xsl:apply-templates select="following-sibling::a[1]" />
</xsl:template>

<!-- stop the merge when we get the the "end" -->
<xsl:template match="a[@type = 'end']" mode="merge" />

<xsl:template match="a" mode="merge">
  <xsl:value-of select="t" />
  <xsl:apply-templates select="following-sibling::a[1]" mode="merge" />
</xsl:template>

注意 following-sibling::a[1][@type = 'end'] 之间的区别(检查紧随其后的 a 元素是否具有type="end") 和 following-sibling::a[@type = 'end'][1](找到最近的 a 确实有 type="end").

关于xml - XSLT:处理所有后续兄弟直到满足特定条件而无需重新处理已处理的节点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21953047/

有关xml - XSLT:处理所有后续兄弟直到满足特定条件而无需重新处理已处理的节点的更多相关文章

  1. ruby - 如何以所有可能的方式将字符串拆分为长度最多为 3 的连续子字符串? - 2

    我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123

  2. ruby - 如何指定 Rack 处理程序 - 2

    Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

  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-on-rails - 跳过状态机方法的所有验证 - 2

    当我的预订模型通过rake任务在状态机上转换时,我试图找出如何跳过对ActiveRecord对象的特定实例的验证。我想在reservation.close时跳过所有验证!叫做。希望调用reservation.close!(:validate=>false)之类的东西。仅供引用,我们正在使用https://github.com/pluginaweek/state_machine用于状态机。这是我的预订模型的示例。classReservation["requested","negotiating","approved"])}state_machine:initial=>'requested

  5. ruby - Nokogiri 剥离所有属性 - 2

    我有这个html标记:我想得到这个:我如何使用Nokogiri做到这一点? 最佳答案 require'nokogiri'doc=Nokogiri::HTML('')您可以通过xpath删除所有属性:doc.xpath('//@*').remove或者,如果您需要做一些更复杂的事情,有时使用以下方法遍历所有元素会更容易:doc.traversedo|node|node.keys.eachdo|attribute|node.deleteattributeendend 关于ruby-Nokog

  6. ruby - 匹配大写字母并用后续字母填充,直到一定的字符串长度 - 2

    我有一个驼峰式字符串,例如:JustAString。我想按照以下规则形成长度为4的字符串:抓取所有大写字母;如果超过4个大写字母,只保留前4个;如果少于4个大写字母,则将最后大写字母后的字母大写并添加字母,直到长度变为4。以下是可能发生的3种情况:ThisIsMyString将产生TIMS(大写字母);ThisIsOneVeryLongString将产生TIOV(前4个大写字母);MyString将生成MSTR(大写字母+tr大写)。我设法用这个片段解决了前两种情况:str.scan(/[A-Z]/).first(4).join但是,我不太确定如何最好地修改上面的代码片段以处理最后一种

  7. ruby - 获取模块中定义的所有常量的值 - 2

    我想获取模块中定义的所有常量的值:moduleLettersA='apple'.freezeB='boy'.freezeendconstants给了我常量的名字:Letters.constants(false)#=>[:A,:B]如何获取它们的值的数组,即["apple","boy"]? 最佳答案 为了做到这一点,请使用mapLetters.constants(false).map&Letters.method(:const_get)这将返回["a","b"]第二种方式:Letters.constants(false).map{|c

  8. ruby - 如何遍历 Ruby 中所有正则表达式匹配的字符串? - 2

    我们有一个字符串:“”这个正则表达式://i如何从当前字符串中获取所有匹配项? 最佳答案 "".scan(//)参见scan在ruby​​-docs上 关于ruby-如何遍历Ruby中所有正则表达式匹配的字符串?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/6857852/

  9. ruby-on-rails - 在所有延迟的作业之前 Hook - 2

    是否可以在所有delayed_job任务之前运行一个方法?基本上,我们试图确保每个运行delayed_job的服务器都有我们代码的最新实例,所以我们想运行一个方法来在每个作业运行之前检查它。(我们已经有了“check”方法并在别处使用它。问题只是关于如何从delayed_job中调用它。) 最佳答案 现在有一种官方方法可以通过插件来做到这一点。这篇博文通过示例清楚地描述了如何执行此操作http://www.salsify.com/blog/delayed-jobs-callbacks-and-hooks-in-rails(本文中描述

  10. Ruby-vips 图像处理库。有什么好的使用示例吗? - 2

    我对图像处理完全陌生。我对JPEG内部是什么以及它是如何工作一无所知。我想知道,是否可以在某处找到执行以下简单操作的ruby​​代码:打开jpeg文件。遍历每个像素并将其颜色设置为fx绿色。将结果写入另一个文件。我对如何使用ruby​​-vips库实现这一点特别感兴趣https://github.com/ender672/ruby-vips我的目标-学习如何使用ruby​​-vips执行基本的图像处理操作(Gamma校正、亮度、色调……)任何指向比“helloworld”更复杂的工作示例的链接——比如ruby​​-vips的github页面上的链接,我们将不胜感激!如果有ruby​​-

随机推荐