0

私はxqueryを初めて使用します。私は次のxmlドキュメントを持っています:

<?xml version="1.0" encoding="UTF-8"?>
     <lines>
        <line>
            <id>1</id>
            <par>1</par>
        </line>
        <line>
            <id>2</id>
            <par>1</par>
        </line>
        <line>
            <id>3</id>
            <par>2</par>
        </line>
        <line>
            <id>4</id>
            <par>2</par>
        </line>
        <line>
            <id>5</id>
            <par>1</par>
        </line>
        <line>
            <id>6</id>
            <par>5</par>
        </line>
        <line>
            <id>7</id>
            <par>5</par>
        </line>
        <line>
            <id>8</id>
            <par>5</par>
        </line>
    </lines>

特定のIDを入力として取得し、入力として指定されたものを含む、このIDの子孫であるすべての行要素を返す関数を作成したいと思います。たとえば、入力1として指定すると、IDが1、2、3、4、5、6、7、8のライン要素が返されます。次を使用して深度1に進むことができることはわかっていますlines/line[par=id_given]が、すべての子孫をフェッチしたい場合はどうなりますか?

4

1 に答える 1

0

ツリーを再帰的にトラバースする関数を定義する必要があります。これはレベルごとに機能します:

declare function local:traverse($tree as element(lines), $id as xs:integer*) as element(line)* {
 let $level := $tree//line[par=$id][id!=$id]
 return
  if ($level)
  then ($level, local:traverse($tree, $level/id))
  else ()
};

を使用して呼び出すことができますlocal:traverse(/lines, 0)

ただし、これはツリーではないため、この関数はサンプルXMLを処理しません。ルート要素に許可されていないサイクルがあります。実際のツリーを作成するには、新しい一意のルートIDを導入するか、ルートから親を削除する必要があります。

<lines>
    <line>
        <id>1</id>
        <par>0</par>
    </line>
    [snip]

上記のコードを変更して、これらの自己参照を処理できるようにすることもできます。[id!=$id]の定義の最後に述語を追加し$levelます。これにより、自己参照が除外されます。これで、ルートノードが結果から除外され、関数呼び出しに再度含めます(/lines/line[id=1], local:traverse(/lines, 1))

于 2012-05-17T20:35:53.687 に答える