【问题标题】:Delete a xml child element from a selected node using FLWOR使用 FLWOR 从选定节点中删除 xml 子元素
【发布时间】:2017-03-06 06:43:44
【问题描述】:

我正在尝试删除“数字”子元素: @tsip:form="wila" 从下面的“应用程序”节点使用 flwor 查询。数据位于 Oracle 11g 数据库中,在 xml_type 列中,Oracle 使用 xquery 1.0。我已经设法在下面完成了这一点,但我的尝试非常笨拙且冗长,因为我已经硬编码了父“应用程序”元素和子“数字”元素之间的中间元素,所以如果 xml 的格式改变了我的查询可能不起作用。谁能提供更通用的解决方案。 它一定比这更容易:

创建表:

CREATE TABLE XML_DOCUMENT_TMP
(
  DOCUMENT_ID   NUMBER(12)                      NOT NULL,
  XML_DATA      SYS.XMLTYPE                     NOT NULL,
  CREATED_DATE  TIMESTAMP(6)                    NOT NULL
);

在 XML_DOCUMENT_TMP 中插入一些数据:

insert into XML_DOCUMENT_TMP
(document_id,created_date,xml_data)
values(6,sysdate,'<patent  xmlns="http://schemas.xx.com/ts/20041221/tsip" 
xmlns:tsip="http://schemas.xx.com/ts/20041221/tsip" 
tsip:action="replace" tsip:cc="CA" tsip:se="2715340" tsip:ki="C">
<keepThis>data</keepThis>
<applications tsip:action="new">
    <application tsip:cc="GB" tsip:se="2338695" tsip:ki="A" tsip:priorityCode="A2">
        <applicationId>
            <number tsip:form="wila">9813397</number>
            <number tsip:form="original">9813397</number>
            <number tsip:form="tsip">000013397</number>
            <countryCode>GB</countryCode>
            <applicationYear>1998</applicationYear>
            <date>1998-06-23</date>
        </applicationId>
    </application>
</applications>
<keepThis2>data2</keepThis2>
</patent>
');

使用@tsip:form="wila" 选择除“数字”元素之外的所有数据

SELECT /*+ NO_XML_QUERY_REWRITE */ xA.document_id ,
XMLSerialize(DOCUMENT
    XMLQuery('xquery version "1.0";
      declare default element namespace  "http://schemas.xx.com/ts/20041221/tsip";
      declare namespace  tsip="http://schemas.xx.com/ts/20041221/tsip";

       <patent xmlns="http://schemas.xx.com/ts/20041221/tsip"   xmlns:tsip="http://schemas.xx.com/ts/20041221/tsip" >{$a/*:patent/@*}   
      {

         for $s in $a/*:patent/*
            return 

            if ($s = $a/*:patent/applications) 
            then    
              <applications>{$a/*:patent/applications/@*}
                <application>{$a/*:patent/applications/application/@*}
                  <applicationId> 
                  {
                    (: Use the "except" clause to remove the unwanted <number> element with the "wila" attribute value :)
                    $a/*:patent/applications/application/applicationId/* except $a/*:patent/applications/application/applicationId/number[@tsip:form="wila"] 
                  }          
                </applicationId>
              </application>
            </applications>
          else $s   
      }
      </patent>'
            PASSING xA.xml_data as "a"  
            RETURNING CONTENT) ) newXml 
 FROM XML_DOCUMENT_TMP xA            
WHERE document_id=6;

【问题讨论】:

    标签: xml oracle11g xquery flwor


    【解决方案1】:

    在 XQuery 中,您可以使用递归函数来访问每个节点并测试是否应该删除该节点。如果它应该被删除,你什么都不做,如果它不应该被删除,你将它复制为具有相同名称 element {node-name(.)} { ... 的新节点并继续访问它的子节点:

    declare namespace  tsip="http://schemas.xx.com/ts/20041221/tsip";
    declare function local:transform($root) {
      $root / (typeswitch (.)
       case element(tsip:number) return 
         if (@tsip:form = "wila") then ()
         else .
       case element() return 
          element {node-name(.)} { 
            @*, for $n in node() return local:transform($n)
          }
       default return .
      )
    };
    local:transform($a)
    

    【讨论】:

    • 谢谢你,但似乎没有删除带有“wila”属性的数字元素?
    • 嗯,应该的。除非$a 可能是一个文档,而不仅仅是一个元素。在这种情况下,请在最后一行尝试$a/*
    • 就是这样,非常感谢。我新有一个递归函数解决方案,但我讨厌递归函数。
    • local:transform() 是 oracle 专有的?
    • @NicholasSaunders 这是标准的 XQuery。为什么会是专有的? declare function local:transform... 定义函数。你可以给它起任何名字
    猜你喜欢
    • 2023-03-29
    • 1970-01-01
    • 1970-01-01
    • 2022-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多