XSLT - Counting child nodes after applying muenchian grouping - xslt-1.0

For the below input XML, I am able to group all the child <invoice> elements under the appropriate <shippingBill> element using muenchian grouping method. However there is a requirement to include the count of the number of <shippingBill>elements and the <invoice> elements in the final output XML. I am not sure how to go about it.
Input XML
<bank>
<shippingBills>
<shippingBill>
<shippingBillNo>5786885</shippingBillNo>
<shippingBillDate>10/02/2016</shippingBillDate>
<LEODate>11/02/2016</LEODate>
<invoice>
<invoiceSerialNo>1</invoiceSerialNo>
<invoiceNo>183</invoiceNo>
<invoiceDate>07/02/2016</invoiceDate>
</invoice>
</shippingBill>
<shippingBill>
<shippingBillNo>5786885</shippingBillNo>
<shippingBillDate>10/02/2016</shippingBillDate>
<LEODate>11/02/2016</LEODate>
<invoice>
<invoiceSerialNo>2</invoiceSerialNo>
<invoiceNo>184</invoiceNo>
<invoiceDate>07/02/2016</invoiceDate>
</invoice>
</shippingBill>
<shippingBill>
<shippingBillNo>3318135</shippingBillNo>
<shippingBillDate>01/10/2015</shippingBillDate>
<LEODate>01/10/2015</LEODate>
<invoice>
<invoiceSerialNo>1</invoiceSerialNo>
<invoiceNo>172</invoiceNo>
<invoiceDate>29/09/2015</invoiceDate>
</invoice>
</shippingBill>
<shippingBill>
<shippingBillNo>3318135</shippingBillNo>
<shippingBillDate>01/10/2015</shippingBillDate>
<LEODate>01/10/2015</LEODate>
<invoice>
<invoiceSerialNo>2</invoiceSerialNo>
<invoiceNo>173</invoiceNo>
<invoiceDate>29/09/2015</invoiceDate>
</invoice>
</shippingBill>
</shippingBills>
</bank>
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:key name="key-bill" match="shippingBill" use="shippingBillNo"/>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*" />
</xsl:copy>
</xsl:template>
<xsl:template match="shippingBills">
<xsl:copy>
<xsl:apply-templates
select="shippingBill[generate-id() = generate-id(key('key-bill', shippingBillNo)[1])]"
mode="group" />
</xsl:copy>
</xsl:template>
<xsl:template match="shippingBill" mode="group">
<shippingBill>
<xsl:apply-templates select="*[not(self::invoice)]" />
<invoices>
<xsl:apply-templates select="key('key-bill', shippingBillNo)/invoice" />
</invoices>
</shippingBill>
</xsl:template>
</xsl:stylesheet>
Final Output XML Required
The <checkSum> element has been added which has child elements that hold the respective counts.
<bank>
<checkSum>
<noOfInvoices>4</noOfInvoices>
<noOfShippingBills>2</noOfShippingBills>
</checkSum>
<shippingBills>
<shippingBill>
<shippingBillNo>5786885</shippingBillNo>
<shippingBillDate>10/02/2016</shippingBillDate>
<LEODate>11/02/2016</LEODate>
<invoices>
<invoice>
<invoiceSerialNo>1</invoiceSerialNo>
<invoiceNo>183</invoiceNo>
<invoiceDate>07/02/2016</invoiceDate>
</invoice>
<invoice>
<invoiceSerialNo>2</invoiceSerialNo>
<invoiceNo>184</invoiceNo>
<invoiceDate>07/02/2016</invoiceDate>
</invoice>
</invoices>
</shippingBill>
<shippingBill>
<shippingBillNo>3318135</shippingBillNo>
<shippingBillDate>01/10/2015</shippingBillDate>
<LEODate>01/10/2015</LEODate>
<invoices>
<invoice>
<invoiceSerialNo>1</invoiceSerialNo>
<invoiceNo>172</invoiceNo>
<invoiceDate>29/09/2015</invoiceDate>
</invoice>
<invoice>
<invoiceSerialNo>2</invoiceSerialNo>
<invoiceNo>173</invoiceNo>
<invoiceDate>29/09/2015</invoiceDate>
</invoice>
</invoices>
</shippingBill>
</shippingBills>
</bank>

I would do 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:strip-space elements="*" />
<xsl:key name="key-bill" match="shippingBill" use="shippingBillNo" />
<!-- identity transform -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="shippingBills">
<xsl:variable name="distinct-bills" select="shippingBill[generate-id() = generate-id(key('key-bill', shippingBillNo)[1])]" />
<checkSum>
<noOfInvoices>
<xsl:value-of select="count(shippingBill/invoice)" />
</noOfInvoices>
<noOfShippingBills>
<xsl:value-of select="count($distinct-bills)" />
</noOfShippingBills>
</checkSum>
<xsl:copy>
<xsl:apply-templates select="$distinct-bills" mode="group" />
</xsl:copy>
</xsl:template>
<xsl:template match="shippingBill" mode="group">
<shippingBill>
<xsl:apply-templates select="*[not(self::invoice)]" />
<invoices>
<xsl:apply-templates select="key('key-bill', shippingBillNo)/invoice" />
</invoices>
</shippingBill>
</xsl:template>
</xsl:stylesheet>

Related

Replacing a child node with another node without affecting its sub node

I need to replace the child node with another node without affecting its sub nodes, I tried matching the child node but was unable to
This is the xml format
<?xml version="1.0" encoding="UTF-8"?>
<Envelope xmlns="http://schemas.microsoft.com/dynamics/2011/01/documents/Message">
<Header>
<MessageId>{A124-B421-C325-D467}</MessageId>
<Action>find</Action>
</Header>
<Body>
<MessageParts xmlns="http://schemas.microsoft.com/dynamics/2011/01/documents/Message">
<Run xmlns="http://schemas.microsoft.com/dynamics/2008/01/documents/Run">
<RunObject class="entity">
<A1>NA</A1>
<A2>False</A2>
<Object class="entity">
<A3>02</A3>
</Object>
<A4>ER</A4>
</RunObject>
</Run>
</MessageParts>
</Body>
</Envelope>
This is the xml format that i require
<?xml version="1.0" encoding="UTF-8"?>
<Envelope xmlns="http://schemas.microsoft.com/dynamics/2011/01/documents/Message">
<Header>
<MessageId>{A124-B421-C325-D467}</MessageId>
<Action>find</Action>
</Header>
<Body>
<Document>
<Item>
<A1>NA</A1>
<A2>False</A2>
<Base>
<A3>02</A3>
</Base>
<A4>ER</A4>
</Item>
</Document>
</Body>
</Envelope>
This is the code that i through which i tried to change the format
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:m="http://schemas.microsoft.com/dynamics/2011/01/documents/Message"
xmlns:r="http://schemas.microsoft.com/dynamics/2008/01/documents/Run"
exclude-result-prefixes="m r">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- move all elements to no namespace -->
<xsl:template match="*">
<xsl:element name="{local-name()}">
<xsl:copy-of select="#*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<!-- rename MessageParts to Document + skip the Run wrapper -->
<xsl:template match="m:MessageParts">
<Document>
<xsl:apply-templates select="r:Run/*"/>
</Document>
</xsl:template>
<!-- rename RunObject to Item + reorder child nodes -->
<xsl:template match="r:RunObject[#class='entity']">
<Item>
<xsl:apply-templates select="r:A1" />
<xsl:apply-templates select="r:A2" />
<xsl:template match="r:Object[#class='entity']>
<Base>
<xsl:apply-templates select="r:A3" />
</Base>
</xsl:Template>
<xsl:apply-templates select="r:A4" />
</Item>
</xsl:template>
</xsl:stylesheet>
I tried matching the Object element but was unable to since i am already matching its parent element that is RunObject
Your mistake is that you cannot define a template inside of a template. So move the <xsl:template match="r:Object[#class='entity']> to the root level and add an <xsl:apply-templates select="r:Object" /> at its place.
The stylesheet could look like this:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:m="http://schemas.microsoft.com/dynamics/2011/01/documents/Message" xmlns:r="http://schemas.microsoft.com/dynamics/2008/01/documents/Run" exclude-result-prefixes="m r">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- move all elements to no namespace -->
<xsl:template match="*">
<xsl:element name="{local-name()}">
<xsl:copy-of select="#*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<!-- rename MessageParts to Document + skip the Run wrapper -->
<xsl:template match="m:MessageParts">
<Document>
<xsl:apply-templates select="r:Run/*"/>
</Document>
</xsl:template>
<!-- rename RunObject to Item + reorder child nodes -->
<xsl:template match="r:RunObject[#class='entity']">
<Item>
<xsl:apply-templates select="r:A1" />
<xsl:apply-templates select="r:A2" />
<xsl:apply-templates select="r:Object" />
<xsl:apply-templates select="r:A4" />
</Item>
</xsl:template>
<xsl:template match="r:Object[#class='entity']">
<Base>
<xsl:apply-templates select="r:A3" />
</Base>
</xsl:template>
</xsl:stylesheet>
Its output is (nearly) as desired:
<?xml version="1.0" encoding="UTF-8"?>
<Envelope>
<Header>
<MessageId>{A124-B421-C325-D467}</MessageId>
<Action>find</Action>
</Header>
<Body>
<Document>
<Item>
<A1>NA</A1>
<A2>False</A2>
<Base>
<A3>02</A3>
</Base>
<A4>ER</A4>
</Item>
</Document>
</Body>
</Envelope>
I added the adjective "nearly", because this result has no namespace, while the sample of your desired outcome is in the namespace
xmlns:m="http://schemas.microsoft.com/dynamics/2011/01/documents/Message"
But because you defined a template that removes the namespaces of all elements, I did ignore that. I simply assume that this part of your question is erroneous.
If you like to change that, restrict the first template and add a general identity template:
<!-- move all elements to no namespace -->
<xsl:template match="*[namespace-uri() != 'http://schemas.microsoft.com/dynamics/2011/01/documents/Message']">
<xsl:element name="{local-name()}">
<xsl:copy-of select="#*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
This would make your output containing the root namespace:
<?xml version="1.0" encoding="UTF-8"?>
<Envelope xmlns="http://schemas.microsoft.com/dynamics/2011/01/documents/Message">
<Header>
<MessageId>{A124-B421-C325-D467}</MessageId>
<Action>find</Action>
</Header>
<Body>
<Document xmlns="">
<Item>
<A1>NA</A1>
<A2>False</A2>
<Base>
<A3>02</A3>
</Base>
<A4>ER</A4>
</Item>
</Document>
</Body>
</Envelope>

Removing Parent Nodes without affecting child nodes

The XML output i am getting is not in the format that i require so tried some code to change the format but was unable to
This is the output that i am getting
<?xml version="1.0" encoding="UTF-8"?>
<Envelope xmlns="http://schemas.microsoft.com/dynamics/2011/01/documents/Message">
<Header>
<MessageId>{A124-B421-C325-D467}</MessageId>
<Action>find</Action>
</Header>
<Body>
<MessageParts xmlns="http://schemas.microsoft.com/dynamics/2011/01/documents/Message">
<Run xmlns="http://schemas.microsoft.com/dynamics/2008/01/documents/Run">
<RunObject class="entity">
<A1>NA</A1>
<A2>False</A2>
<A3>02</A3>
<A4>ER</A4>
</RunObject>
<RunObject class="entity">
<A1>NA</A1>
<A2>False</A2>
<A3>03</A3>
<A4>ER</A4>
</RunObject>
</Run>
</MessageParts>
</Body>
</Envelope>
This is the XML output that i require
<?xml version="1.0" encoding="UTF-8"?>
<Document>
<Item>
<A3>NA</A3>
<A4>False</A4>
<A2>02</A2>
<A1>ER</A1>
</Item>
<Item>
<A3>NA</A3>
<A4>False</A4>
<A2>03</A2>
<A1>ER</A1>
</Item>
</Document>
This is the code that i have used to change the format of the xml that i was getting
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:m="http://schemas.microsoft.com/dynamics/2011/01/documents/Message"
xmlns:r="http://schemas.microsoft.com/dynamics/2008/01/documents/Run"
exclude-result-prefixes="m r">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- move all elements to no namespace -->
<xsl:template match="*">
<xsl:element name="{local-name()}">
<xsl:copy-of select="#*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="m:Envelope"/>
<xsl:template match="m:Header"/>
<xsl:template match="m:MessageId"/>
<xsl:template match="m:Action"/>
<xsl:template match="m:Body"/>
<!-- rename MessageParts to Document + skip the Run wrapper -->
<xsl:template match="m:MessageParts">
<Document>
<xsl:apply-templates select="r:Run/*"/>
</Document>
</xsl:template>
<!-- rename RunObject to Item + reorder child nodes -->
<xsl:template match="r:RunObject[#class='entity']">
<Item>
<xsl:apply-templates select="r:A3" />
<xsl:apply-templates select="r:A4" />
<xsl:apply-templates select="r:A2" />
<xsl:apply-templates select="r:A1" />
</Item>
</xsl:template>
</xsl:stylesheet>
I tried the above code but was not able to change the format of the xml
Instead of:
<xsl:template match="m:Envelope"/>
that removes the Envelope node and all its descendants, you need to remove only the Envelope wrapper and continue processing its contents:
<xsl:template match="m:Envelope">
<xsl:apply-templates/>
</xsl:template>
Likewise for the other wrappers. In fact, you could replace all of these:
<xsl:template match="m:Envelope"/>
<xsl:template match="m:Header"/>
<xsl:template match="m:MessageId"/>
<xsl:template match="m:Action"/>
<xsl:template match="m:Body"/>
with:
<xsl:template match="m:*">
<xsl:apply-templates select="*"/>
</xsl:template>

Changing the output of xml using xslt

How to change the output of the xml.
This is the output that i am getting.
<?xml version="1.0" encoding="UTF-8"?>
<Envelope xmlns="http://schemas.microsoft.com/dynamics/2011/01/documents/Message">
<Header> </Header>
<Body>
<MessageParts xmlns="http://schemas.microsoft.com/dynamics/2011/01/documents/Message">
<Run xmlns="http://schemas.microsoft.com/dynamics/2008/01/documents/Run">
<RunObject class="entity">
<A1>NA</A1>
<A2>False</A2>
<A3>02</A3>
<A4>ER</A4>
</RunObject>
<RunObject class="entity">
<A1>NA</A1>
<A2>False</A2>
<A3>03</A3>
<A4>ER</A4>
</RunObject>
</Run>
</MessageParts>
</Body>
</Envelope>
And the output that i want is this
<?xml version="1.0" encoding="UTF-8"?>
<Envelope>
<Header> </Header>
<Body>
<Document>
<Item>
<A1>NA</A1>
<A2>False</A2>
<A3>02</A3>
<A4>ER</A4>
</Item>
<Item>
<A1>NA</A1>
<A2>False</A2>
<A3>03</A3>
<A4>ER</A4>
</Item>
</Document>
</Body>
</Envelope>
I have tried various things but still i am not to make one final change.
I am not able to change <Runobject class="Entity"> to <Item>.
This the xslt code that i used to alter the xml format
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:s="http://schemas.microsoft.com/dynamics/2008/01/documents/Run"
>
<xsl:output method="xml" indent="yes"/>
**Removes the run tag along with the namespace
<xsl:template match="s:Run">
<xsl:apply-templates select="*"/>
</xsl:template>
**Copies all the tags
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
**Used this code to replace the <RunObject class="entity"> with <Item> but is not working
<xsl:template match="RunObject[#class='Entity']">
<xsl:element name="Item">
<xsl:apply-templates />
</xsl:element>
</xsl:template>
**Removes all namespaces
<xsl:template match="*">
<xsl:element name="{local-name()}">
<xsl:apply-templates select="#* | node()"/>
</xsl:element>
</xsl:template>
**Copies attributes
<xsl:template match="#*">
<xsl:attribute name="{local-name()}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
<!-- template to copy the rest of the nodes -->
<xsl:template match="comment() | text() | processing-instruction()">
<xsl:copy/>
</xsl:template>
</xsl:stylesheet>
I am fairly new to xslt so i mght have certain mistakes while writing the code
There are two reasons why your template:
<xsl:template match="RunObject[#class='Entity']">
<xsl:element name="Item">
<xsl:apply-templates />
</xsl:element>
</xsl:template>
does not match anything:
RunObject is in a namespace, and you are not using a prefix;
XML is case-sensitive; the class attribute contains "entity", not "Entity".
It should work if you do:
<xsl:template match="s:RunObject[#class='entity']">
<xsl:element name="Item">
<xsl:apply-templates />
</xsl:element>
</xsl:template>
Other than that, I believe you could shorten the entire thing considerably - say:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:m="http://schemas.microsoft.com/dynamics/2011/01/documents/Message"
xmlns:r="http://schemas.microsoft.com/dynamics/2008/01/documents/Run"
exclude-result-prefixes="m r">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- move all elements to no namespace -->
<xsl:template match="*">
<xsl:element name="{local-name()}">
<xsl:copy-of select="#*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<!-- rename MessageParts to Document + skip the Run wrapper -->
<xsl:template match="m:MessageParts">
<Document>
<xsl:apply-templates select="r:Run/*"/>
</Document>
</xsl:template>
<!-- rename RunObject to Item -->
<xsl:template match="r:RunObject[#class='entity']">
<Item>
<xsl:apply-templates />
</Item>
</xsl:template>
</xsl:stylesheet>

XSLT 1.0 Move of one Segment

please tell me, how can i move the Segment "BGM" from "CNT" to "GRP"?
Actually XML:
<?xml version="1.0"?>
<SEEDELFOR>
<AG/>
<CNT>
<TRANSMISSION_DATE>20190307</TRANSMISSION_DATE>
<TRANSMISSION_TIME>113300</TRANSMISSION_TIME> </INTERCHANGE_CONTROL_NUMBER>
</SENDER>
</SENDER_QUALIFIER>
</RECEIVER>
</RECEIVER_QUALIFIER>
</SYNTAX_IDENTIFIER>
</SYNTAX_VERSION>
<BGM>227</BGM>
<GRP>
</IDENTIFIER_BY>
</IDENTIFIER_SU>
</DATE_4>
</REF_ON>
</GRP>
</CNT>
</SEEDELFOR>
Correct output of my XML Should be:
<?xml version="1.0"?>
<SEEDELFOR>
<AG/>
<CNT>
<TRANSMISSION_DATE>20190307</TRANSMISSION_DATE>
<TRANSMISSION_TIME>113300</TRANSMISSION_TIME>
<SENDER></SENDER>
</SENDER_QUALIFIER>
</RECEIVER>
</RECEIVER_QUALIFIER>
</SYNTAX_IDENTIFIER>
</SYNTAX_VERSION>
<GRP>
<BGM>227</BGM>
</GRP>
</CNT>
</SEEDELFOR>
Here´s my XSLT: I tried to copy, but i think it´s better to move the segment?
Edit: Thats my full XSLT: Maybe i have to cominate with other copy segments?
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<!--Copy all of CNT != BGM-->
<xsl:template match="CNT">
<xsl:copy>
<xsl:apply-templates select="*[local-name()!='BGM']" />
</xsl:copy>
</xsl:template>
<!--copy BGM from CNT to GRP-->
<xsl:template match="GRP">
<xsl:element name="GRP">
<xsl:apply-templates />
<xsl:copy-of select="../BGM" />
</xsl:element>
</xsl:template>
<!--copy the data from ADD/CONTACT with Qualifier EM to GRP, so it can be used in the mapping to set EMAIL from Customer-->
<xsl:template match="GRP">
<xsl:copy>
<xsl:for-each select ="./ADD/CONTACT">
<xsl:if test="./QUALIFIER='EM'">
<CONTACT_EMAIL>
<xsl:value-of select="NUMBER"/>
</CONTACT_EMAIL>
</xsl:if>
<xsl:if test="./QUALIFIER='TE'">
<CONTACT_TEL>
<xsl:value-of select="NUMBER"/>
</CONTACT_TEL>
</xsl:if>
<xsl:if test="./QUALIFIER='FX'">
<CONTACT_FAX>
<xsl:value-of select="NUMBER"/>
</CONTACT_FAX>
</xsl:if>
</xsl:for-each>
<!--copy all other nodes-->
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<!--delete IC node-->
<xsl:template match="IC" />
<!--delete FILTER_SET node-->
<xsl:template match="FILTER_SET" />
<!--delete SEE_AG node-->
<xsl:template match="SEE_AG" />
<!--delete ME node-->
<xsl:template match="ME" />
<!--delete ADD node-->
<xsl:template match="ADD" />
<!-- delete segment (ADD) with specified QUALIFER (SU) -->
<xsl:template match="ADD[QUALIFIER='SU']"/>
<!--delete TRANSPORT_DETAILS node-->
<xsl:template match="TRANSPORT_DETAILS" />
<!--delete PACKAGE_DETAILS node-->
<xsl:template match="PACKAGE_DETAILS" />
<!--delete AMOUNT_DETAILS node-->
<xsl:template match="AMOUNT_DETAILS" />
<!--delete IC node-->
<xsl:template match="CONTACT" />
<!-- delete empty nodes -->
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[not(#*|*|comment()|processing-instruction()) and normalize-space()='']"/>
<!-- delete empty nodes -->
</xsl:stylesheet>
Thanks for your help.
Best regards
Julian
The idiomatic approach to "moving" a node from one place to another is:
copy everything as is,
except the node in question, and
copy the node to its new place:
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>
<!-- remove BGM -->
<xsl:template match="BGM"/>
<xsl:template match="GRP">
<xsl:copy>
<xsl:apply-templates/>
<!-- add BGM -->
<xsl:copy-of select="../BGM" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
If you need to modify other nodes, add templates matching them as necessary.
Seems your XML is not well formed. If I have got it right then you can find below xslt to achieve your requirement:
XML can be:
<?xml version="1.0"?>
<SEEDELFOR>
<AG />
<CNT>
<TRANSMISSION_DATE>20190307</TRANSMISSION_DATE>
<TRANSMISSION_TIME>113300</TRANSMISSION_TIME>
<INTERCHANGE_CONTROL_NUMBER />
<SENDER />
<SENDER_QUALIFIER />
<RECEIVER />
<RECEIVER_QUALIFIER />
<SYNTAX_IDENTIFIER />
<SYNTAX_VERSION />
<BGM>227</BGM>
<GRP>
<IDENTIFIER_BY />
<IDENTIFIER_SU />
<DATE_4 />
<REF_ON />
</GRP>
</CNT>
</SEEDELFOR>
An the solution would be:
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="*">
<xsl:copy>
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
<xsl:template match="CNT">
<xsl:copy>
<xsl:apply-templates select="*[local-name()!='BGM']" />
</xsl:copy>
</xsl:template>
<xsl:template match="GRP">
<xsl:element name="GRP">
<xsl:apply-templates />
<xsl:copy-of select="../BGM" />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
http://xsltransform.net/eieE3Q5
<!-- remove BGM at CNT-->
<xsl:template match="BGM"/>
<!--copy the data from ADD/CONTACT with Qualifier EM to GRP, so it can be used in the mapping to set EMAIL from Customer-->
<xsl:template match="GRP">
<xsl:copy>
<xsl:for-each select ="./ADD/CONTACT">
<xsl:if test="./QUALIFIER='EM'">
<CONTACT_EMAIL>
<xsl:value-of select="NUMBER"/>
</CONTACT_EMAIL>
</xsl:if>
<xsl:if test="./QUALIFIER='TE'">
<CONTACT_TEL>
<xsl:value-of select="NUMBER"/>
</CONTACT_TEL>
</xsl:if>
<xsl:if test="./QUALIFIER='FX'">
<CONTACT_FAX>
<xsl:value-of select="NUMBER"/>
</CONTACT_FAX>
</xsl:if>
</xsl:for-each>
<!--copy BGM from CNT to GRP -->
<xsl:copy-of select="../BGM" />
<!--copy all other nodes-->
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>

template not getting applied with XSLT

I am using xslt to convert xml to xml.
<root>
<elem>
<confs>
<conf1>1</conf1>
<conf2>2</conf2>
</confs>
</elem>
</root>
My XSL
<xsl:template match="elem">
<xsl:copy>
<xsl:attribute name="className">confs</xsl:attribute>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="confs">
<confs>
<xsl:for-each select="*">
<conf>
<value>
<xsl:value-of select="node()"></xsl:value-of>
</value>
</conf>
</confs>
</xsl:template>
desired output:
<root>
<elem className="confs>
<confs>
<conf>
<value>1</value>
</conf>
<conf>
<value>1</value>
</conf>
</confs>
</elem>
</root>
When ran each template individaully they are good. But I run both the confs template is not affected at all.
Any help?
I believe the most straightforward way to achieve your output would be by:
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="elem">
<elem className="confs">
<xsl:apply-templates/>
</elem>
</xsl:template>
<xsl:template match="confs/*">
<conf>
<value>
<xsl:value-of select="."/>
</value>
</conf>
</xsl:template>
</xsl:stylesheet>