friedman16 Absent Member.
Absent Member.
449 views

Sorting a Nodeset

Is there a way to order or sort a nodeset based on a specific attribute value within each nodeset?

For example, I have the following XML code that is written to an attribute

<OSUworkdayBlob>
<OSUIDMID>idm800155</OSUIDMID>
<Appointment>
<OSUapptAction>delete</OSUapptAction>
<OSUapptActionCd>CNV</OSUapptActionCd>
<OSUapptActionDt>07/07/2014</OSUapptActionDt>
<OSUapptActionReason>CNV</OSUapptActionReason>
<OSUapptClassIndc>F</OSUapptClassIndc>
<OSUapptPstnNbr>00033692</OSUapptPstnNbr>
</Appointment>
<Appointment>
<OSUapptPrimary>true</OSUapptPrimary>
<OSUapptAction>new</OSUapptAction>
<OSUapptActionCd>CNV</OSUapptActionCd>
<OSUapptActionDt>07/07/2014</OSUapptActionDt>
<OSUapptActionReason>CNV</OSUapptActionReason>
<OSUapptClassIndc>F</OSUapptClassIndc>
<OSUapptPstnNbr>00033741</OSUapptPstnNbr>
</Appointment>
<Appointment>
<OSUapptAction>modify</OSUapptAction>
<OSUapptActionCd>CNV</OSUapptActionCd>
<OSUapptActionDt>07/07/2014</OSUapptActionDt>
<OSUapptActionReason>CNV</OSUapptActionReason>
<OSUapptClassIndc>F</OSUapptClassIndc>
<OSUapptPstnNbr>00033899</OSUapptPstnNbr>
</Appointment>
</OSUworkdayBlob>


I know how to put this attribute into a nodeset and I know how to loop through each by using the foreach loop. However, I need to process these in a particular order. Specifically, I need to process all of the OSUapptAction attributes first where the value = new... then process modify... then process the delete values last.

Is there a way to use XPATH to sort the above attributes when putting this into a nodeset? or is there a way to sort these by using the foreach loop?

Any help or advice would be much appreciated.

Thanks,
Frank
Labels (1)
0 Likes
3 Replies
Knowledge Partner
Knowledge Partner

Re: Sorting a Nodeset

friedman16 wrote:

> Any help or advice would be much appreciated.


I found XSLT the easiest way to do this, here's a starting point:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- identity transformation template -->
<!-- in the absence of any other templates this will cause -->
<!-- the stylesheet to copy the input through unchanged to the output -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- sort value nodes of operation attributes by @timestamp -->
<xsl:template match="input//*[value/@timestamp and ancestor::*/@attr-name]">
<xsl:copy>
<xsl:apply-templates select="value[@timestamp]">
<xsl:sort select="@timestamp"/>
</xsl:apply-templates>
<xsl:apply-templates select="*[not(name()='value' and @timestamp)]|@*"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

You might also pass your nodeset to an ECMAscript and have it returned sorted,
I guess. Theoretically, you could even implement e.g. quicksort in DirXMLScript
with tokens clone-xpath, strip-xpath but it sounds pretty complicated,
especially when it's so easy in XSLT.

--
http://www.is4it.de/en/solution/identity-access-management/

(If you find this post helpful, please click on the star below.)
0 Likes
friedman16 Absent Member.
Absent Member.

Re: Sorting a Nodeset

lhaeger,

I came to the conclusion that XSLT was my best bet. After much searching, I found a solution (adding here for those who may have the same problem)

The input:
<nds dtdversion="2.0">
<source>
<product build="20170208_0924" instance="wdStudio" version="4.0.0.4">Identity Manager Driver for SOAP</product>
<contact>NetIQ Corporation</contact>
</source>
<input>
<modify class-name="OSUconfig">
<OSUworkdayBlob>
<OSUidmId>IDM800512</OSUidmId>
<Change>
<attribute>OSUhomeAddr2</attribute>
<beforevalue/>
<aftervalue>Basement</aftervalue>
</Change>
<Appointment>
<OSUapptAction>delete</OSUapptAction>
<OSUapptActionCd>CNV</OSUapptActionCd>
<OSUapptActionDt>07/07/2014</OSUapptActionDt>
<OSUapptActionReason>CNV</OSUapptActionReason>
<OSUapptClassIndc>F</OSUapptClassIndc>
<OSUapptDeptID>18000</OSUapptDeptID>
<OSUapptEffdt>01/07/2014</OSUapptEffdt>
<OSUapptEmplStatus>A</OSUapptEmplStatus>
<OSUapptJobcode>3180a</OSUapptJobcode>
<OSUapptLoc>273</OSUapptLoc>
<OSUapptMedcenterOrg/>
<OSUapptPstnNbr>00033449</OSUapptPstnNbr>
<OSUapptRecordNum>0</OSUapptRecordNum>
<OSUapptRegTemp>R</OSUapptRegTemp>
<OSUapptRptsTo>00022295</OSUapptRptsTo>
<OSUapptSalaryPlan>FAC</OSUapptSalaryPlan>
<OSUapptStdHours>40</OSUapptStdHours>
<OSUsupervisorID>200002385</OSUsupervisorID>
</Appointment>
<Appointment>
<OSUapptAction>delete</OSUapptAction>
<OSUapptActionCd>CNV</OSUapptActionCd>
<OSUapptActionDt>07/07/2014</OSUapptActionDt>
<OSUapptActionReason>CNV</OSUapptActionReason>
<OSUapptClassIndc>F</OSUapptClassIndc>
<OSUapptDeptID>18000</OSUapptDeptID>
<OSUapptEffdt>01/07/2014</OSUapptEffdt>
<OSUapptEmplStatus>A</OSUapptEmplStatus>
<OSUapptJobcode>3180a</OSUapptJobcode>
<OSUapptLoc>273</OSUapptLoc>
<OSUapptMedcenterOrg/>
<OSUapptPstnNbr>00033450</OSUapptPstnNbr>
<OSUapptRecordNum>0</OSUapptRecordNum>
<OSUapptRegTemp>R</OSUapptRegTemp>
<OSUapptRptsTo>00022295</OSUapptRptsTo>
<OSUapptSalaryPlan>FAC</OSUapptSalaryPlan>
<OSUapptStdHours>40</OSUapptStdHours>
<OSUsupervisorID>200002385</OSUsupervisorID>
</Appointment>
<Appointment>
<OSUapptPrimary>true</OSUapptPrimary>
<OSUapptAction>new</OSUapptAction>
<OSUapptActionCd>CNV</OSUapptActionCd>
<OSUapptActionDt>07/07/2014</OSUapptActionDt>
<OSUapptActionReason>CNV</OSUapptActionReason>
<OSUapptClassIndc>F</OSUapptClassIndc>
<OSUapptDeptID>18000</OSUapptDeptID>
<OSUapptEffdt>01/07/2014</OSUapptEffdt>
<OSUapptEmplStatus>A</OSUapptEmplStatus>
<OSUapptJobcode>3180a</OSUapptJobcode>
<OSUapptLoc>273</OSUapptLoc>
<OSUapptMedcenterOrg/>
<OSUapptPstnNbr>00033451</OSUapptPstnNbr>
<OSUapptRecordNum>0</OSUapptRecordNum>
<OSUapptRegTemp>R</OSUapptRegTemp>
<OSUapptRptsTo>00022295</OSUapptRptsTo>
<OSUapptSalaryPlan>FAC</OSUapptSalaryPlan>
<OSUapptStdHours>40</OSUapptStdHours>
<OSUsupervisorID>200002385</OSUsupervisorID>
</Appointment>
</OSUworkdayBlob>
</input>
</nds>




and the XSLT code:

<!-- identity transformation template -->
<!-- in the absence of any other templates this will cause -->
<!-- the stylesheet to copy the input through unchanged to the output -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- sort value nodes of operation attributes by @timestamp -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:apply-templates select="node()">
<xsl:sort select="OSUapptAction" data-type="text" order="descending"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>


This will sort the Appointment stuff according to the value in the OSUapptAction XML tag.
0 Likes
Knowledge Partner
Knowledge Partner

Re: Sorting a Nodeset

Thanks for sharing your solution.
0 Likes
The opinions expressed above are the personal opinions of the authors, not of Micro Focus. By using this site, you accept the Terms of Use and Rules of Participation. Certain versions of content ("Material") accessible here may contain branding from Hewlett-Packard Company (now HP Inc.) and Hewlett Packard Enterprise Company. As of September 1, 2017, the Material is now offered by Micro Focus, a separately owned and operated company. Any reference to the HP and Hewlett Packard Enterprise/HPE marks is historical in nature, and the HP and Hewlett Packard Enterprise/HPE marks are the property of their respective owners.