将节点及其后代从父级移动到兄弟级

时间:2014-04-02 12:52:18

标签: sql xml oracle xquery xquery-update

我有一个XML树,如下所示:

<root>
    <a>
        <a1>A1</a1>
        <a2>A2</a2>
        ...
        ...
        <an>An</an>
    </a>
    <b>
        <b1>B1</b1>
        <b2>B2</b2>
        ...
        ...
        <bm>Bm</bm>
    </b>
    <x>
        <x1>X1</x1>
        <x2>X2</x2>
        ...
        ...
    </x>
    <y>
        ...
        ...
    </y>
    ...
    ...
</root>

使用Oracle XMLQuery和XQuery,我想将此XML更改为:

<root>
    <a>
        <a1>A1</a1>
        <a2>A2</a2>
        ...
        ...
        <an>An</an>
        <b>
            <b1>B1</b1>
            <b2>B2</b2>
            ...
            ...
            <bm>Bm</bm>
        </b>
    </a>
    <x> <!-- This x node and all its siblings have to stay where they are. -->
        <x1>X1</x1>
        <x2>X2</x2>
        ...
        ...
    </x>
    <y>
        ...
        ...
    </y>
    ...
    ...
</root>

简而言之,我想通过追加将整个b节点及其后代放在a下。

到目前为止我尝试的是:

WITH xdata AS (
SELECT XMLTYPE('<root>
                    <a>
                        <a1>A1</a1>
                        <a2>A2</a2>
                    </a>
                    <b>
                        <b1>B1</b1>
                        <b2>B2</b2>
                    </b>
                    <x>
                        <x1>X1</x1>
                        <x2>X2</x2>
                    </x>
                </root>') AS xmldata
  FROM dual
)
SELECT XMLQuery ('for $a in $x1/root/a, $b in $x1/root/b
                  return <root>{$a}{$b}</root>'
                 PASSING x.xmldata AS "x1" RETURNING CONTENT) AS output
  FROM xdata x;

这显然给了我一个非常错误的结果。也许我正在尝试的是完全错误的。请帮忙。

1 个答案:

答案 0 :(得分:1)

SQL> WITH xdata AS (
  2  SELECT XMLTYPE('<root>
  3                      <a>
  4                          <a1>A1</a1>
  5                          <a2>A2</a2>
  6                      </a>
  7                      <b>
  8                          <b1>B1</b1>
  9                          <b2>B2</b2>
 10                      </b>
 11                  </root>') AS xmldata
 12    FROM dual
 13  )
 14  SELECT XMLQuery ('for $v in $x1/root return <root><a>{$x1//root/a/*}{$x1//root/b}</a></root>'
 15                   PASSING x.xmldata AS "x1" RETURNING CONTENT) AS output
 16    FROM xdata x;

OUTPUT                                                                          
--------------------------------------------------------------------------------
<root><a><a1>A1</a1><a2>A2</a2><b><b1>B1</b1><b2>B2</b2></b></a></root>    

对于更复杂的案例:

SQL> WITH xdata AS (
  2  SELECT XMLTYPE('<root>
  3                      <a>
  4                          <a1>A1</a1>
  5                          <a2>A2</a2>
  6                      </a>
  7                      <b>
  8                          <b1>B1</b1>
  9                          <b2>B2</b2>
 10                      </b>
 11                      <x>
 12                          <x1>X1</x1>
 13                          <x2>X2</x2>
 14                      </x>
 15                      <y>
 16                          <y1>Y1</y1>
 17                          <y2>Y2</y2>
 18                      </y>
 19                  </root>') AS xmldata
 20    FROM dual
 21  )
 22  SELECT XMLQuery ('for $v in $x1/root
 23  return <root><a>{$x1/root/a/*}{$x1/root/b}</a>
 24  {for $t in $x1/root/* where $t!=$v/a and $t!=$v/b return $t}</root>'
 25  PASSING x.xmldata AS "x1" RETURNING CONTENT) AS output
 26  FROM xdata x
 27  /

OUTPUT                                                                          
--------------------------------------------------------------------------------
<root><a><a1>A1</a1><a2>A2</a2><b><b1>B1</b1><b2>B2</b2></b></a><x><x1>X1</x1><x
2>X2</x2></x><y><y1>Y1</y1><y2>Y2</y2></y></root>