Reputation: 41
I am trying to sort an XML document using XQuery. First level sorting is by one of the parent element.
And the second level sorting is one of the linked child element.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<FEATURES xmlns="http://www.example.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<FEATURE>
<abbreviation>CANAL</abbreviation>
<LINKED_PROPERTIES>
<LP>
<abbreviation>zltinf</abbreviation>
<category>A</category>
<remarks />
</LP>
<LP>
<abbreviation>altalt</abbreviation>
<category>A</category>
<remarks />
</LP>
<LP>
<abbreviation>betbet</abbreviation>
<category>C</category>
<remarks />
</LP>
</LINKED_PROPERTIES>
<description>Water Canal</description>
<code>23</code>
<relation_type />
</FEATURE>
<FEATURE>
<abbreviation>AREA</abbreviation>
<LINKED_PROPERTIES>
<LP>
<abbreviation>zltzlt</abbreviation>
<category>A</category>
<remarks>zolt zolt</remarks>
</LP>
<LP>
<abbreviation>altalt</abbreviation>
<category>A</category>
<remarks />
</LP>
<LP>
<abbreviation>betbet</abbreviation>
<category>C</category>
<remarks />
</LP>
</LINKED_PROPERTIES>
<description>Area under administration</description>
<code>1</code>
<relation_type />
</FEATURE>
<FEATURE>
<abbreviation>BUOY</abbreviation>
<LINKED_PROPERTIES>
<LP>
<abbreviation>zltinf</abbreviation>
<category>A</category>
<remarks />
</LP>
<LP>
<abbreviation>altalt</abbreviation>
<category>A</category>
<remarks />
</LP>
<LP>
<abbreviation>betbet</abbreviation>
<category>C</category>
<remarks />
</LP>
<LP>
<abbreviation>infinf</abbreviation>
<category>A</category>
<remarks />
</LP>
<LP>
<abbreviation>altalt</abbreviation>
<category>A</category>
<remarks />
</LP>
<LP>
<abbreviation>betbet</abbreviation>
<category>C</category>
<remarks />
</LP>
</LINKED_PROPERTIES>
<description>Buoy on water</description>
<code>18</code>
<relation_type />
</FEATURE>
<FEATURE>
<abbreviation>DRONE</abbreviation>
<LINKED_PROPERTIES>
<LP>
<abbreviation>zltinf</abbreviation>
<category>A</category>
<remarks />
</LP>
<LP>
<abbreviation>beltam</abbreviation>
<category>A</category>
<remarks />
</LP>
<LP>
<abbreviation>betbet</abbreviation>
<category>C</category>
<remarks />
</LP>
</LINKED_PROPERTIES>
<description>Drones Inland</description>
<code>2</code>
<relation_type />
</FEATURE>
</FEATURES>
This document contains features of two levels, which belongs to a standard. So obviously I cannot modify the XML document. Above data is anonymized data.
My XQuery is like the below.
<FEATURES xmlns="http://www.example.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
{
let $doc := doc("features.xml")
for $feature in $doc/FEATURES/FEATURE
order by $feature/abbreviation ascending
return
<FEATURE>
{
for $ft in $feature
return if ($ft/child::element/name() eq
"LINKED_PROPERTIES")then
<LINKED_PROPERTIES_XXXXXXXX>{
for $lp in $ft/LINKED_PROPERTIES/LP
order
by $lp/abbreviation ascending
return $lp
}
</LINKED_PROPERTIES_XXXXXXXX>
else $ft/*}
</FEATURE>
}
</FEATURES>
I am unable to get the proper equality condition at the child level and hence not getting desired sorting at the child level.
I do not want to go back to DOM/XSL for several reasons. Please assist.
Upvotes: 0
Views: 431
Reputation: 7279
The inner for
needs to iterate on the children of the feature, otherwise there will be only one item to iterate on. Also, further down in the tree, LINKED_PROPERTIES
must be removed as $ft is already at that node, and other children must be returned as they are. Finally, the kind test was not quite right (must be child::element()
).
<FEATURES xmlns="http://www.example.com/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">{
let $doc := doc("features.xml")
for $feature in $doc/FEATURES/FEATURE
order by $feature/abbreviation ascending
return <FEATURE>{
for $ft-child in $feature/child::element()
return if ($ft-child/name() eq "LINKED_PROPERTIES")
then <LINKED_PROPERTIES_XXXXXXXX>{
for $lp in $ft-child/LP
order by $lp/abbreviation ascending
return $lp
}</LINKED_PROPERTIES_XXXXXXXX>
else $ft-child
}</FEATURE>
}</FEATURES>
The above query succeeds in oXygen.
Upvotes: 1
Reputation: 89285
If you meant to test if FEATURE
has chid element LINKED_PROPERTIES
:
return if ($ft/LINKED_PROPERTIES) then
<LINKED_PROPERTIES_XXXXXXXX>
{
.....
}
</LINKED_PROPERTIES_XXXXXXXX>
Your XQuery attempt for the same doesn't make much sense, it will never evaluates to true since it looks for child element named element
($ft/child::element
) and further test if the element name equals "LINKED_PROPERTIES"
(/name() eq "LINKED_PROPERTIES"
).
Upvotes: 0