1

Please see my below groovy code which is working as expected - but wondered if there is a better way to get ancestor info?

My sample xml record:

String record = '''
<collections>
  <material>
    <books>
      <title>Italy</title>
    </books>
  </material>
  <material>
    <books>
      <title>Greece</title>
    </books>  
  </material>
  <material>
    <books>
      <author>Germany</author>
    </books>  
  </material>  
  <material>
    <cd>
      <author>France</author>
    </cd>  
  </material>  
</collections>
'''

I am wondering if there is any better way to optimise this bit of getting the ancestors ?

GPathResult extractedMaterialBlocks = extractAllMaterialBlocks(record)
String finalXml = serializeXml(extractedMaterialBlocks.parent().parent(), 'UTF-8') 
println "finalXml : ${finalXml}"

My methods:

GPathResult extractAllMaterialBlocks(String record) {
    GPathResult result = new XmlSlurper().parseText(record)
    return result ? result.'material'?.'books'?.'title'?.findAll { it }  : null
}

String serializeXml(GPathResult xmlToSerialize, String encoding) {
    def builder = new StreamingMarkupBuilder()
    builder.encoding = encoding
    builder.useDoubleQuotes = true

    return builder.bind {
        out << xmlToSerialize
    }.toString()
}

Output as expected:

<material>
    <books>
      <title>Italy</title>
    </books>
</material>
<material>
    <books>
      <title>Greece</title>
    </books>  
</material>
user292049
  • 1,138
  • 1
  • 14
  • 20
  • Do you want each `material` element separate? what you have shown is not a well-formed, right? – Rao Jun 30 '17 at 05:37
  • Yes, you are correct the above output is not well-formed, but I needed this current node block to be appended to another well-formed document tree. – user292049 Jun 30 '17 at 09:59

2 Answers2

1

You don't need to get the ancestors, if you don't dive too deep. If you want the material nodes, get those with a condition on their children instead of gettint the childs and then going up again. Your whole code can be condensed to this one line:

System.out.println new StreamingMarkupBuilder().bind { out << new XmlSlurper().parseText(record).material.findAll { it.books.title.size() } }
Vampire
  • 35,631
  • 4
  • 76
  • 102
1

Here you go, comments inline:

//Get all the collection of materials which has titles
def materials = new XmlSlurper().parseText(record).material.findAll { it.books.title.size() }
//Print each node
materials.each { println groovy.xml.XmlUtil.serialize(it) }​

Output:

<?xml version="1.0" encoding="UTF-8"?><material>
  <books>
    <title>Italy</title>
  </books>
</material>

<?xml version="1.0" encoding="UTF-8"?><material>
  <books>
    <title>Greece</title>
  </books>
</material>

You can quickly try it online Demo

EDIT: based on OP comments

def materials = new XmlSlurper().parseText(record).material.findAll { it.books.title.size() } 
​println new groovy.xml.StreamingMarkupBuilder().bind { 
   mkp.yield materials
}.toString()
Rao
  • 20,781
  • 11
  • 57
  • 77
  • 1
    That is not the output specified by OP, I used `XmlUtil` first too. – Vampire Jun 30 '17 at 10:21
  • Taken. I sought for the `well-formed` ness issue with OP and answer posted before his reply. Looks needed as string than xml. – Rao Jun 30 '17 at 10:24