1

たとえば、次の XML を指定します。

<root>
    <item>
        <id>111</id>
        <description>aisle 12, shelf 3</description>
        <description>inside the box</description>
    </item>
</root>

結果が欲しい:

<root>
    <item>
        <id>111</id>
        <description>aisle 12, shelf 3 inside the box</description>
    </item>
</root>

ただし、ノードには任意の名前を付けることができ、任意のレベルにある可能性があります。タグが繰り返される限り、同じクエリが異なる XML で機能することを望みます。

<root>
    <item>
        <id>112</id>
        <attributes>
            <author>Joe Smith</author>
            <author>Arthur Clarke</author>
            <author>Jeremiah Wright</author>
        </attributes>
    </item>
</root>

出力:

<root>
    <item>
        <id>112</id>
        <attributes>
            <author>Joe Smith Arthur Clarke Jeremiah Wright</author>
        </attributes>
    </item>
</root>

これは BaseX で可能ですか? そうでない場合、既知の要素 (たとえば、/root/item/attributes/author のみ) を指定してこれを行うことはできますか?

4

1 に答える 1

0

兄弟の直後にのみマージすることを保証すると、少し複雑になります。以下のコードがどのように機能するかについて、いくつかのコメントを追加しました。

let $xml := document{<root>
    <item>
        <id>112</id>
        <attributes>
            <author>Joe Smith</author>
            <author>Arthur Clarke</author>
            <author>Jeremiah Wright</author>
            <foo/>
            <author>Donald Duck</author>
        </attributes>
    </item>
</root>}
return
  (: Use an XQuery Update transformation :)
  copy $copy := $xml
  modify (
    (: Loop over all leaves (only containing text nodes. :)
    (: This might have to be adjusted if you want to merge arbitrary nodes. :)
    for $leaf in $copy//*[not(*)]
    (: Where the preceding node is not of the same name :)
    (: (as it will be merged anyway) :)
    where not($leaf/preceding-sibling::*[1 and name(.) eq name($leaf)])
    (: Now find following siblings... :)
    let $siblings := $leaf/following-sibling::*[
      (: ... of the same name ... :)
      name(.) eq name($leaf) and
      (: ... and that do not have a node with another name in-between :)
      not(preceding-sibling::*[name(.) != name($leaf) and $leaf << .])
    ]
    return (
      (: Merge text contents into $leaf :)
      replace value of node $leaf with string-join(($leaf, $siblings), ' '),
      (: And delete all others :)
      delete nodes $siblings
    )
  )
  return $copy
于 2014-07-28T08:07:10.050 に答える