3

Trying to remove xml nodes using groovy. Here want to remove requiredByDate element, which is present multiple times and has namcespace with a prefix.

Looked at many examples available on the net, and stackover as well. Some of them are close. If there is no namespace for that xml element, then getting the desired output.


Problem is that the xml element has namespace and not able to achieve the intended out.

Here is the groovy script that I am trying:

import groovy.xml.*
def x='''<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:com="http://www.example/test/commontypes" xmlns:ord="http://www.example/test/orderservice" xmlns:ord1="http://www.example/test/order">
   <soapenv:Header/>
   <soapenv:Body>
         <ord:orderRequest>
            <ord1:orderRef>${#TestCase#ORDERREF}</ord1:orderRef>
            <ord1:header>
               <ord1:description>user test</ord1:description>
               <ord1:customerID></ord1:customerID>
               <ord1:requiredByDate>2010-02-02T12:00:00-07:00</ord1:requiredByDate>               
            </ord1:header>
            <ord1:line>
               <ord1:lineNumber>1</ord1:lineNumber>
               <ord1:actionMode>mode1</ord1:actionMode>
               <ord1:requiredByDate>2010-02-02T12:00:00-07:00</ord1:requiredByDate>
            </ord1:line>
            <ord1:line>
               <ord1:lineNumber>2</ord1:lineNumber>
               <ord1:action>userAction</ord1:action>
               <ord1:requiredByDate>2010-02-02T12:00:00-07:00</ord1:requiredByDate>
            </ord1:line>
         </ord:orderRequest>
   </soapenv:Body>
</soapenv:Envelope>'''
def xml=new XmlParser().parseText(x)
def nodes = xml.'**'.findAll{ it.name() == 'requiredByDate' }
nodes.each{it.parent().remove(it)}
XmlUtil.serialize(xml).toString()

The output comes the same as input i.e., does not remove requiredByDate elements(present 3 times in the xml)

If I hard code with namespace i.e., 'ord1:requiredByDate', then desired output comes. Referring xml.'**'.findAll{ it.name() == 'ord1:requiredByDate' } here.

However, I do not know what prefix comes in the xml during runtime. Hence, cannot use the hardcoded prefix in findAll above.

Rao
  • 20,781
  • 11
  • 57
  • 77

1 Answers1

2

A node with a namespace return a QName for his name() method. You can access the "local" name of the node, without the namespace, with the method QName.getLocalPart()

Try this:

def nodes = xml.'**'.findAll{ it.name().localPart == 'requiredByDate' }

See QName

Or the javadoc for Node:

Typically the name is a String and a value is either a String or a List of other Nodes, though the types are extensible to provide a flexible structure, e.g. you could use a QName as the name which includes a namespace URI and a local name.

Jérémie B
  • 10,611
  • 1
  • 26
  • 43