Reputation: 735
So I have this (unusual) task
"Write a query that inverts all the sub elements of the /music element so that their own sub elements become attributes and their attributes become sub elements. For those sub elements that lack sub elements of their own, their data content should become an attribute with the name 'value'."
where I use this database: https://gist.githubusercontent.com/Schytheron/0a5c4756db62a1f43fc40226659c12cf/raw/71378ab9cede19e3f5bb33e948177a9fccfcc132/songs.xml and I genuinely don't even know where to begin. I am completely lost. Can this only be solved recursively or is there another way (because I have never tried doing recursion in Xquery)? Do you have any tips/strategies for solving this or any useful functions (I am very new to Xquery so I don't really know that many useful functions) I can use?
Thoughts? Ideas?
Thanks!
EDIT: Just to make things clear. I know that I can probably just do this manually for each element and their child elements with x amount of nested for-loops but I want to know if there is a way to make this dynamic so that it works with ANY XML database.
Upvotes: 1
Views: 284
Reputation: 167446
For the limited use case of transforming the children of the root element as you want you can use some functions:
declare function local:transform($element as element()) as element() {
element {name($element)} {
$element/node() ! local:attribute(.),
$element/@* ! local:element(.)
}
};
declare function local:attribute($node as node()) as attribute() {
typeswitch ($node)
case element() return attribute {name($node)} {data($node) }
case text() return attribute value { $node }
default return ()
};
declare function local:element($att as attribute()) as element() {
element {name($att)} { data($att) }
};
/*!element {name()} { *!local:transform(.) }
https://xqueryfiddle.liberty-development.net/nbUY4ki
Upvotes: 3