Eliminating Duplicate Element set using XQuery and XPath

Well i am not to sure as how often one would encounter a scenario wherein we have to select only the distinct elements when it is defined as unbounded and there are duplicate values.

However if we ever encounter this scenario while using BPEL or OSB we can use a small xquery construct to eliminate the duplicate elements.

Consider that you have a collection of Fault coming as

<FaultLogCollection>
<FaultLog>
<faultCode>001</faultCode>
<faultText>SystemFault</faultText>
<faultSeverity>High</faultSeverity>
<faultingServiceName>OrderProcessingPipeline</faultingServiceName>
<faultLogId>23</faultLogId>
</FaultLog>
<FaultLog>
<faultCode>001</faultCode>
<faultText>SystemFault</faultText>
<faultSeverity>High</faultSeverity>
<faultingServiceName>OrderProcessingPipeline</faultingServiceName>
<faultLogId>23</faultLogId>
</FaultLog>
</FaultLogCollection>

This may very well be a scenario in case we are reading from a DB/File which has duplicate values. Consider that faultCode is supposed to uniquely determine the FaultLog element.

I would use the .xq resource in Eclipse to show how this can be achieved

The schema for to be used for creating the .xq resource can be copied from under

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="FaultLogCollection" type="FaultLogCollection"/>
<xs:complexType name="FaultLogCollection">
<xs:sequence>
<xs:element name="FaultLog" type="FaultLog" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="FaultLog">
<xs:sequence>
<xs:element name="faultCode" type="xs:string" minOccurs="0"/>
<xs:element name="faultText" type="xs:string" minOccurs="0"/>
<xs:element name="faultSeverity" type="xs:string" minOccurs="0"/>
<xs:element name="faultingServiceName" type="xs:string" minOccurs="0"/>
<xs:element name="faultLogId" type="xs:decimal" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
  • Open Eclipse with OEPE and create a OSB Configuration Project. Also create an OSB project a shown below

image

  • Right click on the XQProject and create two new folder under it. Name them as xsd and xq respectively.
  • Right click on the xsd folder and then click New to create a new XML schema. Name it as FaultCollection. Copy the inline xsd content into FaultCollection.

image

  • Right click on the xq folder and then click New to create a XQuery Transformation resource as under

image

  • Click on the Source view

image

  • Copy and paste the following code snippet in the source editor
xquery version "1.0" encoding "Cp1252";
(:: pragma bea:global-element-parameter parameter="$faultLogCollection" element="FaultLogCollection" location="../xsd/FaultCollection.xsd" ::)
(:: pragma bea:global-element-return element="FaultLogCollection" location="../xsd/FaultCollection.xsd" ::)
declare namespace xf = "http://tempuri.org/XQProject/xq/DistinctFaultCollection/";
declare namespace custxf = "http://tempuri.org/XQProject/CustomXq/DistinctFaultCollection";

declare function custxf:distinct-deep ( $nodes as node()* )  as node()*
{
for $seq in (1 to count($nodes))
return $nodes[$seq][not(custxf:is-node-in-sequence-deep-equal(.,$nodes[position() < $seq]))]
} ;
declare function custxf:is-node-in-sequence-deep-equal($node as node()? ,$seq as node()* )
as xs:boolean {
some $nodeInSeq in $seq satisfies deep-equal($nodeInSeq,$node)
} ;

declare function xf:DistinctFaultCollection($faultLogCollection as element(FaultLogCollection))
as element(FaultLogCollection) {
<FaultLogCollection>
{
let $distinctFaultLogCol := custxf:distinct-deep($faultLogCollection/FaultLog)
for $FaultLog in $distinctFaultLogCol
return
 <FaultLog>
  <faultCode>{data($FaultLog/faultCode)}</faultCode>
  <faultText>{data($FaultLog/faultText)}</faultText>
  <faultSeverity>{data($FaultLog/faultSeverity)}</faultSeverity>
  <faultingServiceName>{data($FaultLog/faultingServiceName)}</faultingServiceName>
  <faultLogId>{data($FaultLog/faultLogId)}</faultLogId>
 </FaultLog>
}
</FaultLogCollection>
};
declare variable $faultLogCollection as element(FaultLogCollection) external;
xf:DistinctFaultCollection($faultLogCollection)

image

  • Having done this, now we are all set to test the XQuery function in Eclipse. Click on the the Test tab.
  • Use the sample FaultLogCollection xml posted above to test the function and see that the output of the function has eliminated the duplicate node.

image

  • The output collection filters the FaultLogCollection and removes the duplicates.
  • Try with yet another request and see the result data again. Here is the XML that can be used
<FaultLogCollection>
<FaultLog>
<faultCode>001</faultCode>
<faultText>SystemFault</faultText>
<faultSeverity>High</faultSeverity>
<faultingServiceName>OrderProcessingPipeline</faultingServiceName>
<faultLogId>23</faultLogId>
</FaultLog>
<FaultLog>
<faultCode>001</faultCode>
<faultText>SystemFault</faultText>
<faultSeverity>High</faultSeverity>
<faultingServiceName>OrderProcessingPipeline</faultingServiceName>
<faultLogId>23</faultLogId>
</FaultLog>
<FaultLog>
<faultCode>002</faultCode>
<faultText>SystemFault</faultText>
<faultSeverity>High</faultSeverity>
<faultingServiceName>OrderProcessingPipeline</faultingServiceName>
<faultLogId>23</faultLogId>
</FaultLog>
<FaultLog>
<faultCode>002</faultCode>
<faultText>SystemFault</faultText>
<faultSeverity>High</faultSeverity>
<faultingServiceName>OrderProcessingPipeline</faultingServiceName>
<faultLogId>23</faultLogId>
</FaultLog>
</FaultLogCollection>

image

The OSB Eclipse XQ project used in the example can be downloaded from here. Unzip to get the OSB jar.

One thought on “Eliminating Duplicate Element set using XQuery and XPath

  1. Pingback: Eliminating Duplicate Element set using XSLT and XPath « Oracle Technologies Premier

If you have any comments, suggestions or feedback about the post, please feel free to type it here and I will do my best to address them asap

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s