xmlgroovymarkupbuilder

Omit empty elements with groovy StreamingMarkupBuilder


Groovy's MarkupBuilder has an omitNullAttributes and an omitEmptyAttributes. But StreamingMarkupBuilder doesn't.
I have tag like that one <foo />

Could I omit them from final output?

P.S. Could I somehow use a trick from the post Omit empty attributes with groovy DOMBuilder ?

UPDATE: Example of XML

<A>
<Header><ID>1234</ID></Header>
<Body>
<item>
<id>001</id>
<foo />
</item>
</Body>
</A>

Solution

  • Right, so from the comments, it looks like you are trying to strip empty elements, not empty attributes...

    If you want to strip empty nodes from xml, you would need to read it in, find the empty ones, remove them, then write it back out...

    Like this example:

    def xml = new StringWriter().with { sw ->
      new groovy.xml.MarkupBuilder( sw ).with { mb ->
        a {
          b( 'tim' )
          foo()
        }
        sw.toString()
      }
    }
    
    def parser = new XmlParser().parseText( xml )
    
    def emptykids = parser.depthFirst().findAll { it.children().size() == 0 }
    
    emptykids.each {
      parser.remove( it )
    }
    
    new XmlNodePrinter().print( parser )
    

    However, if you want to not add empty elements to your XML when using StreamingMarkupBuilder, there is no way I know of of doing this. I guess you could re-implement the class itself to handle this, but other than that, you're stuck...

    It should be said however that neither of the two attributes you point out in the question will make MarkupBuilder do this either. It will stop adding empty attributes, but it will add empty elements

    Now we have an example to work to:

    Try this:

    def xml = '''|<A>
                 |<Header><ID>1234</ID></Header>
                 |<Body>
                 |<item>
                 |<id>001</id>
                 |<foo />
                 |</item>
                 |</Body>
                 |</A>'''.stripMargin()
    
    def parser = new XmlParser().parseText( xml )
    
    parser.depthFirst().each { 
      if( it.children().size() == 0 ) {
        it.parent().remove( it )
      }
    }
    
    new XmlNodePrinter().print( parser )