• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • paul wheaton
  • Liutauras Vilda
  • Ron McLeod
Sheriffs:
  • Jeanne Boyarsky
  • Devaka Cooray
  • Paul Clapham
Saloon Keepers:
  • Scott Selikoff
  • Tim Holloway
  • Piet Souris
  • Mikalai Zaikin
  • Frits Walraven
Bartenders:
  • Stephan van Hulst
  • Carey Brown

[XSL] XML to XML without empty element

 
Ranch Hand
Posts: 43
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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>
 
Ranch Hand
Posts: 662
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 43
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I'm going to test it right now.
Thanks
 
Ranch Hand
Posts: 1953
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 662
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 43
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks a lot !!!
 
Roseanne Zhang
Ranch Hand
Posts: 1953
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 43
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I will test it tomorrow at work.
Thanks for your help
 
Roseanne Zhang
Ranch Hand
Posts: 1953
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 1953
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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?
 
Ranch Hand
Posts: 123
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hello to all of You

Thanx for this code snippet, its very usefull for us ATP.DK
 
Politics n. Poly "many" + ticks "blood sucking insects". Tiny ad:
Gift giving made easy with the permaculture playing cards
https://coderanch.com/t/777758/Gift-giving-easy-permaculture-playing
reply
    Bookmark Topic Watch Topic
  • New Topic