2

我正在尝试使用 flwor 查询从下面的“应用程序”节点中删除“数字”子元素:@tsip:form="wila"。数据位于 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;
4

1 回答 1

3

在 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)
于 2016-10-24T13:33:16.900 回答