aspose file tools*
The moose likes XML and Related Technologies and the fly likes [XSL] XML to XML without empty element Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Engineering » XML and Related Technologies
Bookmark "[XSL] XML to XML without empty element" Watch "[XSL] XML to XML without empty element" New topic
Author

[XSL] XML to XML without empty element

Brian Grey
Ranch Hand

Joined: Nov 15, 2002
Posts: 43
I'd like to remove all empty element from a XML file. How can I do that in XSL?
Thanks
Example
FileIN:
<?xml version="1.0" encoding="UTF-8"?>
<Data>
<Row>
<Rank>1</Rank>
<ID>142</ID>
<Name></Name>
</Row>
<Row>
<Rank>2</Rank>
<ID>200</ID>
<Name>David</Name>
</Row>
<Row>
<Rank>2</Rank>
<ID>200</ID>
<Name/>
</Row>
<Data>
FileOUT:
<?xml version="1.0" encoding="UTF-8"?>
<Data>
<Row>
<Rank>1</Rank>
<ID>142</ID>
</Row>
<Row>
<Rank>2</Rank>
<ID>200</ID>
<Name>David</Name>
</Row>
<Row>
<Rank>2</Rank>
<ID>200</ID>
</Row>
<Data>
Jayadev Pulaparty
Ranch Hand

Joined: Mar 25, 2002
Posts: 662
Here we go -
==================================================
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="*">
<xsl:choose>
<xsl:when
test="count(*|text()[string-length(normalize-space(.))>0])">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:when>
<xsl therwise/>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
=================================================
The algo is something like this. Whenever i have an element node "<xsl:template match="*">", i'm trying to see if it has children or non-empty text nodes "test="count(*|text()[string-length(normalize-space(.))>0])">". If so, i'm copying the node to the output tree "<xsl:copy>" and proceeding further down the tree "<xsl:apply-templates/>". Please remember that <xsl:copy> only copies the node and not its children or attributes. If you want to copy the attributes, you should do it yourself as the attributes are not seen as children of the elements and hence the default templates rules to walk down the tree will not pick them up. When it comes to "as to how to do this task" i guess it can be done in many ways and may be more elegantly than the above-mentioned. The solution mentioned here is just one of the working approches.
Brian Grey
Ranch Hand

Joined: Nov 15, 2002
Posts: 43
I'm going to test it right now.
Thanks
Roseanne Zhang
Ranch Hand

Joined: Nov 14, 2000
Posts: 1953
I'm trying to do what you required. However, I found that it was way more complicated task than I thought. It is because the non-empty element could become empty after you've stripped out the empty elements the first round. You need recursively apply the transformation on the result xml until no strip happened.
Another thing is of course you need to keep the text as well as attributes of the non-empty elements.
Oh, my...
Jayadev Pulaparty
Ranch Hand

Joined: Mar 25, 2002
Posts: 662
I guess the following can be looked at one of the potential solution -
================================================
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="*[count(descendant::text()[string-length(normalize-space(.))>0])>0]">
<xsl:choose>
<xsl:when test="count(*|text()[string-length(normalize-space(.))>0])">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:when>
<xsl therwise/>
</xsl:choose>
</xsl:template>
<xsl:template match="text()[string-length(normalize-space(.))>0]">
<xsl:value-of select="normalize-space(.)"/>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
=================================================
I tested it on some of the configurations as Roseanne thought of and it seems to be doing the job. One more thing is that it gives the output in normalized sort of form which doesnot have any additional carriage-returns, and empty text nodes. One more thing is that now its 12:42 A.M. and i need to go to bed
Brian Grey
Ranch Hand

Joined: Nov 15, 2002
Posts: 43
Thanks a lot !!!
Roseanne Zhang
Ranch Hand

Joined: Nov 14, 2000
Posts: 1953
With the help of Jayadev, I finally got it.
This xsl will eliminate all "absolutely empty nodes", which means no child nodes and no attributes. If you want to eliminate all "empty nodes", no matter it has attribute or not, you only need to delete the "|@*" from the count(). This is really a team work!

Thanks all!
Roseanne
[ November 24, 2002: Message edited by: Roseanne Zhang ]
Brian Grey
Ranch Hand

Joined: Nov 15, 2002
Posts: 43
I will test it tomorrow at work.
Thanks for your help
Roseanne Zhang
Ranch Hand

Joined: Nov 14, 2000
Posts: 1953
As a nth thought , my code still contains a pitfall there, if your XML has attributes, and you do want to keep empty nodes with attributes. I don't have time to fix it now. If not, it is ok.
Always need to test with the extreme cases...
[ November 25, 2002: Message edited by: Roseanne Zhang ]
Roseanne Zhang
Ranch Hand

Joined: Nov 14, 2000
Posts: 1953
Just found a little time to fix the pitfall in my above code and test it rather intensively. My guess is that Brian might not need that. However, others might need it.
See code here Q. How to eliminate all empty node from the xml source file?
Tom Stevns
Ranch Hand

Joined: Nov 20, 2001
Posts: 120
Hello to all of You

Thanx for this code snippet, its very usefull for us ATP.DK


Regards Tom Stevns, SCJP2
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: [XSL] XML to XML without empty element