I am attempting to create an XSLT file that will create a new XML from a source XML that will sort the types nodes by name, then sort the members inside of each types.
Source:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<types>
<members>Ontario</members>
<members>Quebec</members>
<members>Alberta</members>
<name>Provinces</name>
</types>
<types>
<members>Vancouver</members>
<members>Calgary</members>
<members>Toronto</members>
<members>Montreal</members>
<name>Cities</name>
</types>
<version>43.0</version>
</Package>
Expected Output:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<types>
<members>Calgary</members>
<members>Montreal</members>
<members>Toronto</members>
<members>Vancouver</members>
<name>Cities</name>
</types>
<types>
<members>Alberta</members>
<members>Ontario</members>
<members>Quebec</members>
<name>Provinces</name>
</types>
<version>43.0</version>
</Package>
I started by trying to sort the types by name but it doesnt seem to be sorting anything for me
XSL:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Package">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates select="types">
<xsl:sort select="name"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Your script failed because you have forgotten about namespaces. Eg template matching Package
refers to this name in the empty namespace, whereas your input Package
element is in http://soap.sforce.com/2006/04/metadata
namespace.
So the proper XSLT script should:
stylesheet
tag, specyfying a prefix (eg m
), Below you have a working script:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:m="http://soap.sforce.com/2006/04/metadata">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="m:Package">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates select="m:types">
<xsl:sort select="m:name"/>
</xsl:apply-templates>
<xsl:apply-templates select="*[local-name() != 'types']"/>
</xsl:copy>
</xsl:template>
<xsl:template match="m:types">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates select="m:members">
<xsl:sort select="."/>
</xsl:apply-templates>
<xsl:apply-templates select="m:name"/>
</xsl:copy>
</xsl:template>
<xsl:template match="node()|@*">
<xsl:copy><xsl:apply-templates select="node()|@*"/></xsl:copy>
</xsl:template>
</xsl:stylesheet>
As you can see, I added a template matching types
, to provide sort for members
, just as you specified.
<xsl:output method="xml" indent="yes"/>
<xsl:template match="Package">
<xsl:copy copy-namespaces="yes">
<xsl:for-each select="types">
<xsl:sort select="." order="descending"/>
<types>
<xsl:for-each select="members">
<xsl:sort order="ascending"/>
<members>
<xsl:value-of select="."/>
</members>
</xsl:for-each>
<name>
<xsl:value-of select="name"/>
</name>
</types>
</xsl:for-each>
<xsl:apply-templates select="version"/>
</xsl:copy>
</xsl:template>
<xsl:template match="version">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
Check it
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.