Skip to content

Instantly share code, notes, and snippets.

@wolfgangmm
Last active May 24, 2020 11:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wolfgangmm/ef6948017db8a51ecaebcb8fd56aa6e1 to your computer and use it in GitHub Desktop.
Save wolfgangmm/ef6948017db8a51ecaebcb8fd56aa6e1 to your computer and use it in GitHub Desktop.
xquery version "3.1";
declare variable $depth := 3;
declare variable $xml :=
document {
<div xml:id="d1">
<p>First <hi>section</hi> para 1</p>
<p>First <hi>section</hi> <hi>para</hi> 2</p>
<div xml:id="d2">
<p>First para in <hi>d2</hi></p>
<p>Second para in <hi>d2</hi></p>
<div xml:id="d7">
<p>First <hi>para</hi> in d7</p>
<p>Second <hi>para</hi> in <hi>d7</hi></p>
<!-- below div should be included in d7 output -->
<div xml:id="d10"/>
</div>
</div>
<div xml:id="d3">
<p>Third section</p>
<div xml:id="d4"/>
<div xml:id="d5"/>
</div>
<div xml:id="d6">
<p>Third <hi>section</hi> para 1</p>
<p>Third <hi>section</hi> <hi>para</hi> 2</p>
<div xml:id="d9"/>
</div>
<div xml:id="d8"/>
</div>
}
;
declare function local:filler($div) {
if ($div/div and count(($div/div[1])/preceding-sibling::*//*) < 2) then
$div/div[1]
else
()
};
declare function local:needs-fill($div) {
exists(local:filler($div))
};
declare function local:fill($div) {
if ($div/div and count($div/ancestor-or-self::div) < $depth) then
let $filler := local:filler($div)
return
if ($filler) then
element { node-name($div) } {
$div/@*,
$filler/preceding-sibling::node(),
$filler
}
else
element { node-name($div) } {
$div/@*,
$div/div[1]/preceding-sibling::*
}
else
$div
};
declare function local:next-page($div) {
let $filled := local:filler($div)
return
if ($filled) then
$filled/following::div[1]
else
($div/descendant::div[count(ancestor-or-self::div) <= $depth],
$div/following::div[count(ancestor-or-self::div) <= $depth])[1]
};
declare function local:previous-page($div) {
let $previous := $div/preceding::div[count(ancestor-or-self::div) <= $depth][1]
let $parent := $div/ancestor::div[1]
let $previous := if ($previous << $parent) then $parent else $previous
return
if ($previous) then
let $parent := $previous/ancestor::div[1]
return
if (local:filler($parent) is $previous) then
$parent
else
$previous
else
$div/ancestor::div[1]
};
(
local:fill(id('d1', $xml)),
local:fill(local:next-page(id('d1', $xml))), (: d2 :)
local:fill(local:next-page(id('d2', $xml))), (: d7 :)
local:fill(local:next-page(id('d7', $xml))), (: d5 :)
local:fill(local:next-page(id('d3', $xml))), (: d5 :)
local:fill(local:next-page(id('d5', $xml))), (: d6 :)
local:fill(local:next-page(id('d6', $xml))), (: d9 :)
local:fill(local:next-page(id('d9', $xml))), (: d8 :)
local:fill(local:previous-page(id('d8', $xml))),
local:fill(local:previous-page(id('d9', $xml))),
local:fill(local:previous-page(id('d6', $xml))),
local:fill(local:previous-page(id('d5', $xml))),
local:fill(local:previous-page(id('d3', $xml))),
local:fill(local:previous-page(id('d7', $xml))),
local:fill(local:previous-page(id('d2', $xml)))
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment