Search code examples
xmlxsltxsdxproc

Spliting an XML and remove empty attributes using xslt 2.0


I want to remove empty attributes from xml and also need to split it based on particular element .I created two xsl's for splitting and removing empty attributes seperately , its working fine . But i need to combine these two xsl's such that after removing empty attributes the xml needs to be splitted based on particular element .

RemoveAttribute xslt :

 <xsl:template match="node()|@*">        

 <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
 </xsl:copy>
 </xsl:template> 

 <xsl:template match="@*[not(normalize-space(.))]">

  <xsl:if test="descendant::*/@*[not(normalize-space(.))]">
     <xsl:copy />
  </xsl:if>

 </xsl:template>
 </xsl:stylesheet>

Splitting XSLT :

 <?xml version="1.0" encoding="ISO-8859-1"?>
  <xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"        
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

   <xsl:output omit-xml-declaration="yes" indent="yes"/>



   <xsl:template match="/*" >


   <xsl:result-document href="ure.xml">
    <xsl:element name="Employee" >
        <xsl:attribute name="xsi:schemaLocation">sample.xsd</xsl:attribute>
        <xsl:copy-of select="/Employee/*"/>          
    </xsl:element>


</xsl:result-document>

     </xsl:template>


    </xsl:stylesheet>

Input XML :

  <?xml version="1.0" encoding="UTF-8"?>
  <Enroll>
   <Department id="x1" name="">
      <members id ="" name="lio">ds</members>
   </Department>
    <Employee>
    <address id="s1" no=""></address>
    <domain id="" no="34"></domain>
    </Employee>
  </Enroll> 

output_one xml :

   <Department id="x1" name="">
      <members id ="" name="lio">ds</members>
   </Department>

ouput+_two Xml :

   <Employee>
    <address id="s1" ></address>
    <domain  no="34"></domain>
   </Employee>

Output should be an two separate xml file which should have the splitted xml part and empty attributes needs to be removed .

I have tried it using Apply-templates , include and xml pipelining but i couldn't get it working .

Any help would be very much appreciated .


Solution

  • This should accomplish what you are describing:

    <xsl:stylesheet version="2.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 omit-xml-declaration="yes" indent="yes"/>
    
      <xsl:template match="node()|@*">
        <xsl:copy>
          <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
      </xsl:template>
    
      <xsl:template match="Employee//@*[not(normalize-space())]" />
    
      <xsl:template match="/*" >
    
        <xsl:result-document href="output_one.xml">
          <xsl:apply-templates select="Department" />
        </xsl:result-document>
    
        <xsl:result-document href="output_two.xml">
          <xsl:apply-templates select="Employee" />
        </xsl:result-document>
    
      </xsl:template>
    
    </xsl:stylesheet>
    

    When run on your provided input, the result is:

    output_one.xml:

    <Department id="x1" name="">
        <members id="" name="lio">ds</members>
    </Department>
    

    output_two.xml:

    <Employee>
      <address id="s1" />
      <domain no="34" />
    </Employee>