ramu_src2k
asked on
Re-arrange xml elements based on attributes using XSLT
Hi,
I need to re-arrange the below input xml using the "name" attribute through XSLT
<?xml version="1.0" encoding="UTF-16"?>
<codes>
<Entity name="entity4" >
<somedata1>Raghu</somedata 1>
<somedata2>Hemanth</someda ta2>
</Entity>
<Entity name="entity2">
<somedata1>Shilpa</somedat a1>
<somedata2>Sudha</somedata 2>
</Entity>
<Entity name="entity3">
<somedata1>Ramesh</somedat a1>
<somedata2>Sivakumar</some data2>
</Entity>
<Entity name="entity1">
<somedata1>John</somedata1 >
<somedata2>Peter</somedata 2>
</Entity>
</codes>
Output xml needs to be:
<?xml version="1.0" encoding="UTF-16"?>
<codes>
<Entity name="entity1">
<somedata1>John</somedata1 >
<somedata2>Peter</somedata 2>
</Entity>
<Entity name="entity2">
<somedata1>Shilpa</somedat a1>
<somedata2>Sudha</somedata 2>
</Entity>
<Entity name="entity3">
<somedata1>Ramesh</somedat a1>
<somedata2>Sivakumar</some data2>
</Entity>
<Entity name="entity4" >
<somedata1>Raghu</somedata 1>
<somedata2>Hemanth</someda ta2>
</Entity>
</codes>
I need to re-arrange the below input xml using the "name" attribute through XSLT
<?xml version="1.0" encoding="UTF-16"?>
<codes>
<Entity name="entity4" >
<somedata1>Raghu</somedata
<somedata2>Hemanth</someda
</Entity>
<Entity name="entity2">
<somedata1>Shilpa</somedat
<somedata2>Sudha</somedata
</Entity>
<Entity name="entity3">
<somedata1>Ramesh</somedat
<somedata2>Sivakumar</some
</Entity>
<Entity name="entity1">
<somedata1>John</somedata1
<somedata2>Peter</somedata
</Entity>
</codes>
Output xml needs to be:
<?xml version="1.0" encoding="UTF-16"?>
<codes>
<Entity name="entity1">
<somedata1>John</somedata1
<somedata2>Peter</somedata
</Entity>
<Entity name="entity2">
<somedata1>Shilpa</somedat
<somedata2>Sudha</somedata
</Entity>
<Entity name="entity3">
<somedata1>Ramesh</somedat
<somedata2>Sivakumar</some
</Entity>
<Entity name="entity4" >
<somedata1>Raghu</somedata
<somedata2>Hemanth</someda
</Entity>
</codes>
ASKER
Can you please let me know how can i handle the scenario if the value of the name attribute are like "cricket" , "football", "golf" , "tennis" etc. where i dont have a number to sort
if you just want to sort alfabetically, use this
<xsl:sort select="@name" order="ascending"/>
<xsl:sort select="@name" order="ascending"/>
ASKER
For example my Input XML would be:
<?xml version="1.0" encoding="UTF-16"?>
<codes>
<Entity name="cricket" >
<somedata1>Raghu</somedata 1>
<somedata2>Hemanth</someda ta2>
</Entity>
<Entity name="golf">
<somedata1>Shilpa</somedat a1>
<somedata2>Sudha</somedata 2>
</Entity>
<Entity name="tennis">
<somedata1>Ramesh</somedat a1>
<somedata2>Sivakumar</some data2>
</Entity>
<Entity name="football">
<somedata1>John</somedata1 >
<somedata2>Peter</somedata 2>
</Entity>
</codes>
Output should be :
<?xml version="1.0" encoding="UTF-16"?>
<codes>
<Entity name="tennis">
<somedata1>Ramesh</somedat a1>
<somedata2>Sivakumar</some data2>
</Entity>
<Entity name="cricket" >
<somedata1>Raghu</somedata 1>
<somedata2>Hemanth</someda ta2>
</Entity>
<Entity name="football">
<somedata1>John</somedata1 >
<somedata2>Peter</somedata 2>
</Entity>
<Entity name="golf">
<somedata1>Shilpa</somedat a1>
<somedata2>Sudha</somedata 2>
</Entity>
</codes>
<?xml version="1.0" encoding="UTF-16"?>
<codes>
<Entity name="cricket" >
<somedata1>Raghu</somedata
<somedata2>Hemanth</someda
</Entity>
<Entity name="golf">
<somedata1>Shilpa</somedat
<somedata2>Sudha</somedata
</Entity>
<Entity name="tennis">
<somedata1>Ramesh</somedat
<somedata2>Sivakumar</some
</Entity>
<Entity name="football">
<somedata1>John</somedata1
<somedata2>Peter</somedata
</Entity>
</codes>
Output should be :
<?xml version="1.0" encoding="UTF-16"?>
<codes>
<Entity name="tennis">
<somedata1>Ramesh</somedat
<somedata2>Sivakumar</some
</Entity>
<Entity name="cricket" >
<somedata1>Raghu</somedata
<somedata2>Hemanth</someda
</Entity>
<Entity name="football">
<somedata1>John</somedata1
<somedata2>Peter</somedata
</Entity>
<Entity name="golf">
<somedata1>Shilpa</somedat
<somedata2>Sudha</somedata
</Entity>
</codes>
ASKER
Actually i tried adding a new attribute called "id" which will rank my element and then use this newly added attribute "id" for sorting. But these thwo things i was not able to do it in a single xslt. I had to use two seperate xslt's to achieve this..Can you please help me to get this done in a single xslt.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
two XSLTs in a row are not necessarily a bad thing, I do it all the time.
Sometimes two XSLTs in a row are easier to maintain than one complex CXSLT
Sometimes two XSLTs in a row are easier to maintain than one complex CXSLT
ASKER
I tried using the mapping table but the user defined order does not happen.Can you help me regarding this
XML used:
<?xml version="1.0" encoding="UTF-16"?>
<codes>
<Entity name="Cricket" >
<somedata1>Raghu</somedata 1>
<somedata2>Hemanth</someda ta2>
</Entity>
<Entity name="Golf">
<somedata1>Shilpa</somedat a1>
<somedata2>Sudha</somedata 2>
</Entity>
<Entity name="Tennis">
<somedata1>Ramesh</somedat a1>
<somedata2>Sivakumar</some data2>
</Entity>
<Entity name="Football">
<somedata1>John</somedata1 >
<somedata2>Peter</somedata 2>
</Entity>
</codes>
XSL used:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:map="gbs:map" exclude-result-prefixes="m ap" version="1.0">
<xsl:strip-space elements="*"/>
<xsl:output indent="yes" encoding="UTF-16"/>
<xsl:template match="*">
<codes>
<xsl:for-each select="Entity">
<xsl:sort select="document('')//map: item[@name =current() ]/@order" order="ascending"/>
<xsl:copy-of select="."/>
</xsl:for-each>
</codes>
</xsl:template>
<map:item name="Tennis" order="1"/>
<map:item name="Cricket" order="2"/>
<map:item name="Football" order="3"/>
<map:item name="Golf" order="4"/>
</xsl:stylesheet>
XML used:
<?xml version="1.0" encoding="UTF-16"?>
<codes>
<Entity name="Cricket" >
<somedata1>Raghu</somedata
<somedata2>Hemanth</someda
</Entity>
<Entity name="Golf">
<somedata1>Shilpa</somedat
<somedata2>Sudha</somedata
</Entity>
<Entity name="Tennis">
<somedata1>Ramesh</somedat
<somedata2>Sivakumar</some
</Entity>
<Entity name="Football">
<somedata1>John</somedata1
<somedata2>Peter</somedata
</Entity>
</codes>
XSL used:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:map="gbs:map" exclude-result-prefixes="m
<xsl:strip-space elements="*"/>
<xsl:output indent="yes" encoding="UTF-16"/>
<xsl:template match="*">
<codes>
<xsl:for-each select="Entity">
<xsl:sort select="document('')//map:
<xsl:copy-of select="."/>
</xsl:for-each>
</codes>
</xsl:template>
<map:item name="Tennis" order="1"/>
<map:item name="Cricket" order="2"/>
<map:item name="Football" order="3"/>
<map:item name="Golf" order="4"/>
</xsl:stylesheet>
ASKER
I have got the answer and it meets my requirement. Thanks a lot for your valuable inputs
Here is the solution
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:strip-space elements="*"/>
<xsl:output indent="yes" encoding="UTF-16"/>
<xsl:template match="codes">
<codes>
<xsl:for-each select="Entity">
<xsl:sort
select="(number(@name='Ten nis') * 1)
+ (number(@name='Cricket') * 2)
+ (number(@name='Football') * 3)
+ (number(@name='Golf') * 4)"
order="ascending" data-type="number" />
<xsl:copy-of select="."/>
</xsl:for-each>
</codes>
</xsl:template>
</xsl:stylesheet>
Here is the solution
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:strip-space elements="*"/>
<xsl:output indent="yes" encoding="UTF-16"/>
<xsl:template match="codes">
<codes>
<xsl:for-each select="Entity">
<xsl:sort
select="(number(@name='Ten
+ (number(@name='Cricket') * 2)
+ (number(@name='Football') * 3)
+ (number(@name='Golf') * 4)"
order="ascending" data-type="number" />
<xsl:copy-of select="."/>
</xsl:for-each>
</codes>
</xsl:template>
</xsl:stylesheet>
your mapping statement is wrong
<xsl:sort select="document('')//map: item[@name =current() ]/@order" order="ascending"/>
should be
<xsl:sort select="document('')//map: item[@name =current() /@name]/@o rder" order="ascending"/>
<xsl:sort select="document('')//map:
should be
<xsl:sort select="document('')//map:
oh, you found something too...
well, that works, I personally find a mapping table more elegant,
but yours will work even when using the document('') function is switched off (it sometimes is for security reasons)
cheers
Geert
well, that works, I personally find a mapping table more elegant,
but yours will work even when using the document('') function is switched off (it sometimes is for security reasons)
cheers
Geert
Open in new window