【问题标题】:XQuery that selects node but omits returning child nodes选择节点但忽略返回子节点的 XQuery
【发布时间】:2011-07-06 18:10:18
【问题描述】:

我正在尝试创建一个 xquery 表达式,它将返回选定的节点但不会返回它们的子节点。这可能最好用一个例子来说明。我有以下 myNode 节点:

<myNode>
  <myElements id="1">
    <myElement key="one">aaa</myElement>
    <myElement key="two" >bbb</myElement>
    <myElement key="three">ccc</myElement>
  </myElements>
  <myElements id="2">
    <myElement key="one">ddd</myElement>
    <myElement key="two" >eee</myElement>
    <myElement key="three">fff</myElement>
  </myElements>
</myNode>

我有兴趣返回 节点,但没有更低的。我想要的回报如下所示:

<myNode>
  <myElements id="1" />
  <myElements id="2" />
</myNode>

<myNode>
  <myElements id="1"></myElements>
  <myElements id="2"></myElements>
</myNode>

我目前有一个 xpath 表达式,看起来类似于以下内容(为此图进行了简化),正如预期的那样,它正在返回 myElement 子项:


$results/myNode/MyElements

我是不是找错树了?这在 XPath/XQuery 中是否可行?

【问题讨论】:

标签: xml xslt xpath xquery


【解决方案1】:

试试这个递归算法..

    xquery version "1.0";

    declare function local:passthru($x as node()) as node()* {   for $z in $x/node() return local:recurseReplace($z) };

    declare function local:recurseReplace($x as node()) {
        typeswitch ($x) 
            (: Changes based on a condition :)
            case element(myElements) return <myElements id="{$x/@id}" />
            (: IGNORE ANY CHANGES :)
            case text() return $x
            case comment() return comment {"an altered comment"}
            case element() return element {fn:node-name($x)} {for $a in $x/attribute()
                                                              return $a, local:passthru($x)}
            default return ()           
};

    let $doc := 
<myNode>   
  <myElements id="1">
        <myElement key="one">aaa</myElement>
        <myElement key="two" >bbb</myElement>
        <myElement key="three">ccc</myElement>   
  </myElements>   
  <myElements id="2">
        <myElement key="one">ddd</myElement>
        <myElement key="two" >eee</myElement>
        <myElement key="three">fff</myElement>   
  </myElements> 
</myNode> 
return local:recurseReplace($doc)

【讨论】:

    【解决方案2】:

    XQuery 在此类任务上远不如 XSLT:

    <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:template match="node()|@*">
      <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
     </xsl:template>
    
     <xsl:template match="myElements/node()"/>
    </xsl:stylesheet>
    

    当此转换应用于提供的 XML 文档时:

    <myNode>
        <myElements id="1">
            <myElement key="one">aaa</myElement>
            <myElement key="two" >bbb</myElement>
            <myElement key="three">ccc</myElement>
        </myElements>
        <myElements id="2">
            <myElement key="one">ddd</myElement>
            <myElement key="two" >eee</myElement>
            <myElement key="three">fff</myElement>
        </myElements>
    </myNode>
    

    产生了想要的正确结果:

    <myNode>
      <myElements id="1" />
      <myElements id="2" />
    </myNode>
    

    说明:标识规则,为myElements的子节点覆盖

    【讨论】:

    • +1 我同意 XSLT 是一种更适合此类任务的技术。
    【解决方案3】:

    XQuery is 只返回顶级节点,它不返回它们的子节点。但是返回的节点仍然连接到它们的子节点,无论显示结果的代码是选择在您实际选择的节点下显示完整的子树。

    因此,了解您的问题的第一步是要意识到您不希望通过查询从源文档中选择节点,而是希望它通过具有不同的子节点来构造与原始节点不同的新节点。

    这意味着它是您希望生成与原始文档相同但有一些小的更改的结果文档的查询之一。正如 Dimitre 所说,XSLT 在这类问题上比 XQuery 好得多。但正如 Scott 所示,这当然可以使用 XQuery 完成。

    【讨论】:

      【解决方案4】:

      试试这是最短的方法

      let $a := 
      <myNode>
        <myElements id="1">
          <myElement key="one">aaa</myElement>
          <myElement key="two" >bbb</myElement>
          <myElement key="three">ccc</myElement>
        </myElements>
        <myElements id="2">
          <myElement key="one">ddd</myElement>
          <myElement key="two" >eee</myElement>
          <myElement key="three">fff</myElement>
        </myElements>
      </myNode>
      
      for $e1 in $a
      return element {name($e1)}
      {
        for $e2 in $e1/*
        return element{name($e2)}{$e2/@*}
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-09-11
        • 1970-01-01
        • 1970-01-01
        • 2011-07-14
        • 1970-01-01
        相关资源
        最近更新 更多