xmlgroovygpath

How to obtain Attribute Values of an XML with XMLPath?


I have an XMLPath Object, and I wish to take the attribute names for some nodes. For Example,

<?xml version="1.0" encoding="UTF-8"?>
<md:EntityDescriptor entityID="https://scspr0269974001.c4.com/saml/metadata" ID="https___scspr0269974001.c2_saml_metadata" xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata">
  <md:SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol" WantAssertionsSigned="true" AuthnRequestsSigned="true">
    <md:SingleLogoutService Location="https://scspr0269974001.company2.com/saml/SingleLogout" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"/>
       <md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</md:NameIDFormat>
       <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</md:NameIDFormat>
       <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat>
       <md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</md:NameIDFormat>
       <md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName</md:NameIDFormat>
       <md:AssertionConsumerService Location="https://scspr0269974001.company1.com/saml/SSO" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" isDefault="true" index="0"/>
    <md:AssertionConsumerService Location="https://scspr0269974001.company2.com/saml/SSO" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" index="1"/>
  </md:SPSSODescriptor>
</md:EntityDescriptor>

For this XML, what is the XMLPath expression to obtain the attribute Location of the md:SingleLogoutService?

I can get the entityID of the md:EntityDescriptor with the following: entityId=metadataXml.get("md:EntityDescriptor.@entityID")

But for the Location attribute, which I'm trying to get like

logoutURL=metadataXml.get("'md:EntityDescriptor'.'md:SPSSODescriptor'.'md:SingleLogoutService'.@Location")

And output I get is [] and nothing else.


Solution

  • Here you go, comments inline:

    def xml = """<?xml version="1.0" encoding="UTF-8"?>
    <md:EntityDescriptor entityID="https://scspr0269974001.c4.com/saml/metadata" ID="https___scspr0269974001.c2_saml_metadata" xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata">
      <md:SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol" WantAssertionsSigned="true" AuthnRequestsSigned="true">
        <md:SingleLogoutService Location="https://scspr0269974001.company2.com/saml/SingleLogout" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"/>
           <md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</md:NameIDFormat>
           <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</md:NameIDFormat>
           <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat>
           <md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</md:NameIDFormat>
           <md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName</md:NameIDFormat>
           <md:AssertionConsumerService Location="https://scspr0269974001.company1.com/saml/SSO" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" isDefault="true" index="0"/>
        <md:AssertionConsumerService Location="https://scspr0269974001.company2.com/saml/SSO" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" index="1"/>
      </md:SPSSODescriptor>
    </md:EntityDescriptor>"""
    //Parse the xml with XmlSlurper
    def pxml = new XmlSlurper().parseText(xml)
    //Extract the required attribute and print
    println pxml.'**'.find{it.name() == 'SingleLogoutService'}.@Location.text()
    //alternative to above line is that you can use below statement as well; both yield same result
    println pxml.SPSSODescriptor.SingleLogoutService.@Location.text()
    

    You an try it quickly online Demo