简体   繁体   English

XPath产生一个结果节点集多次包含同一个节点?

[英]XPath to produce a result node-set containing the same node more than once?

What I tried to say in the title is: 我想在标题中说的是:

Given a bit of XML in which I know a particular element appears only once, is it possible using a single XPath query to select a node-set that contains that element twice? 给定我只知道一个特定元素仅出现一次的XML,是否有可能使用单个 XPath查询来选择两次包含该元素的节点集?

I understand there's a "union" operator (|) but that's basically a logical-OR, right? 我知道有一个“联合”运算符(|),但这基本上是逻辑或,对吗? In SQL terms I'm looking then for the equivalent of a "union all". 用SQL术语来说,我正在寻找等同于“全部联合”的东西。

Eg Given the XML fragment... 例如,鉴于XML片段...

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

...is there a query that will get me a result set equivalent to... ...是否有一个查询,将获得与...相等的结果集

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

I haven't found anything that makes me think it can be done - but that's why I'm asking... 我没有发现任何让我认为可以完成的事情-但这就是为什么我要问...

As pointed in the other answers, XPath cannot modify an XML document and produce new nodes . 正如其他答案所指出的那样,XPath无法修改XML文档并生成新节点

Any node can participate in a node-set only once, due to the definition of "set" . 由于"set"的定义,任何节点只能参与一次节点"set"

However, XPath 2.0 gives us the new sequence type , which allows items to be repeated. 但是,XPath 2.0为我们提供了新的序列类型序列类型允许重复项。

In order to have an element appearing twice in a sequence, one would just use the sequence concatenation operator "," as in the below expression: 为了使元素在序列中出现两次,只需使用序列连接运算符"," ,如下所示:

/*/ElementYouWant, /*/ElementYouWant

Put this into an XSLT2.0 stylesheet as simple as this: 像这样简单地将其放入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>

And apply this transformation on this XML document: 并将此转换应用于此XML文档:

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

to produce the wanted result: 产生想要的结果:

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

Do note, that if one uses the <xsl:sequence> instruction, no new copy of the <ElementYouWant> element is created -- therefore in XSLT 2.0 it is recommended to use <xsl:sequence> and to avoid using <xsl:copy-of> which creates (unnecessary) copies of nodes. 请注意,如果使用<xsl:sequence>指令,则不会创建<ElementYouWant>元素的新副本-因此,在XSLT 2.0中,建议使用<xsl:sequence>并避免使用<xsl:copy-of>会创建(不必要的)节点副本。

XPath gives you node- sets , so by definition nodes appear only once. XPath为您提供了节点 ,因此根据定义,节点仅出现一次。 Now, you can have named template and call it twice with same XPath. 现在,您可以命名模板并使用相同的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>

XPath is a language to query the data within an XML document while the SQL UNION ALL syntax combines resultsets from two different queries. XPath是一种查询XML文档中数据的语言,而SQL UNION ALL语法则结合了来自两个不同查询的结果集。

XPath by itself cannot be used to present the existing data in a format that does not match the existing format. XPath本身不能用于以与现有格式不匹配的格式来显示现有数据。 However, you could use XSLT to perform this transformation: 但是,您可以使用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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM