Removing empty nodes

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • jhurrell
    New Member
    • Mar 2007
    • 4

    #1

    Removing empty nodes

    I have an XML file that contains some empty nodes like:

    Code:
    <sample>
       <test/>
       <test1/>
    </sample>
    I am using Saxon 8.8 to transform this XML into another XML file, but I'd like to remove the empty nodes and leave the rest of the document as it was.

    XML:

    Code:
    <?xml version="1.0" ?>
    
    <ROOT>
    	<CRITERION>
    		<CRITERION_ID>1000</CRITERION_ID>
    		<CRITERION_NAME>TEST</CRITERION_NAME>
    	</CRITERION>
    	<CRITERION>
    		<CRITERION_ID>2000</CRITERION_ID>
    		<CRITERION_NAME>TESTA</CRITERION_NAME>
    	</CRITERION>
    	<CRITERION>
    		<CRITERION_ID />
    		<CRITERION_NAME />
    	</CRITERION>
    	<CRITERION>
    		<CRITERION_ID>3000</CRITERION_ID>
    		<CRITERION_NAME>TESTB</CRITERION_NAME>
    	</CRITERION>
    	<CRITERION>
    		<CRITERION_ID />
    		<CRITERION_NAME />
    	</CRITERION>
    </ROOT>
    Required result:

    Code:
    <?xml version="1.0" ?>
    
    <ROOT>
    	<CRITERION>
    		<CRITERION_ID>1000</CRITERION_ID>
    		<CRITERION_NAME>TEST</CRITERION_NAME>
    	</CRITERION>
    	<CRITERION>
    		<CRITERION_ID>2000</CRITERION_ID>
    		<CRITERION_NAME>TESTA</CRITERION_NAME>
    	</CRITERION>
    	<CRITERION>
    		<CRITERION_ID>3000</CRITERION_ID>
    		<CRITERION_NAME>TESTB</CRITERION_NAME>
    	</CRITERION>
    </ROOT>
    So far I have partly managed this using the following stylesheet:

    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    
    <xsl:output method="xml"/>
    <xsl:template match="/">
    	<ROOT>
    		<xsl:for-each select="//CRITERION">
    			<CRITERION>
    				<xsl:copy-of select="CRITERION_ID[normalize-space(.) != '']" />
    				<xsl:copy-of select="CRITERION_NAME[normalize-space(.) != '']" />
    			</CRITERION>
    		</xsl:for-each>
    	</ROOT>
    </xsl:template>	
    
    </xsl:stylesheet>
    However, it creates the following:

    Code:
    <?xml version="1.0" ?>
    
    <ROOT>
    	<CRITERION>
    		<CRITERION_ID>1000</CRITERION_ID>
    		<CRITERION_NAME>TEST</CRITERION_NAME>
    	</CRITERION>
    	<CRITERION>
    		<CRITERION_ID>2000</CRITERION_ID>
    		<CRITERION_NAME>TESTA</CRITERION_NAME>
    	</CRITERION>
    	<CRITERION />
    	<CRITERION>
    		<CRITERION_ID>3000</CRITERION_ID>
    		<CRITERION_NAME>TESTB</CRITERION_NAME>
    	</CRITERION>
    	<CRITERION />
    </ROOT>
    I can see why it does this, but I cannot figure out how to get rid of the empty <CRITERION /> nodes completely.

    Any ideas gratefully received.
  • dorinbogdan
    Recognized Expert Contributor
    • Feb 2007
    • 839

    #2
    Try this method:
    [html]<?xml version="1.0" encoding="UTF-8"?>

    <xsl:output method="xml"/>
    <xsl:template match="/">
    <ROOT>
    <xsl:for-each select="//CRITERION">
    <xsl:if test="CRITERION _ID[normalize-space(.) != ''] or CRITERION_NAME[normalize-space(.) != '']">
    <CRITERION>
    <xsl:copy-of select="CRITERI ON_ID" />
    <xsl:copy-of select="CRITERI ON_NAME" />
    </CRITERION>
    </xsl:if>
    </xsl:for-each>
    </ROOT>
    </xsl:template>

    </xsl:stylesheet>[/html]

    If CRITERION_ID is empty but CRITERION_NAME is not empty, or vice-versa, then both are printed.
    I don't have Saxon, but opened the xml in IE and it shows the text fine.

    Comment

    • jhurrell
      New Member
      • Mar 2007
      • 4

      #3
      Originally posted by dorinbogdan
      Try this method:
      [html]<?xml version="1.0" encoding="UTF-8"?>

      <xsl:output method="xml"/>
      <xsl:template match="/">
      <ROOT>
      <xsl:for-each select="//CRITERION">
      <xsl:if test="CRITERION _ID[normalize-space(.) != ''] or CRITERION_NAME[normalize-space(.) != '']">
      <CRITERION>
      <xsl:copy-of select="CRITERI ON_ID" />
      <xsl:copy-of select="CRITERI ON_NAME" />
      </CRITERION>
      </xsl:if>
      </xsl:for-each>
      </ROOT>
      </xsl:template>

      </xsl:stylesheet>[/html]

      If CRITERION_ID is empty but CRITERION_NAME is not empty, or vice-versa, then both are printed.
      I don't have Saxon, but opened the xml in IE and it shows the text fine.
      Genius!!! Thank you Dorin! This does indeed solve the problem!! I had tried an IF tag, but hadn't thought to combine it with an OR.
      Thanks again.

      Comment

      • dorinbogdan
        Recognized Expert Contributor
        • Feb 2007
        • 839

        #4
        You're always welcome.
        Be blessed.

        Comment

        • dorinbogdan
          Recognized Expert Contributor
          • Feb 2007
          • 839

          #5
          Since the problem was solved I'll close the thread.

          Comment

          • dorinbogdan
            Recognized Expert Contributor
            • Feb 2007
            • 839

            #6
            I re-open the thread in order to allow further comments or suggestions from other members or experts, as per adim request.

            Comment

            Working...