1

Given the following three pieces of XML:

<?xml version="1.0" encoding="utf-8"?>
<root>
    <body>
        <customerSearchRequest>
            <id>1234</id>
        </customerSearchRequest>
    </body>
</root>

<?xml version="1.0" encoding="utf-8"?>
<root>
    <BODY>
        <userSearchRequest>
            <id>5678</id>
        </userSearchRequest>
    </BODY>
</root>


<?xml version="1.0" encoding="utf-8"?>
<root>
    <Body>
        <orderSearchRequest>
            <id>9101</id>
        </orderSearchRequest>
    </Body>
</root>

I need to extract the name of the first-child of body (i.e. customerSearchRequest, userSearchRequest and orderSearchRequest), which I am currently doing as follows:

name(//SOAP-ENV:body/*[1]) 

The problem is, this only works for the first request as body is case-sensitive. How do I make the path case-insensitive?

Thanks for any pointers.

smilin_stan
  • 1,693
  • 2
  • 28
  • 40

1 Answers1

1

I would go with this :

name(//SOAP-ENV:*[translate(local-name(),'BODY','body')='body']/*[1]) 

The following part first finds elements in namespace of SOAP-ENV, and then filter to those with local-name equals 'body', case-insensitive :

//SOAP-ENV:*[translate(local-name(),'BODY','body')='body']

If you have XPath 2.0 available, it can be done in a cleaner way using lower-case(), upper-case(), or regex based functions like matches() : case-insensitive matching in xpath?

Community
  • 1
  • 1
har07
  • 88,338
  • 12
  • 84
  • 137
  • 1
    Correct answer, but also note that OP should consider pushing back to party responsible for the XML to standardize on a single case convention since `body`, `BODY`, and `Body` are really three distinct elements. – kjhughes Jun 08 '16 at 15:10
  • I'm using logstash, which uses Nokogiri, which doesn't support XPath 2 so my final solution is `local-name(//*[translate(local-name(),'BODY','body')='body']/*[1])` – smilin_stan Jun 08 '16 at 16:57