Parent-Child Unbound Transformation from Linear Structure
Hi ,
We need to convert the linear people structure into Parent-Child relation with unbounded depth using XQuery. To give in detail, we have the XML schema as
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/ParentChild" xmlns:tns="http://www.example.org/ParentChild" elementFormDefault="qualified">
<complexType name="People">
<sequence>
<element name="id" type="string" />
<element name="name" type="string" />
<element name="age" type="string" />
<element name="parentId" type="string" minOccurs="0" />
</sequence>
</complexType>
<complexType name="Peoples">
<sequence>
<element name="people" type="tns:People" maxOccurs="unbounded"></element>
</sequence>
</complexType>
<element name="Peoples" type="tns:Peoples"></element>
<element name="People" type="tns:People"></element>
<complexType name="Parent">
<sequence>
<element name="id" type="string" />
<element name="name" type="string" />
<element name="age" type="string" />
<element name="child" type="tns:Parent" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
<complexType name="Parents">
<sequence>
<element name="Parent" type="tns:Parent" maxOccurs="unbounded" ></element>
</sequence>
</complexType>
<element name="Parents" type="tns:Parents"></element>
<element name="Parent" type="tns:Parent"></element>
</schema>
The input structure can appear as
<?xml version="1.0"?>
<ns0:Peoples xmlns:ns0="http://www.example.org/ParentChild">
<ns0:people>
<ns0:id>1</ns0:id>
<ns0:name>x</ns0:name>
<ns0:age>11</ns0:age>
<ns0:parentId>2</ns0:parentId>
</ns0:people>
<ns0:people>
<ns0:id>2</ns0:id>
<ns0:name>y</ns0:name>
<ns0:age>11</ns0:age>
<ns0:parentId>3</ns0:parentId>
</ns0:people>
<ns0:people>
<ns0:id>3</ns0:id>
<ns0:name>z</ns0:name>
<ns0:age>11</ns0:age>
</ns0:people>
<ns0:people>
<ns0:id>5</ns0:id>
<ns0:name>a</ns0:name>
<ns0:age>11</ns0:age>
</ns0:people>
</ns0:Peoples>
The response should be like below
<?xml version="1.0"?>
<ns0:Parents xmlns:ns0="http://www.example.org/ParentChild">
<ns0:Parent>
<ns0:id>3</ns0:id>
<ns0:name>z</ns0:name>
<ns0:age>11</ns0:age>
<ns0:child>
<ns0:id>2</ns0:id>
<ns0:name>y</ns0:name>
<ns0:age>11</ns0:age>
<ns0:child>
<ns0:id>1</ns0:id>
<ns0:name>x</ns0:name>
<ns0:age>11</ns0:age>
</ns0:child>
</ns0:child>
</ns0:Parent>
<ns0:Parent>
<ns0:id>5</ns0:id>
<ns0:name>a</ns0:name>
<ns0:age>11</ns0:age>
</ns0:Parent>
</ns0:Parents>
We tried with below XQuery, but it is not resulting as expected.
(:: pragma bea:global-element-parameter parameter="$peoples" element="ns0:Peoples" location="ParentChild.xsd" ::)
(:: pragma bea:global-element-return element="ns0:Parents" location="ParentChild.xsd" ::)
declare namespace ns0 = "http://www.example.org/ParentChild";
declare namespace xf = "http://tempuri.org/RecursiveParentChild/ParentChild/";
declare function xf:ParentChild($peoples as element(ns0:Peoples))
as element(ns0:Parents) {
<ns0:Parents>
{
let $results := <a>{
for $people1 in $peoples/ns0:people where (not (exists ($people1/*:parentId)))
return
<ns0:Parent>
<ns0:id>{ data($people1/ns0:id) }</ns0:id>
<ns0:name>{ data($people1/ns0:name) }</ns0:name>
<ns0:age>{ data($people1/ns0:age) }</ns0:age>
</ns0:Parent>
}
</a>
let $result1 :=
for $people1 in $peoples/ns0:people where (exists ($people1/*:parentId))
return
if (data($people1/ns0:parentId) = data($results/ns0:id)) then
<ns0:child>
$people1/*
</ns0:child>
else()
return $result1
}
</ns0:Parents>
};
declare variable $peoples as element(ns0:Peoples) external;
xf:ParentChild($peoples)
Anyone tried similar kind of XQuery?. THere is a possibility that the child node can appear before the parent node, how we can handle that as well?
Any help on this is appreciated
Regards
Venkata Madhu