'How to add Attribute as well as child element at same time for XML using XSLT

I am new to XSLT I am trying to perform below operations(adding ID as child element as well pattern as attribute on package) on XML. I have provided expected output as well as my XSLT. Can you please provide me generic solution as I have nested package nodes in xml for simplicity I have provided simple XML.As of now I am able to add only attribute change(pattern) on my xml my ID related changes(child element) is getting overridden.

Input XML

<Package ID="b9e05dea-80dc-436b-bea6-497161b08342" xsi:type="Mobile_Plan_Package_Template" BusinessID="000126" Path="/Package/Product/Launch_Entity" Version="1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Name>SuperCare Plan</Name>
</Package>

Expected Output from XSLT

<Package ID="b9e05dea-80dc-436b-bea6-497161b08342" pattern="Package" xsi:type="Mobile_Plan_Package_Template" BusinessID="000126" Path="/Package/Product/Launch_Entity" Version="1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Name>SuperCare Plan</Name>
<ID>b9e05dea-80dc-436b-bea6-497161b08342</ID>
</Package>

XSLT

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  exclude-result-prefixes="xsi">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
    
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    
    <!--To Add IDs in all nodes-->
    <xsl:template match="*[@ID]" >      
            <xsl:copy>  
            <xsl:apply-templates select="@*|node()"/>
            <ID>
                <xsl:value-of select="current()/@ID" />
            </ID>
            
           </xsl:copy>
                    
    </xsl:template>
    <!--To Add IDs in all nodes-->

    
<!--To Add Attributes in package node-->
   <xsl:template match="*[local-name() = 'Package']">

        <xsl:copy>
            <xsl:attribute name="pattern">
                <xsl:value-of select="local-name()"/>
            </xsl:attribute>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>

    </xsl:template>
<!--To Add Attributes in package node-->


</xsl:stylesheet>

Thanks for your help in advance



Solution 1:[1]

AFAICT, this should work for you:

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="Package">
    <xsl:copy>
        <xsl:attribute name="pattern">
            <xsl:value-of select="local-name()"/>
        </xsl:attribute>
        <xsl:apply-templates select="@*|node()"/>
        <ID>
            <xsl:value-of select="@ID"/>
        </ID>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 michael.hor257k