【问题标题】:XPath to produce a result node-set containing the same node more than once?XPath 生成包含同一节点的结果节点集不止一次?
【发布时间】:2010-10-17 07:41:14
【问题描述】:

我想在标题中说的是:

鉴于我知道某个特定元素只出现一次的一些 XML,是否可以使用 single XPath 查询来选择包含该元素两次的节点集?

我知道有一个“联合”运算符 (|) 但这基本上是一个逻辑或,对吗?在 SQL 术语中,我正在寻找相当于“union all”的东西。

例如给定 XML 片段...

<toplevel>
  <ElementIWant>
    <SomeSubElement1>specific data</SomeSubElement1>
    <SomeSubElement2>specific data 2</SomeSubElement2>
  </ElementIWant>
</toplevel>

...是否有一个查询可以让我获得相当于...的结果集

<ElementIWant>
  ...identical content...
</ElementIWant>
<ElementIWant>
  ...identical content...
</ElementIWant>

我还没有找到任何让我认为可以做到的事情 - 但这就是我要问的原因......

【问题讨论】:

    标签: xml xslt xpath


    【解决方案1】:

    正如其他答案所指出的,XPath 无法修改 XML 文档并生成新节点

    由于"set" 的定义,任何节点只能参与一次节点集。

    但是,XPath 2.0 为我们提供了新的sequence type,它允许重复项目。

    为了让一个元素在一个序列中出现两次,只需使用the sequence concatenation operator ",",如下所示:

    /*/ElementYouWant, /*/ElementYouWant

    像这样简单地将其放入 XSLT2.0 样式表中:

    <xsl:stylesheet version="2.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:xs="http://www.w3.org/2001/XMLSchema"
     xmlns:f="http://fxsl.sf.net/"
     exclude-result-prefixes="f xs"
     >
    
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
    
     <xsl:template match="/">
       <t>
         <xsl:sequence select=
          "/*/ElementYouWant, /*/ElementYouWant"/>
       </t>
     </xsl:template>
    </xsl:stylesheet>
    

    并将此转换应用于此 XML 文档:

    <toplevel>
        <ElementYouWant>
            <SomeSubElement1>specific data</SomeSubElement1>
            <SomeSubElement2>specific data 2</SomeSubElement2>
        </ElementYouWant>
    </toplevel>
    

    产生想要的结果:

    <t>
       <ElementYouWant>
                <SomeSubElement1>specific data</SomeSubElement1>
                <SomeSubElement2>specific data 2</SomeSubElement2>
          </ElementYouWant>
       <ElementYouWant>
                <SomeSubElement1>specific data</SomeSubElement1>
                <SomeSubElement2>specific data 2</SomeSubElement2>
          </ElementYouWant>
    </t>
    

    请注意,如果使用&lt;xsl:sequence&gt; 指令,则不会创建&lt;ElementYouWant&gt; 元素的新副本——因此在XSLT 2.0 中建议使用&lt;xsl:sequence&gt; 并避免使用&lt;xsl:copy-of&gt;,它会创建(不必要的)节点副本。

    【讨论】:

    • 大坝,我将不得不重新学习 xpath。 :) 感谢您的提醒。
    【解决方案2】:

    XPath 是一种在 XML 文档中查询数据的语言,而 SQL UNION ALL 语法结合了来自两个不同查询的结果集。

    XPath 本身不能用于以与现有格式不匹配的格式呈现现有数据。但是,您可以使用 XSLT 来执行此转换:

    <x:stylesheet version="1.0" xmlns:x="http://www.w3.org/1999/XSL/Transform">
      <x:output method="xml"/>
    
      <x:template match="/">
        <topMostLevel>
          <x:apply-templates />
        </topMostLevel>
      </x:template>
    
      <x:template match="toplevel">
        <x:copy-of select="."/>
        <x:copy-of select="."/>
      </x:template>
    </x:stylesheet>
    

    【讨论】:

      【解决方案3】:

      XPath 为您提供 node-sets,因此根据定义,节点只出现一次。 现在,您可以命名模板并使用相同的 XPath 调用它两次。

      <xsl:template match="/ElementIWant"> 
        <xsl:call-template name="repeat"/>
        <xsl:call-template name="repeat"/>
      </xsl:template>
      
      <xsl:template name="repeat"> 
        <xsl:copy select=".">
          <xsl:text>... same content ...</xsl:text>
        </xsl:copy>
      </xsl:template>
      

      【讨论】:

      • 好吧,这是唯一的方法;-)
      • 干杯(两者)。下次我会尽量记住这一点,只是有时,术语可以帮助我们!
      猜你喜欢
      • 2021-06-09
      • 2011-07-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-18
      • 1970-01-01
      • 2011-11-20
      相关资源
      最近更新 更多