2016-10-24 5 views
0

flwor 쿼리를 사용하여 아래의 "applications"노드에서 @tsip : form = "wila" 과 함께 "number"자식 요소를 제거하려고합니다. 데이터는 Oracle 11g 데이터베이스에 있으며, xml_type 열에서 Oracle은 xquery 1.0을 사용합니다. 나는 이것을 아래에서 달성 할 수 있었지만 부모의 "applications"엘리먼트와 자식 "number"엘리먼트 사이의 중간 엘리먼트를 하드 코딩했기 때문에 나의 시도는 매우 서투르고 길다. 그래서 xml의 포맷이 내 쿼리를 변경하면 작동하지 않을 수 있습니다. 누구나 좀 더 일반적인 솔루션을 제공 할 수 있습니까? FLWOR을 사용하여 선택한 노드에서 xml 하위 요소 삭제

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와 "수"요소를 제외한 모든 데이터를 선택 :

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로 일부 데이터를 삽입 :

테이블을 만듭니다 이것보다 더 쉽게해야합니다 : 양식 = "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; 

답변

1

XQuery에서 재귀 functi 각 노드를 방문하여 해당 노드를 제거해야하는지 테스트하십시오. 이를 제거해야하는 경우는 같은 이름 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) 
+0

감사하지만 '아무튼 "wila"속성을 가진 number 요소를 제거하는 것처럼 보입니까? –

+0

음, 그래야합니다. 아마도'$ a'가 단지 하나의 문서가 아니라면 문서가 아닙니다. 이 경우 마지막 줄에'$ a/*'를 입력하십시오 – BeniBela

+0

그게 전부입니다, 고마워요. 재귀 함수 솔루션이 새로 생겼지 만 재귀 함수가 싫다. –