i am new to xquery. I have the following xml document :
<?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>
I would like to create a function that would get as input a certain id , and would return all the line elements – descendants of this id , including the one given as input. For example giving as input 1 it would return the line elements with ids 1,2,3,4,5,6,7,8. I know i can go to depth 1 using the following: lines/line[par=id_given], but what if i would like to fetch all descendants?
You have to define a function which traverses the tree recursively. This one does works level-wise:
You can call it using
local:traverse(/lines, 0).But this function will not deal with your example XML, as this is no tree: there is a cycle in the root element which isn’t allowed. You will have to introduce some new unique root id or remove the parent from the root for having a real tree.
You could also change the code above to be able to deal with these self-references: Add the predicate
[id!=$id]to the end of the definition of$level, this will exclude self-references. Now your root node is excluded from the results, reinclude it in the function call:(/lines/line[id=1], local:traverse(/lines, 1)).