2016-11-27 1 views
0

검색 할 노드의 이름을 지정하는 문자열 배열을 기반으로 문서를 다시 작성할 수있는 XQuery 함수가 필요합니다. 특히 자식 노드의 하위 집합을 반환 할 수 있어야합니다. 아래의 정의를 만족해야하고 임의의 문서를 사용해야합니다.XQuery의 문자열을 기반으로 MarkLogic XML 문서를 동적으로 다시 작성하십시오.

local:apply-node-includes($document, $includedNodeNames as xs:string*) 

것은 내가 그런 다음 함수는 이름 만 자식 노드가 includedNodes이 반환 $을에서 지정하도록 문서를 변환해야합니다 일부 XML 문서를

let $doc := 
    <foo a="b"> 
    <bar>hello</bar> 
    <baz>1</baz> 
    <bang> 
     <text>world</text> 
    </bang> 
    </foo>') 

했다 감안할 때.

local:apply-node-includes($doc, 'baz')

<foo a="b"> 
    <bar>hello</bar> 
    <bang> 
    <text>world</text> 
    </bang> 
</foo> 

내가 노드 반복 실험을 반환

<foo a="b"> 
    <baz>1</baz> 
</foo> 

local:apply-node-includes($doc, ('bar','bang')))를 반환, 및/또는 재귀 typeswitch의 일부 양식을 사용하지만, 지금까지 얻을 수 없었던 것 맞아. 'bang.text'는 손자 노드 만 포함하고 형제는 포함하지 않을 수도 있지만 어쩌면 너무 많이 묻는 것입니다.

+1

함수가 문자열이 아닌 xs : QNames 시퀀스를 사용하는 것을 고려하십시오. XML은 기본 네임 스페이스를 사용하기 때문에 작동하지만 네임 스페이스가있는 경우 문제가 발생합니다. –

답변

1

가장 세련된 해결책인지는 모르지만 요구 사항을 충족하는 것으로 보입니다. 여기에있는 함수는 전달 된 문서의 루트 요소를 다시 만든 다음 전달 된 목록의 문자열과 일치하는 요소 이름을 갖는 모든 직계 자식 요소 (및 모든 특성과 하위 요소)를 포함합니다.

declare function local:apply-node-includes($doc as item(), $includedNodeNames as xs:string*) as item() 
{ 
    (: Recreate the root element :) 
    element {name($doc)} 
    { (: Replicate root element's attributes :) 
    (for $attribute in $doc/@* return $attribute), 
    (: Replicate root element's immediate children having any of given names :) 
    (for $element in $doc/* where name($element) = $includedNodeNames 
     return $element) 
    } 
}; 

let $doc := 
    <foo a="b"> 
    <bar>hello</bar> 
    <baz>1</baz> 
    <bang> 
     <text>world</text> 
    </bang> 
    </foo> 
return local:apply-node-includes($doc, ('bar','bang')) 

는 출력 :

<foo a="b"><bar>hello</bar><bang><text>world</text></bang></foo> 
+0

나는 그 오타를 바로 잡았고 그 해답을 주셔서 감사합니다. 나는 너의 것을 받아 들였지만 다른 사람들이 따를 수 있도록 세련된 버전을 게시했다. – alastairtree

1

@DavidDeneberg은 꽤 좋은 대답을했다,하지만 난 더 그렇게 다른 사람을 위해 게시 일부 XPath를 사용하여 간단하게 할 수 있었다.

declare function local:apply-node-includes($doc as element(), $includedNodeNames as xs:string*) as element()? 
{ 
    element {node-name($doc) } 
    { 
    $doc/@*, 
    $doc/*[name(.)=$include-names] 
    } 
}; 

또한이 책은 주제 https://en.wikibooks.org/wiki/XQuery/Filtering_Nodes에 매우 유용하며 재귀 정체성의 종류는 당신이 질문의 손자 부분을 처리 할 수 ​​있어야합니다 변환을 보여줍니다.

관련 문제