草庐IT

xml - XSLT 1.0 将特定的后代/子注释重新排列到与父/祖先相同的级别

coder 2024-06-30 原文

我正在寻找一种通用方法来将某些特定后代重新排列到其祖先节点的级别。

重要的是:

  • 我需要一个适用于 px 的通用模板。
  • 节点a b DEEPSPACENODE的顺序(从上到下)尽量不要改变。

我的输入:

<root>
    <p>
        <a>1</a>
        <a>2</a>
        <a><DEEPSPACENODE/></a>
        <b>3</b>
        <b>4</b>
        <a>5</a>
        <a>6</a>
        <b>7</b>
    </p>

    <x>
        <a>8</a>
        <a>9</a>
        <b>10</b>
        <b>11</b>
        <a>12</a>
        <a>13</a>
        <b>14</b>
    </x>    
</root>

我想要的输出:

<root>
    <p>
        <a>1</a>
        <a>2</a>
        <a/>
    </p>
    <DEEPSPACENODE/>
    <b>3</b>
    <b>4</b>
    <p>
        <a>5</a>
        <a>6</a>
    </p>
    <b>7</b>

    <x>
        <a>8</a>
        <a>9</a>
    </x>
    <b>10</b>
    <b>11</b>
    <x>
        <a>12</a>
        <a>13</a>
    </x>
    <b>14</b>
</root>

感谢您的帮助。我尝试自己解决,但没有成功。

最佳答案

这是一个更通用的解决方案,可以在不对 XML 文档施加任何限制的情况下产生所需的结果——我们不假设任何预定义的嵌套级别,或者名为b 存在:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:key name="kFollowing"
   match="a[preceding-sibling::*[1]
                              [self::a]
           ]"
   use="concat(
         generate-id(
                preceding-sibling::*[not(self::a)][1]
                    ),
         generate-id(..)
               )
         "/>

 <xsl:template match="node()|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="*[a]">
   <xsl:apply-templates/>
 </xsl:template>

 <xsl:template match=
   "a[not(preceding-sibling::*[1][self::a])]">

   <xsl:variable name="vGroup" select=
   ".|key('kFollowing',
             concat(generate-id(preceding-sibling::*[1]),
                    generate-id(..)
                   )
          )"/>

   <xsl:element name="{name(..)}">
     <xsl:apply-templates mode="group"
     select="$vGroup"/>
   </xsl:element>

   <xsl:apply-templates select="$vGroup/*"/>
 </xsl:template>

 <xsl:template match="a" mode="group">
  <a>
   <xsl:apply-templates select="node()[not(self::*)]"/>
  </a>
 </xsl:template>

 <xsl:template match=
  "a[preceding-sibling::*[1]
                       [self::a]
    ]"/>
</xsl:stylesheet>

应用于提供的 XML 文档时:

<root>
    <p>
        <a>1</a>
        <a>2</a>
        <a>
            <DEEPSPACENODE/>
        </a>
        <b>3</b>
        <b>4</b>
        <a>5</a>
        <a>6</a>
        <b>7</b>
    </p>
    <x>
        <a>8</a>
        <a>9</a>
        <b>10</b>
        <b>11</b>
        <a>12</a>
        <a>13</a>
        <b>14</b>
    </x>
</root>

产生了想要的、正确的结果:

<root>
   <p>
      <a>1</a>
      <a>2</a>
      <a/>
   </p>
   <DEEPSPACENODE/>
   <b>3</b>
   <b>4</b>
   <p>
      <a>5</a>
      <a>6</a>
   </p>
   <b>7</b>
   <x>
      <a>8</a>
      <a>9</a>
   </x>
   <b>10</b>
   <b>11</b>
   <x>
      <a>12</a>
      <a>13</a>
   </x>
   <b>14</b>
</root>

现在,对于以下 XML 文档,此解决方案仍会产生所需的结果,而 @empo 的解决方案却在其上阻塞:

<root>
   <c>
    <p>
        <a>1</a>
        <a>2</a>
        <a>
            <DEEPSPACENODE/>
        </a>
        <z>3</z>
        <z>4</z>
        <a>5</a>
        <a>6</a>
        <b>7</b>
    </p>
    <x>
        <a>8</a>
        <a>9</a>
        <b>10</b>
        <z>11</z>
        <a>12</a>
        <a>13</a>
        <b>14</b>
    </x>
  </c>  
</root>

同样的转换,当应用于上面的 XML 文档时,再次产生正确的、想要的结果:

<root>
   <c>
      <p>
         <a>1</a>
         <a>2</a>
         <a/>
      </p>
      <DEEPSPACENODE/>
      <z>3</z>
      <z>4</z>
      <p>
         <a>5</a>
         <a>6</a>
      </p>
      <b>7</b>
      <x>
         <a>8</a>
         <a>9</a>
      </x>
      <b>10</b>
      <z>11</z>
      <x>
         <a>12</a>
         <a>13</a>
      </x>
      <b>14</b>
   </c>
</root>

二。 XSLT 2.0 解决方案:

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="node()|@*" mode="#all">
      <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
  </xsl:template>

 <xsl:template match="*[a]">
  <xsl:for-each-group select="node()"
                      group-adjacent="name() eq 'a'">
    <xsl:apply-templates select="current-group()"
                         mode="group">
      <xsl:with-param name="pGroup"
                      select="current-group()"/>
    </xsl:apply-templates>
    <xsl:apply-templates select="current-group()[self::a]/*"/>
   </xsl:for-each-group>
  </xsl:template>

 <xsl:template match="a" mode="group"/>

 <xsl:template mode="group"
          match="a[not(preceding-sibling::*[1][self::a])]" >
   <xsl:param name="pGroup" as="node()*"/>

   <xsl:element name="{name(..)}">
     <xsl:apply-templates select="$pGroup" mode="shallow"/>
   </xsl:element>
 </xsl:template>

  <xsl:template match="a" mode="shallow">
    <a>
      <xsl:apply-templates select="node()[not(self::*)]"/>
    </a>
   </xsl:template>
</xsl:stylesheet>

关于xml - XSLT 1.0 将特定的后代/子注释重新排列到与父/祖先相同的级别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7032275/

有关xml - XSLT 1.0 将特定的后代/子注释重新排列到与父/祖先相同的级别的更多相关文章

  1. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  2. 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代码修改为

  3. ruby-on-rails - faraday如何设置日志级别 - 2

    我最近将我的http客户端切换到faraday,一切都按预期工作。我有以下代码来创建连接:@connection=Faraday.new(:url=>base_url)do|faraday|faraday.useCustim::Middlewarefaraday.request:url_encoded#form-encodePOSTparamsfaraday.request:jsonfaraday.response:json,:content_type=>/\bjson$/faraday.response:loggerfaraday.adapterFaraday.default_ada

  4. ruby-on-rails - 如何在 Rails 3 中禁用 XML 解析 - 2

    我想禁用HTTP参数的自动XML解析。但我发现命令仅适用于Rails2.x,它们都不适用于3.0:config.action_controller.param_parsers.deleteMime::XML(application.rb)ActionController::Base.param_parsers.deleteMime::XMLRails3.0中的等价物是什么? 最佳答案 根据CVE-2013-0156的最新安全公告你可以将它用于Rails3.0。3.1和3.2ActionDispatch::ParamsParser::

  5. ruby - 如何使用 Nokogiri::XML::Builder 生成动态标签? - 2

    我正在遍历数组中的一组标签名称,我想使用构建器打印每个标签名称,而不是求助于“我认为:builder=Nokogiri::XML::Builder.newdo|xml|fortagintagsxml.tag!tag,somevalendend会这样做,但它只是创建名称为“tag”的标签,并将标签变量作为元素的文本值。有人可以帮忙吗?这个看起来应该比较简单,我刚刚在搜索引擎上找不到答案。我可能没有以正确的方式提问。 最佳答案 尝试以下操作。如果我没记错的话,我添加了一个根节点,因为Nokogiri需要一个。builder=Nokogi

  6. ruby - 如何让 Nokogiri 解析并返回 XML 文档? - 2

    这是一些奇怪的例子:#!/usr/bin/rubyrequire'rubygems'require'open-uri'require'nokogiri'print"withoutread:",Nokogiri(open('http://weblog.rubyonrails.org/')).class,"\n"print"withread:",Nokogiri(open('http://weblog.rubyonrails.org/').read).class,"\n"运行此返回:withoutread:Nokogiri::XML::Documentwithread:Nokogiri::

  7. ruby - 模式加载时出现 Nokogiri::XML::Schema SyntaxError - 2

    我正在尝试加载SAML协议(protocol)架构(具体来说:https://www.oasis-open.org/committees/download.php/3407/oasis-sstc-saml-schema-protocol-1.1.xsd),但在执行此操作之后:schema=Nokogiri::XML::Schema(File.read('saml11_schema.xsd'))我得到这个输出:Nokogiri::XML::SyntaxErrorException:Element'{http://www.w3.org/2001/XMLSchema}element',att

  8. ruby - 如何更改 Sinatra 中的日志级别 - 2

    我正在使用此代码在我的Sinatra应用程序中启用日志记录:log_file=File.new('my_log_file.log',"a")$stdout.reopen(log_file)$stderr.reopen(log_file)$stdout.sync=true$stderr.sync=true实际的日志记录是使用:logger.debug("Startingcall.Params=#{params.inspect}")事实证明,只有INFO或更高级别的日志消息被记录,而DEBUG消息没有被记录。我正在寻找一种将日志级别设置为DEBUG的方法。 最佳

  9. ruby - 堆栈级别太深(SystemStackError) - 2

    我有Sinatra应用程序,需要测试我的应用程序。features/support/env.rb:require_relative"../../application"require"capybara"require"capybara/cucumber"require"rspec"WorlddoCapybara.app=ApplicationincludeCapybara::DSLincludeRSpec::Matchersendfeatures/one.feature:Feature:TesthomepageInordertomakesurepeoplecanopenmysiteIw

  10. ruby-on-rails - ActiveSupport::DescendantsTracker.descendants 不返回后代 - 2

    这个问题与另一个关于LookingupallthedescendantsofaclassinRuby的堆栈溢出问题类似/相关.一个很好的问题,里面充满了我正在寻找的信息——除了当我进入Rails控制台时:irb(main):001:0>ActiveSupport::DescendantsTracker.descendants(Object)=>[]irb(main):002:0>ObjectSpace.each_object(Class).select{|klass|klass[IRB::Notifier::AbstractNotifier,IRB::Notifier::ErrUnre

随机推荐