2016-11-27 10 views
0

検索するノードの名前を指定する文字列に基づいて、子ノードのサブセットを返すことができるXQuery関数が必要です。以下のような定義を満たす必要があり、任意の文書を扱う必要がある場合。私はその後、関数は$ includedNodesで指定された名前の子ノードのみが返されるように文書を変換する必要があり、いくつかのXML文書にMarkLogic XML文書をXQueryの文字列に基づいて動的に書き直します

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

を持っていた考える

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

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に非常に有用であり、再帰的なアイデンティティの種類は、あなたが質問の孫の一部を処理できるようにする必要があります変換を示しています。

関連する問題