0

Xqueryの再帰関数の演習で問題が発生しました。Xqueryのみを使用してフラットXMLツリーをネストされたXMLツリーに変換する必要があります。

フラットXMLは次のようになります。

    <?xml version="1.0"?>
    <tree>
      <node id="1" type="Folder">
        <child>2</child>
        <child>3</child>
      </node>
      <node id="2" type="Folder">
        <child>4</child>
      </node>
      <node id="3" type="Folder">
        <child>5</child>
        <child>6</child>
      </node>
      <node id="4" type="Item" />
      <node id="5" type="Folder">
        <child>7</child>
      </node>
      <node id="6" type="Item" />
      <node id="7" type="Item" />
    </tree>

必要なネストされたXMLは次のようになります。

    <?xml version="1.0"?>
    <tree>
      <node id="1" type="Folder" children="2 3">
        <node id="2" type="Folder">
          <node id="4" type="Item" />
        </node>
        <node id="3" type="Folder">
          <node id="5" type="Folder" children="7">
            <node id="7" type="Item" />
          </node>
          <node id="6" type="Item" />
        </node>
      </node>
    </tree>

私は再帰関数なしでこれをXqueryしようとしましたが、あまり運がありませんでした。特に条件付けは私には奇妙に思えます。新しいネストされたXMLのルート要素は、他の要素の子として存在しないため、id="1"のノードである必要があります。ただし、これを条件として指定しようとすると、たとえば以下のように、そのノードを選択するだけでは不十分なようです。

    for $node in /Tree/node[@id != /Tree/node/child]
    return
    <node id="{data($node/@id)}" type="{data($node/@type)}">

            (: Lower level subqueries.... :)

    </node>

更新:私はさらに進んでいますが、親ノードの内容と等しいIDを持つノードの選択に関する[条件]で立ち往生しています。つまり、再帰関数のforステートメントは予期しないノードをバックします。

これはこれまでの私のコードです:

    declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization";
    declare namespace local = "localhost";
    declare option output:method "xml";
    declare option output:omit-xml-declaration "no";
    declare option output:indent "yes";
    declare option output:doctype-system "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd";

    declare function local:addSubNode($n)
    {
        for $subnode in doc("xml/flat-tree.xml")/tree/node[@id = $n]
            let $subnid:=data($subnode/@id)
            let $subtype:=data($subnode/@type)
        return <node id="{$subnid}" type="{$subtype}">
                {local:addSubNode($subnid)}
                </node>
        };

    <tree>

    {
    for $node in doc("xml/flat-tree.xml")/tree/node[not(@id = /tree/node/child)]
    let $nid:=data($node/@id)

    return <node id="{$nid}" type="{data($node/@type)}"> 
        {for $child in $node
        let $cid:=data($child)
        return local:addSubNode($cid)
        }

            </node>
    }

    </tree>
4

2 に答える 2

0

部分的な答えです。アトミック値をシーケンス=!=比較できますが、各項に対して論理ORとして機能します。つまり、「a = b」は「bにaに等しい値がある」ことを意味し、「a!= b」は「bにaに等しくない値がある」ことを意味します。これは、探しているものではありません。 。「not(a = b)」である「aに等しいbの値はありません」が必要です。

for $node in $d/node[not(@id = $d/node/child)] return
<node id="{$node/@id}" type="{$node/@type}">
    (: etc. :)
</node>
于 2012-07-10T15:57:58.267 に答える
0

はい、わかった!最終的に、id属性だけでなく、$nodeまたは$child要素全体を再帰関数にフィードしました。これで機能します。

    declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization";
    declare namespace local = "localhost";
    declare option output:method "xml";
    declare option output:omit-xml-declaration "no";
    declare option output:indent "yes";
    declare option output:doctype-system "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd";

    (:lookupChildren function :)
    declare function local:lookupChildren($p)
    {
    for $child in $p/child
    return $child
    };

    declare function local:addSubNode($n)
    {
    for $subnode in doc("xml/flat-tree.xml")/tree/node
            let $subnid:=data($subnode/@id)
            let $subtype:=data($subnode/@type)
    where $subnode/@id = $n/child
        return 
        <node id="{$subnid}" type="{$subtype}" children="{local:lookupChildren($subnode)}">
               {local:addSubNode($subnode)}
                </node>
    };

    <tree>

    {
    for $node in doc("xml/flat-tree.xml")/tree/node[not(@id = /tree/node/child)]
    let $nid:=data($node/@id)
    let $ntype:=data($node/@type)

    return  <node id="{$nid}" type="{$ntype}" children="{local:lookupChildren($node)}"> 
            {local:addSubNode($node)}

            </node>
    }

    </tree>
于 2012-07-12T08:21:49.897 に答える