xmlgroovyxmlslurpergpath

Groovy Get value of an XML attribute with GPath Slurper


Need to parse an XML document that contains attributes within a header context.

<?xml version="1.0" encoding="UTF-8"?>
<S38:manageRequest xmlns:S38="http://ns.com/S38" xmlns:header="http://ns.com/header/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://ns.com/xsd/ManageItem XSD\ManageItem.xsd">
    <header:standardHeader>
        <header:serviceAddressing>
            <header:to>
                <header:address>http://ns.com/BLAHBLAH</header:address>
                <header:contextItemList>
                    <header:contextItem contextName="Channel" contextId="http://ns.com/contextItem">I Need This</header:contextItem>
                    <header:contextItem contextName="Box" contextId="http://ns.com/contextItem">Blue</header:contextItem>
                </header:contextItemList>
            </header:to>
        </header:serviceAddressing>
    </header:standardHeader>
</S38:manageRequest>

I want to get the attribute "Channel" value of "I Need This" using groovy.util.slurpersupport.GPathResult.

I have found a way that works, but I don't believe it's correct as I am picking the contextItem and luckily the first one is the one I am interested in:

private Map parseServiceAddressing(GPathResult message,Map values){ 
def serviceAddressingList=message."standardHeader"."serviceAddressing"."to"."contextItemList";
    if(serviceAddressingList.isEmpty()){ 
    throw new sourceException("serviceAddressing list is missing",values);
}

def contextItem=serviceAddressingList.'*'.find{
    it.name()=='contextItem'
    };

values.put(tag.CHANNEL, contextItem);

return values;

All attempts to use Channel as the location text fails to retrieve a value. Unfortunately I'm tied to using the GPath as it part of a very large Groovy script I have been asked to modify which does a lot of other stuff.

Can someone please tell me what the correct way of achieving this?


Solution

  • You should find it using element name and elements attribute is matching the request value as shown below:

    def xmlString = """<?xml version="1.0" encoding="UTF-8"?>
    <S38:manageRequest xmlns:S38="http://ns.com/S38" xmlns:header="http://ns.com/header/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://ns.com/xsd/ManageItem XSD/ManageItem.xsd">
        <header:standardHeader>
            <header:serviceAddressing>
                <header:to>
                    <header:address>http://ns.com/BLAHBLAH</header:address>
                    <header:contextItemList>
                        <header:contextItem contextName="Channel" contextId="http://ns.com/contextItem">I Need This</header:contextItem>
                        <header:contextItem contextName="Box" contextId="http://ns.com/contextItem">Blue</header:contextItem>
                    </header:contextItemList>
                </header:to>
            </header:serviceAddressing>
        </header:standardHeader>
    </S38:manageRequest>"""
    
    
    def xml = new XmlSlurper().parseText(xmlString)
    def cItemChannel = xml.'**'.find {it.name() == 'contextItem' && it.@contextName == 'Channel'}?.text()
    println cItemChannel
    

    You can quickly try it online demo