简体   繁体   English

使用FLWOR从所选节点中删除xml子元素

[英]Delete a xml child element from a selected node using FLWOR

I'm trying to remove the "number" child element with: @tsip:form="wila" from the "applications" node below using a flwor query. 我正在尝试使用flwor查询从以下“应用程序”节点中删除@number子元素:@tsip:form =“ wila”。 The data is in an Oracle 11g database, in a xml_type column, Oracle uses xquery 1.0. 数据位于Oracle 11g数据库的xml_type列中,Oracle使用xquery 1.0。 I've managed to accomplish this below but my attempt is very clumsy and long winded as I have hard coded the intermediate elements between the parent "applications" element and the child "number" element , so if the format of the xml changes my query may not work. 我已经设法在下面完成此操作,但是由于我已经硬编码了父“应用程序”元素和子“数字”元素之间的中间元素,因此我的尝试非常笨拙且漫长,所以如果xml的格式更改了我的查询,可能不起作用。 Can anyone offer a more generic solution. 任何人都可以提供更通用的解决方案。 It must be easier than this: 它一定比这更容易:

Create a table: 创建一个表:

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

Insert some data into XML_DOCUMENT_TMP: 将一些数据插入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>
');

Select all the data except the "number" element with @tsip:form="wila" 使用@tsip:form =“ wila”选择除“ number”元素以外的所有数据

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;

In XQuery you can use a recursive function to visit each node and test if that node should be removed. 在XQuery中,您可以使用递归函数访问每个节点并测试是否应删除该节点。 If it should be removed, you do nothing, if it should not be removed you make a copy of it as a new node with the same name element {node-name(.)} { ... and continue visiting its children: 如果应删除它,则不执行任何操作,如果不删除它,则将其复制为具有相同名称element {node-name(.)} { ...的新节点,然后继续访问其子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)

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

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