Sambit Swain
Sambit Swain

Reputation: 141

Groovy - xpath to filter XML payload by attribute

I have a groovy code which accepts xpath expression and find the value of nodes (both XML and JSON), but I am not able to filter by attributes. Below is my code, please can I get some help?

def message = '''
<payload>
    <division name="DivisionCodes">
        <param name="DivisionCode">FFM-VKM</string>
        <param name="DivisionGroupCode">FFM</string>
        <param name="DivisionCountryCode">DE</string>
    </division>
</payload>
'''
def xpathEx='*/param[@name="DivisionCountryCode"]'
def result = ''
if(xpathEx) {
    def gPaths = xpathEx?.split(",") as LinkedList
    def extractedData=[:]
    gPaths.eachWithIndex { String entry, int idx ->
        def inputData = ''
        def headerKey = ''
        def path = entry?.replace('/', '.')?.replace(':','')?.split('\\.') as LinkedList
        if (path) {
            if (message.trim().charAt(0) == '<') {
                inputData = new XmlSlurper().parseText(message)
            }
            path.forEach({ inputData = inputData."${it}" })
        }
        extractedData.put(path.getLast().toString(),inputData)
    }
    if(extractedData.isEmpty()) {
        result = ' '
    } else {
        result = ', XPath reference: '+extractedData?.toMapString()
    }                   
}
println result

I am interested to get the value of param child node where attribute is "DivisionGroupCode". My xpath expression is only able to filter by child node.

What should be the correct xpathEx? OR What should correct groovy code which can take xpathEx as parameter and process on any XML payload

Upvotes: 0

Views: 1343

Answers (2)

Sambit Swain
Sambit Swain

Reputation: 141

import groovy.json.JsonSlurper

def result = ''
def message = '''
<payload>
    <division name="DivisionCodes">
        <param name="DivisionCode">FFM-VKM</param>
        <param name="DivisionGroupCode">FFM</param>
        <param name="DivisionCountryCode">DE</param>
    </division>
    <division value="SectorCodes">
        <param value="SectorCode">SEC-LOC-23</param>
        <param value="SectorGroupCode">DUK-001002</param>
        <param value="SectorCountryCode">PH</param>
    </division>
</payload>
'''
def xpathEx='*@name="DivisionCode",*@value="SectorCode",*@name="DivisionCountryCode",*@value="SectorCountryCode"'

if(xpathEx) {
    def gPaths = xpathEx?.split(",") as LinkedList
    def extractedData=[:]
    gPaths.eachWithIndex { String entry, int idx ->
        def inputData = ''
        def path = entry?.replace('/', '.')?.replace('@', '.@')?.replace(':','')?.split('\\.') as LinkedList
        if (path) {
            if (message.trim().charAt(0) == '<') {
                inputData = new XmlSlurper().parseText(message)
            } else if (message.trim().charAt(0) == '{') {
                inputData = new JsonSlurper().parseText(message)
            }
            path.forEach({ 
                if ("${it}".contains("=")) {
                    def attName = "${it}".substring(1, "${it}".indexOf("="))
                    def attValue = "${it}".substring("${it}".indexOf("=") + 2, "${it}".length() - 1)
                    inputData = inputData.depthFirst().find {arg -> if (arg.attributes().get(attName) == attValue) { arg } }
                } else {
                    inputData = inputData."${it}" 
                }
            })
        }
        extractedData.put(path.getLast().toString(),inputData)
    }
    if(extractedData.isEmpty()) {
        result = ' '
    } else {
        result = ', XPath reference: '+extractedData?.toMapString()
    }                   
}
println result

Upvotes: 0

ou_ryperd
ou_ryperd

Reputation: 2133

If yourt only requirement is like you stated: "I am interested to get the value of param child node where attribute is 'DivisionGroupCode'", then this will work. However, your XML is not valid, the closing tags: </string> should be </param>.

def message = '''
<payload>
    <division name="DivisionCodes">
        <param name="DivisionCode">FFM-VKM</param>
        <param name="DivisionGroupCode">FFM</param>
        <param name="DivisionCountryCode">DE</param>
    </division>
</payload>
'''

def payload = new XmlSlurper().parseText(message)

def name = payload.depthFirst().find { param ->
    param.@name == 'DivisionGroupCode'
}

println name

Upvotes: 0

Related Questions