2016-11-02 17 views
0

下のコードでは、oldXmlにoldXml2の "name"要素を挿入し、oldXmlの "test"属性値を "newTest"に更新しようとしています。出力はnewXmlです。それが動作しなくなったoldXml2からname要素を取得するためにOracle XMLQueryでの "Transform"とFLWOR式の結合

let $newName := $b/users/user/name 

句:私が追加したときに コードが成功し、属性値を変更しますが。 誰かがこの問題の解決策を持っていますか?

私はxquery 1.0を使用するOracle 11gを使用しています。

WITH myXml AS (select 1 id, xmltype(
'<users> 
    <user test="oldvalue"> 
    <userid>id1</userid> 
    <name>dave</name> 
    </user> 
</users> 
' 
) oldXml 
from dual), 
myXml2 AS (select 1 id,xmltype(
'<users> 
    <user> 
    <userid>id2</userid> 
    <name>steve</name> 
    </user> 
</users> 
' 
) oldXml2 
from dual) 
    SELECT oldXml,oldXml2, 
XMLQuery(' copy $c := $a 
     (: let $newName := $b/users/user/name :) (: If you add this clause it doesnt work:) 
     modify (rename node $c/users/user/@test as "newTest") 
     return $c' 
       PASSING a.oldXml as "a" ,b.oldXml2 as "b" RETURNING CONTENT) newXml 
    FROM myXml a 
    JOIN myXml2 b 
    ON a.id = b.id; 

newXmlで必要な出力は次のようになります。あなたがlet最初に行うと、それをあなたがコピー/変更しないその中で、独自のreturn句を、与える必要が

<users> 
     <user test="newTest"> 
      <userid>id1</userid> 
      <name>dave</name> 
     </user> 
     <user> 
      <userid>id2</userid> 
      <name>steve</name> 
     </user> 
</users> 
+0

)'行方不明... – Shnugo

+0

あなたがしている最終的な結果はどのようなものです:Xqueryのを作る - あなたの本当のシナリオで達成しようとしている? 2つの入力XMLは表示されていますが、出力XMLは表示されません。どのようにnewNameを使用する予定かわかりません--daveをsteveに変更します(ただし、useridだけを残しますか?)か、1人のユーザーに対して2つの名前ノードを使用しますか? –

+0

Alex - 必要な出力を追加しました –

答えて

1

SELECT oldXml, oldXml2, 
    XMLQuery(' 
    let $newName := $b/users/user/name 
    return 
     copy $c := $a 
     modify (rename node $c/users/user/@test as "newTest") 
     return $c' 
    PASSING a.oldXml as "a", b.oldXml2 as "b" RETURNING CONTENT) newXml 
FROM myXml a 
JOIN myXml2 b 
ON a.id = b.id; 

コピー/変更部分内の$newNameを参照できますが、使用方法が明確ではありません。実際のコードがforループ内にある場合を除き、$b/users/user/nameを直接参照するのではなく、その変数を使用する理由があります。


あなたが直接$b/users/userノードを挿入することができ、あなたがやりたいletは必要ありません。 XMLSERIALIZEでちょうど出力をフォーマットする:

SELECT oldXml, oldXml2, 
    XMLSerialize(CONTENT XMLQuery(' 
    copy $c := $a 
    modify (rename node $c/users/user/@test as "newTest", 
     insert nodes $b/users/user after $c/users/user) 
    return $c' 
    PASSING a.oldXml as "a", b.oldXml2 as "b" RETURNING CONTENT) 
    AS VARCHAR2(4000) INDENT SIZE=2) newXml 
FROM myXml a 
JOIN myXml2 b 
ON a.id = b.id; 

OLDXML       OLDXML2      NEWXML       
------------------------------ ------------------------------ ------------------------------ 
<users>      <users>      <users>      
    <user test="oldvalue">   <user>       <user newTest="oldvalue"> 
    <userid>id1</userid>   <userid>id2</userid>   <userid>id1</userid>  
    <name>dave</name>    <name>steve</name>    <name>dave</name>   
    </user>      </user>      </user>      
</users>      </users>       <user>      
                    <userid>id2</userid>  
                    <name>steve</name>   
                   </user>      
                   </users>      

あなたはそれがこの例ではあなたに何かを獲得必ずreturnを追加した場合の答えの最初の部分のように、letを使用しますが、することはできません - 多分それはより便利です私は、OracleのXMLのアプローチに慣れていないんだけど、私は( `/テキストがあると思い

let $newUser := $b/users/user 
return 
    copy $c := $a 
    modify (rename node $c/users/user/@test as "newTest", 
    insert nodes $newUser after $c/users/user) 
    return $c 
+0

はい、実際のシナリオでは便利です。 1つの行方不明の "return"キーワードと私は立ち往生した。どうもありがとう。 –