XSLT 2.0: Adding a new element in its valid place in a sequence of elements as specified by an xsd:sequence - sequence

Consider the following schema:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.zoo.org/animals" targetNamespace="http://www.zoo.org/animals" elementFormDefault="unqualified" attributeFormDefault="unqualified" version="1.0.0">
<xsd:complexType name="Animals_Type">
<xsd:sequence>
<xsd:element ref="Cat" minOccurs="0" maxOccurs="unbounded" />
<xsd:element ref="Dog" minOccurs="0" maxOccurs="unbounded" />
<xsd:element ref="Mouse" minOccurs="0" maxOccurs="unbounded" />
<xsd:element ref="Lion" minOccurs="0" maxOccurs="unbounded" />
<xsd:element ref="Tiger" minOccurs="0" maxOccurs="unbounded" />
<xsd:element ref="Bear" minOccurs="0" maxOccurs="unbounded" />
<xsd:element ref="Penguin" minOccurs="0" maxOccurs="unbounded" />
<xsd:element ref="Monkey" minOccurs="0" maxOccurs="unbounded" />
</xsd:sequence>
</xsd:complexType>
<xsd:element name="Animals" type="Animals_Type"/>
<xsd:element name="Cat" type="xsd:string"/>
<xsd:element name="Dog" type="xsd:string"/>
<xsd:element name="Mouse" type="xsd:string"/>
<xsd:element name="Lion" type="xsd:string"/>
<xsd:element name="Tiger" type="xsd:string"/>
<xsd:element name="Bear" type="xsd:string"/>
<xsd:element name="Penguin" type="xsd:string"/>
<xsd:element name="Monkey" type="xsd:string"/>
</xsd:schema>
With the following input xml:
<Animals xmlns="http://www.zoo.org/animals">
<Cat>Pixel</Cat>
<Dog>Ada</Dog>
<Mouse>Minnie</Mouse>
<Lion>Donnie</Lion>
<Tiger>Phil</Tiger>
<Bear>Susie</Bear>
<Penguin>Bob</Penguin>
<Monkey>Lennie</Monkey>
</Animals>
Where the desired output xml is to add a Bear named Billy:
<Animals xmlns="http://www.zoo.org/animals">
<Cat>Pixel</Cat>
<Dog>Ada</Dog>
<Mouse>Minnie</Mouse>
<Lion>Donnie</Lion>
<Tiger>Phil</Tiger>
<Bear>Susie</Bear>
<Bear>Billy</Bear>
<Penguin>Bob</Penguin>
<Monkey>Lennie</Monkey>
</Animals>
The following xslt will add Billy the Bear to the xml, however it will add Billy at the end after all other elements are copied and thus will create a schema invalid xml:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xpath-default-namespace="http://www.zoo.org/animals">
<!-- element template that copies over elements -->
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="Animals">
<xsl:copy>
<xsl:apply-templates select="node()|#*" />
<xsl:element name="Bear" namespace="{namespace-uri()}">Billy</xsl:element>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Creates schema invalid xml due to sequence out of order:
<?xml version="1.0" encoding="UTF-8"?>
<Animals xmlns="http://www.zoo.org/animals">
<Cat>Pixel</Cat>
<Dog>Ada</Dog>
<Mouse>Minnie</Mouse>
<Lion>Donnie</Lion>
<Tiger>Phil</Tiger>
<Bear>Susie</Bear>
<Penguin>Bob</Penguin>
<Monkey>Lennie</Monkey>
<Bear>Billy</Bear>
</Animals>
A better xslt that will add Billy the Bear in the correct location is:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xpath-default-namespace="http://www.zoo.org/animals">
<xsl:strip-space elements="*" />
<!-- element template that copies over elements -->
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="Animals">
<xsl:copy>
<xsl:apply-templates select="#*|node()[not(self::Penguin)][not(self::Monkey)]" />
<xsl:element name="Bear" namespace="{namespace-uri()}">Billy</xsl:element>
<xsl:apply-templates select="#*|node()[not(self::Cat)][not(self::Dog)][not(self::Mouse)][not(self::Lion)][not(self::Tiger)][not(self::Bear)]" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Creates correct xml:
<?xml version="1.0" encoding="UTF-8"?>
<Animals xmlns="http://www.zoo.org/animals">
<Cat>Pixel</Cat>
<Dog>Ada</Dog>
<Mouse>Minnie</Mouse>
<Lion>Donnie</Lion>
<Tiger>Phil</Tiger>
<Bear>Susie</Bear>
<Bear>Billy</Bear>
<Penguin>Bob</Penguin>
<Monkey>Lennie</Monkey>
</Animals>
The concern I have with this xslt is that it is directly coupled to the current schema. For instance if the schema is later updated with a simple element addition to the sequence, this xslt will break.
What is the most flexible way to add an element to the middle of a sequence? Is there a transform that can be written such that new elements being added to the sequence in the future will not break the transform?

I believe you want something like this:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:zoo="http://www.zoo.org/animals">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="pAddElementName" select="'Bear'"/>
<xsl:param name="pAddValue" select="'Billy'"/>
<xsl:variable name="vSchema" select="document('animals.xsd')"/>
<xsl:variable name="vElementNameSpecified" select=
"$vSchema/*/xs:complexType[#name='Animals_Type']
/xs:sequence/xs:element[#ref=$pAddElementName]"/>
<xsl:variable name="vPreceding" select=
"$vSchema/*/xs:complexType[#name='Animals_Type']
/xs:sequence
/xs:element[following-sibling::xs:element
[#ref=$pAddElementName]]/#ref/string()"/>
<xsl:variable name="vFollowing" select=
"$vSchema/*/xs:complexType[#name='Animals_Type']
/xs:sequence
/xs:element[preceding-sibling::xs:element
[#ref=$pAddElementName]]/#ref/string()"/>
<xsl:template match="node()|#*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*[$vElementNameSpecified]/zoo:*[name()=$vPreceding][last()]">
<xsl:call-template name="identity"/>
<xsl:element name="{$pAddElementName}" namespace="http://www.zoo.org/animals">
<xsl:sequence select="$pAddValue"/>
</xsl:element>
</xsl:template>
<xsl:template match="/*[$vElementNameSpecified][not(zoo:*[name()=$vPreceding])]
/zoo:*[name()=$vFollowing][1]">
<xsl:element name="{$pAddElementName}" namespace="http://www.zoo.org/animals">
<xsl:sequence select="$pAddValue"/>
</xsl:element>
<xsl:call-template name="identity"/>
</xsl:template>
<xsl:template match="/*[$vElementNameSpecified]
[not(zoo:*[name()=$vPreceding])
and not(zoo:*[name()=$vFollowing])]">
<xsl:copy>
<xsl:apply-templates select="#*"/>
<xsl:element name="{$pAddElementName}" namespace="http://www.zoo.org/animals">
<xsl:sequence select="$pAddValue"/>
</xsl:element>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Explanation:
The XML Schema is accessed using the document() function.
All different names of elements that can precede the element to be added, are dynamically identified.
All different names of elements that can follow the element to be added, are dynamically identified.
There are three cases: a) preceding elements exist; b) preceding elements don't exist, but following elements exist; c) neither preceding elements nor following elements exist. The transformation contains a template for each of these cases, that adds the wanted new element in its correct place.

Related

How to remove Namespaces when copying nodes to a different node in XML through XSLT1.0?

I'm new to XSL and i'm trying to copy a node of XML to another node in the same XML using XSLT. I can able to transform the file as expected but the XMLNS attribute is getting added to the destination which I don't want.
I have tried all the option of copy-namespaces='no' using XSLT2.0 but that doesn't work. Also, I cant have a prefix of namespaces in the XSLT and use exclude namespaces to avoid xmlns because the incoming XML file is dynamic and namespaces keep on changing. I can't have all the namespaces declared as a prefix in XSLT.
Incoming XML:
<?xml version="1.0" encoding="UTF-8"?>
<PropertySet>
<Message>
<NotificationHeader>
<BusinessId></BusinessId>
<CorrelationId>0201201916:21:24CKG3N</CorrelationId>
<SourceName></SourceName>
<SourceId></SourceId>
<EventType></EventType>
<SecurityIdentifierId></SecurityIdentifierId>
<ClientRequestId></ClientRequestId>
<TargetId>ESB</TargetId>
<EventTime></EventTime>
<RequestUser></RequestUser>
</NotificationHeader>
<EventList>
<Event>
<PayLoad>
<ListOfActionIo xmlns="http://www.test.com/IO">
<Action>
<ActivityId>4-309C7WV</ActivityId>
<ActivitySRId></ActivitySRId>
<ActivityTemplateId></ActivityTemplateId>
<ActivityUID>4-309C7WV</ActivityUID>
<Category> Notification</Category>
<Comment></Comment>
<Type>Action</Type>
<ListOfDestination>
<Destination>
<DestinationName>NSW Aboriginal Education Consultative Group Incorporated</DestinationName>
</Destination>
<Destination>
<DestinationName>NSW Aboriginal Education Consultative Group Incorporated</DestinationName>
</Destination>
</ListOfDestination>
</Action>
</ListOfActionIo>
</PayLoad>
</Event>
</EventList>
<DestinationList>
<Destination>
<DestinationName></DestinationName>
<DestinationId></DestinationId>
</Destination>
</DestinationList>
</Message>
</PropertySet>
XSLT Code:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" method="xml" encoding="UTF-8"/>
<xsl:strip-space elements="*"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="//*[name()='Message']/*[name()='DestinationList']//*[name()='Destination']"></xsl:template>
<!--Copy the destination from one node to another node-->
<xsl:template match="//*[name()='Message']/*[name()='DestinationList']">
<xsl:copy>
<xsl:copy-of select="//*[name()='Message']/*[name()='EventList']//*[name()='Destination']"/>
</xsl:copy>
</xsl:template>
<!--Remove the original node from where the destination was copied-->
<xsl:template match="//*[name()='Message']/*[name()='EventList']//*[name()='ListOfDestination']"></xsl:template>
</xsl:stylesheet>
Output:
<PropertySet>
<Message>
<NotificationHeader>
<BusinessId/>
<CorrelationId>0201201916:21:24CKG3N</CorrelationId>
<SourceName/>
<SourceId/>
<EventType/>
<SecurityIdentifierId/>
<ClientRequestId/>
<TargetId>ESB</TargetId>
<EventTime/>
<RequestUser/>
</NotificationHeader>
<EventList>
<Event>
<PayLoad>
<ListOfActionIo xmlns="http://www.test.com/IO">
<Action>
<ActivityId>4-309C7WV</ActivityId>
<ActivitySRId/>
<ActivityTemplateId/>
<ActivityUID>4-309C7WV</ActivityUID>
<Category> Notification</Category>
<Comment/>
<Type>Action</Type>
</Action>
</ListOfActionIo>
</PayLoad>
</Event>
</EventList>
<DestinationList>
<Destination xmlns="http://www.test.com/IO">
<DestinationName>NSW Aboriginal Education Consultative Group Incorporated</DestinationName>
</Destination>
<Destination xmlns="http://www.test.com/IO">
<DestinationName>NSW Aboriginal Education Consultative Group Incorporated</DestinationName>
</Destination>
</DestinationList>
</Message>
</PropertySet>
Expected Output:
Without the Namespaces on the copied node.
<PropertySet>
<Message>
<NotificationHeader>
<BusinessId/>
<CorrelationId>0201201916:21:24CKG3N</CorrelationId>
<SourceName/>
<SourceId/>
<EventType/>
<SecurityIdentifierId/>
<ClientRequestId/>
<TargetId>ESB</TargetId>
<EventTime/>
<RequestUser/>
</NotificationHeader>
<EventList>
<Event>
<PayLoad>
<ListOfActionIo xmlns="http://www.test.com/IO">
<Action>
<ActivityId>4-309C7WV</ActivityId>
<ActivitySRId/>
<ActivityTemplateId/>
<ActivityUID>4-309C7WV</ActivityUID>
<Category> Notification</Category>
<Comment/>
<Type>Action</Type>
</Action>
</ListOfActionIo>
</PayLoad>
</Event>
</EventList>
<DestinationList>
<Destination>
<DestinationName>NSW Aboriginal Education Consultative Group Incorporated</DestinationName>
</Destination>
<Destination>
<DestinationName>NSW Aboriginal Education Consultative Group Incorporated</DestinationName>
</Destination>
</DestinationList>
</Message>
</PropertySet>
You are asking the wrong question. You don't want to "remove namespaces" - you want to change the namespace of transformed elements. This is akin to renaming the elements.
Now, since your example is confusing (and too long), consider the following:
XML
<root>
<colors>
<color>red</color>
<color>blue</color>
</colors>
<shapes xmlns="some-unknown-namespace">
<shape>circle</shape>
<shape>square</shape>
</shapes>
<sizes>
<size>small</size>
<size>large</size>
</sizes>
</root>
To change the namespace of shapes (and its descendants, that inherit it!) to no-namespace, without knowing in advance what the original namespace will be, you can do:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[ancestor-or-self::*[name()='shapes']]">
<xsl:element name="{local-name()}">
<xsl:apply-templates select="#*|node()"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Result
<?xml version="1.0" encoding="UTF-8"?>
<root>
<colors>
<color>red</color>
<color>blue</color>
</colors>
<shapes>
<shape>circle</shape>
<shape>square</shape>
</shapes>
<sizes>
<size>small</size>
<size>large</size>
</sizes>
</root>
Added:
lets modify the code to move the shapes into sizes and remove the shapes node.
OK, let's do that:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="sizes">
<xsl:copy>
<xsl:apply-templates/>
<!-- move the shapes into sizes -->
<xsl:apply-templates select="../*[name()='shapes']/*"/>
</xsl:copy>
</xsl:template>
<!-- remove the shapes element -->
<xsl:template match="*[name()='shapes']"/>
<xsl:template match="*[ancestor::*[name()='shapes']]">
<xsl:element name="{local-name()}">
<xsl:apply-templates select="#*|node()"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Result
<?xml version="1.0" encoding="UTF-8"?>
<root>
<colors>
<color>red</color>
<color>blue</color>
</colors>
<sizes>
<size>small</size>
<size>large</size>
<shape>circle</shape>
<shape>square</shape>
</sizes>
</root>

Get enum value from string using xslt and xsd

I am trying to get the enum value of the corresponding string. I am translating one XML into another.
For example, the source element is
<VehicleBodyType>Van</VehicleBodyType>
I need to transform it to
<VehicleTypeCode>5</VehicleTypeCode>
This is in an XSD:
<xs:simpleType name="VehicleBodyType">
<xs:restriction base="xs:string">
<xs:enumeration value="NotProvided" />
<xs:enumeration value="NotApplicable" />
<xs:enumeration value="PassengerCar" />
<xs:enumeration value="TruckPickupOrPassengerTruck" />
<xs:enumeration value="Van" />
<xs:enumeration value="TruckSingleUnitTruck2Axles" />
<xs:enumeration value="MotorHomeRecreationalVehicle" />
</xs:restriction>
</xs:simpleType>
I tried this:
<VehicleTypeCode>
<xsl:template match="xs:simpleType[#name='VehicleBodyType']/xs:restriction">
<xsl:for-each select="xs:enumeration">
<xsl:value-of select="#value"/>
</xsl:for-each>
</xsl:template>
</VehicleTypeCode>
but would get an error indicating that I can't do a template as a child of 'VehicleTypeCode' element.
I would prefer to use an XSD, but I can put this into the XSLT as well, if that makes it easier. I don't even know if the for-each is valid, but I found it on here and it looks like what I want.
Here is a sample of the source xml:
<?xml version="1.0" encoding="UTF-8"?>
<Crash>
<Vehicles>
<Vehicle>
<VehicleBodyType>Van</VehicleBodyType>
<VehicleColor>Red</VehicleColor>
</Vehicle>
</Vehicles>
</Crash>
Here the stripped down xslt i'm using:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0" exclude-result-prefixes="xsl xs fn xsi">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/Crash" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<CrashEntity>
<WorkZoneWorkers>
<xsl:value-of select="WorkersPresentCde"/>
</WorkZoneWorkers>
<xsl:choose>
<xsl:when test="not(Vehicles/Vehicle)">
<CrashUnits/>
</xsl:when>
<xsl:otherwise>
<CrashUnits>
<xsl:apply-templates select="Vehicles/Vehicle" />
</CrashUnits>
</xsl:otherwise>
</xsl:choose>
</CrashEntity>
</xsl:template>
<!-- Vehicles/Vehicle -->
<xsl:template match="Vehicles/Vehicle">
<CrashUnitsEntity>
<VehicleTypeCode>
<xsl:value-of select="VehicleBodyType"/>
</VehicleTypeCode>
<!--Can't use a template within a template-->
<!--<xsl:template match="xs:simpleType[#name='VehicleBodyType']/xs:restriction">
<VehicleTypeCode>
<xsl:value-of select="count(xs:enumeration[#value = 'Van']/preceding-sibling::xs:enumeration) + 1"/>
</VehicleTypeCode>
</xsl:template>-->
<!--Can't use a template within a template (original attempt)-->
<!--<VehicleTypeCode>
<xsl:template match="xs:simpleType[#name=$data]/xs:restriction">
<xsl:for-each select="xs:enumeration">
<xsl:value-of select="#value"/>
</xsl:for-each>
</xsl:template>
</VehicleTypeCode>-->
<!--Try to call a function-->
<VehicleTypeCode function="Enum1">
<xsl:call-template name="getEnum1">
<xsl:with-param name="type" select="VehicleBodyType"/>
<xsl:with-param name="data" select="VehicleBodyType"/>
</xsl:call-template>
</VehicleTypeCode>
<!--Try to call a function-->
<VehicleTypeCode function="Enum2">
<xsl:call-template name="getEnum2">
<xsl:with-param name="type" select="VehicleBodyType"/>
<xsl:with-param name="data" select="VehicleBodyType"/>
</xsl:call-template>
</VehicleTypeCode>
<Vehicle>
<UnitNumber>
<xsl:value-of select="#VehicleNumber"/>
</UnitNumber>
</Vehicle>
</CrashUnitsEntity>
</xsl:template>
<!-- ##################################### functions ##################################### -->
<!-- Can't call a template inside another template-->
<xsl:template name="getEnum1">
<xsl:param name="type"/>
<xsl:param name="data"/>
<xsl:if test="$data">
<!--<xsl:template match="xs:simpleType[#name=$type]/xs:restriction">
<xsl:for-each select="xs:enumeration">
<xsl:value-of select="#value"/>
</xsl:for-each>
</xsl:template>-->
</xsl:if>
</xsl:template>
<!-- Can't call a template inside another template-->
<xsl:template name="getEnum2">
<xsl:param name="type"/>
<xsl:param name="data"/>
<xsl:if test="$data">
<!--<xsl:template match="xs:simpleType[#name=$type]/xs:restriction">
<xsl:value-of select="count(xs:enumeration[#value = $data]/preceding-sibling::xs:enumeration) + 1"/>
</xsl:template>-->
</xsl:if>
</xsl:template>
<xs:simpleType name="VehicleBodyType">
<xs:restriction base="xs:string">
<xs:enumeration value="NotProvided" />
<xs:enumeration value="NotApplicable" />
<xs:enumeration value="PassengerCar" />
<xs:enumeration value="Van" />
<xs:enumeration value="Truck" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="VehicleColor">
<xs:restriction base="xs:string">
<xs:enumeration value="NotProvided" />
<xs:enumeration value="Red" />
<xs:enumeration value="Green" />
<xs:enumeration value="Blue" />
</xs:restriction>
</xs:simpleType>
</xsl:stylesheet>
Expected output xml:
<?xml version="1.0" encoding="UTF-8"?>
<CrashEntity>
<WorkZoneWorkers/>
<CrashUnits>
<CrashUnitsEntity>
<VehicleTypeCode>4</VehicleTypeCode>
<VehicleColor>2</VehicleColor>
</CrashUnitsEntity>
</CrashUnits>
</CrashEntity>

Based on the object corresponding values should be taken using xslt

INPUT XML
<root>
<file1>
<commodity>
<units>1</units>
<obj>mango</obj>
</commodity>
<commodity>
<units>5</units>
<obj>guava</obj>
</commodity>
</file1>
<file2>
<category>
<object>guava</object>
<type>CAT1</type>
<colour>green</colour>
</category>
<category>
<object>mango</object>
<type>CAT2</type>
<colour>yellow</colour>
</category>
</file2>
</root>
I need to compare the values of obj in file1 and object in file2 under root, if same I need to take their corresponding units, type and colour and produce the following output using xslt.
OUTPUT XML
<output>
<com>
<name>guava</name>
<num>5</num>
<category>CAT1</category>
<col>green</col>
</com>
<com>
<name>mango</name>
<num>1</num>
<category>CAT2</category>
<col>yellow</col>
</com>
</output>
I tried the below XSLT but the response is not as expected. Its not looping properly. Could you please tell me where I am going wrong.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml" version="1.0" encoding="UTF-8"
indent="yes" />
<xsl:key name="object-search" match="root/file1/commodity" use="obj" />
<xsl:template match="/">
<output>
<xsl:for-each select="key('object-search', //category/object)">
<com>
<name>
<xsl:value-of select="obj" />
</name>
<num>
<xsl:value-of select="units" />
</num>
<category>
<xsl:value-of
select="//root/file2/category/type" />
</category>
<col>
<xsl:value-of
select="//root/file2/category/colour" />
</col>
</com>
</xsl:for-each>
</output>
</xsl:template>
</xsl:stylesheet>
Try it this way:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="cat" match="category" use="object" />
<xsl:template match="/root">
<output>
<xsl:for-each select="file1/commodity">
<com>
<name>
<xsl:value-of select="obj" />
</name>
<num>
<xsl:value-of select="units" />
</num>
<xsl:variable name="cat" select="key('cat', obj)" />
<category>
<xsl:value-of select="$cat/type" />
</category>
<col>
<xsl:value-of select="$cat/colour" />
</col>
</com>
</xsl:for-each>
</output>
</xsl:template>
</xsl:stylesheet>
Note that the result is slightly different from what you posted:
<?xml version="1.0" encoding="UTF-8"?>
<output>
<com>
<name>mango</name>
<num>1</num>
<category>CAT2</category>
<col>yellow</col>
</com>
<com>
<name>guava</name>
<num>5</num>
<category>CAT1</category>
<col>green</col>
</com>
</output>
Alternatively, you could do:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="com" match="commodity" use="obj" />
<xsl:template match="/root">
<output>
<xsl:for-each select="file2/category">
<xsl:variable name="com" select="key('com', object)" />
<com>
<name>
<xsl:value-of select="$com/obj" />
</name>
<num>
<xsl:value-of select="$com/units" />
</num>
<category>
<xsl:value-of select="type" />
</category>
<col>
<xsl:value-of select="colour" />
</col>
</com>
</xsl:for-each>
</output>
</xsl:template>
</xsl:stylesheet>
and get:
<?xml version="1.0" encoding="UTF-8"?>
<output>
<com>
<name>guava</name>
<num>5</num>
<category>CAT1</category>
<col>green</col>
</com>
<com>
<name>mango</name>
<num>1</num>
<category>CAT2</category>
<col>yellow</col>
</com>
</output>

Unable to Successfully Pass Parameters to xsl:call-template

I have a generic template I've designed with 2 params title and category.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.1"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:param name="category" />
<xsl:param name="title" />
<xsl:template name="test-group">
<fo:block>
<xsl:value=of select="$title" />
</fo:block>
<fo:block>
<xsl:value-of select="$category" />
</fo:block>
</xsl:template>
</xsl:stylesheet>
In the parent template I have the following:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:include href="templates/generic_template.xsl" />
...
<xsl:call-template name="test-group">
<xsl:with-param name="category" select="'animals'" />
<xsl:with-param name="title" select="'DOGS'" />
</xsl:call-template>
...
</xsl:stylesheet>
However, when the transform completes title and category are blank. I'm using FOP 2.0 so I'm not sure if this is a known shortcoming.
When defining a xsl:template that takes parameters, the parameter names used within the xsl:template should be declared using xls:param elements nested within.
<xsl:template name="test-group">
<xsl:param name="category" />
<xsl:param name="title" />
...
</xsl:template>
The parameters being attached to the xsl:template and not the xsl:stylesheet.
This is similar to when calling the template with xsl:call-template, except you are specifying the values instead using xsl:with-param.

transformation in particular sequence

I would like to know that is it possible to move xml element up or down in element tree.
The input xml.
<ROOT>
<A1>A</A1>
<B1>B</B1>
<C1>C</C1>
<D1>D</D1>
</ROOT>
The required output xml.
<ROOT>
<A1>A</A1>
<D1>D</D1>
<B1>B</B1>
<C1>C</C1>
</ROOT>
XSD Sequence Rule
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="ROOT">
<xs:complexType>
<xs:sequence>
<xs:element type="xs:string" name="A1"/>
<xs:element type="xs:string" name="D1"/>
<xs:element type="xs:string" name="B1"/>
<xs:element type="xs:string" name="C1"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Can anyone provide me some XSLT example to do this such of thing? Thank you for any help in advance.
Martin Honnen help me to get answer from other post, hence just thought to share answer to help others but still I am wondering if there is any other way to do this - as in this approach if there is change in XSD tag sequence one has to change xsl sequence too.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output indent="yes"/>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ROOT">
<ROOT>
<xsl:apply-templates select="A1"/>
<xsl:apply-templates select="D1"/>
<xsl:apply-templates select="C1"/>
<xsl:apply-templates select="B1"/>
</ROOT>
</xsl:template>
<xsl:template match="A1">
<a1>
<xsl:apply-templates />
</a1>
</xsl:template>
<xsl:template match="B1">
<b1>
<xsl:apply-templates />
</b1>
</xsl:template>
<xsl:template match="C1">
<c1>
<xsl:apply-templates />
</c1>
</xsl:template>
<xsl:template match="D1">
<d1>
<xsl:apply-templates />
</d1>
</xsl:template>
</xsl:stylesheet>