Search code examples
xsltxslt-1.0apply-templates

XSLT Identity template overriding


I need to remove some unwanted fields over a big response XML using XSL 1.0, and want to use apply-templates instead of for-each. Below is the code I tried but is not giving expected results i.e., unwanted fields are removed successfully but few other fields outside match also disappeared. Am I using identity template incorrectly.

Input XML:

   <?xml version="1.0" encoding="UTF-8"?>
   <xsl:object xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:array name="BankDetails">
   <one>field1</one>
   <two>field2</two>
   <xsl:object>
   <date>1234-56-78</date>
   <Time>12345678</Time>
   </xsl:object>
   <xsl:object>
   <date>0000-00-00</date>
   <Time>00000000</Time>
   </xsl:object>
   <xsl:object>
   <date>0000-00-00</date>
   <Time>00000000</Time>
   </xsl:object>
   <xsl:object>
   <date>0000-00-00</date>
   <Time>00000000</Time>
   </xsl:object>
   <three>field3</three>
   <four>field4</four>
   <five>field5</five>
   <six>field6</six>
   </xsl:array>
   </xsl:object>

Applied XSLT:

   <xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:axsl="http://www.w3.org/1999/XSL/TransformAlias"
    xmlns:str="http://exslt.org/strings">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
    <xsl:namespace-alias stylesheet-prefix="axsl"   result-prefix="xsl" />
   <xsl:template match="@*|node()">
       <xsl:copy>
           <xsl:apply-templates select="@*|node()"/>
       </xsl:copy>
   </xsl:template>
     <xsl:template match="xsl:object/xsl:array">    
           <xsl:for-each select="xsl:object[Time !='00000000']">
                <xsl:copy-of select = "."/>
           </xsl:for-each>  
   </xsl:template>
   </xsl:stylesheet>

What I got:

   <?xml version="1.0" encoding="UTF-8"?><xsl:object xmlns:xsl="http://www.w3.org/1999/XSL/Transform">    
       <xsl:object>        
           <date>1234-56-78</date>
            <Time>12345678</Time>
            </xsl:object>
   </xsl:object>
   

What is expected:

   <?xml version="1.0" encoding="UTF-8"?>
   <xsl:object xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:array name="BankDetails">
        <one>field1</one>
        <two>field2</two>
        <xsl:object>
            <date>1234-56-78</date>
            <Time>12345678</Time>
        </xsl:object>
        <three>field3</three>
        <four>field4</four>
        <five>field5</five>
        <six>field6</six>
    </xsl:array>
   </xsl:object>    

Solution

  • The problem with your attempt is that you are copying only xsl:object elements that have the right Time - but not doing anything (i.e. copy or apply templates) for the other elements that are also children of the context xsl:array element (one, two etc). If you do not apply templates to them, then the identity transform template will not be applied to them.

    You are also not copying the context xsl:array element.

    I would suggest you approach it from the opposite point-of-view:

    XSLT 1.0

    <xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:axsl="http://www.w3.org/1999/XSL/TransformAlias">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
    <xsl:strip-space elements="*"/>
    <xsl:namespace-alias stylesheet-prefix="axsl"   result-prefix="xsl" />
    
    <!-- identity transform -->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    
    <xsl:template match="xsl:object[Time ='00000000']"/>   
              
    </xsl:stylesheet>