[xquery-talk] Building a tree from sequence of maps

Andreas Mixich mixich.andreas at gmail.com
Sat Dec 21 10:14:42 PST 2019


Hi,

I feel like I try to get a hold on a piece of wet soap with this...

Background: Atom Syndication has an extension[1], which allows threading of
entries. These entries are ordered in a flat sequence, one by one.
As a result we end up with an Atom feed, that has a bunch of entries, where
each entry could have a reference to the ID of another entry, which would
then be it's parent.
No nesting is done.

A simplified input could look like this:

declare variable $local:example :=
let $xml := <xml>
  <item id="e1" />
  <item id="e2" refid="e1" />
  <item id="e3" refid="e2" />
  <item id="e4" refid="e2" />
  <item id="e5" refid="e4" />
  <item id="e6" />
</xml>

The task I want to accomplish is to create an output *tree* of *nested*
sections, resembling the natural flow of replies:

<result>
  <section id="e1">
    <section id="e2" refid="e1">
      <section id="e3" refid="e2" />
      <section id="e4" refid="e2">
        <section id="e5" refid="e4" />
      </section>
    </section>
  </section>
  <section id="e6" />
</result>

One of the many queries I tried is:

declare function local:rec($data) {
  if (empty($data))
  then ()
  else (
         let $current := head($data)
         let $children := tail($data)[@refid = $current/@id]
         return (
                  <section id="{$current/@id}">
                  {
                    $current/*
(:                  , prof:dump("current: " || $current/@id/data() || "
children: " || $children/@id/data() => string-join())
:)
                  , for $child in $children
                    return local:rec($children)
                  }
                  </section>
                  , local:rec(tail($data))
                )
       )
};

<result>
  { local:rec($local:example/item) }
</result>

Of course, this has not yet any logic, to keep out the already processed
items (besides other issues).
When I tried that, however, by removing them from the return sequence, I
found no way to break out
of scope and have that modified return sequence go back to the next
recursion.

Previous example results in this, btw.:

<section id="e1">
  <section id="e2"/>
</section>
<section id="e2">
  <section id="e3"/>
  <section id="e4"/>
  <section id="e3"/>
  <section id="e4"/>
</section>
<section id="e3"/>
<section id="e4">
  <section id="e5"/>
</section>
<section id="e5"/>
<section id="e6"/>

I can't believe, that there is no super easy way to do it. Any help would
be greatly appreciated!

-- 
Minden jót, all the best, Alles Gute,
Andreas Mixich
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://x-query.com/pipermail/talk/attachments/20191221/823b3064/attachment.html>


More information about the talk mailing list