Home > Back-end >  Parsing curl response in xml format with xmllint
Parsing curl response in xml format with xmllint

Time:02-17

I am trying to parse the curl response in xml format to retrieve value of 'version'. I am using below command:

curl -v -k -X GET -u username:password -H "Content-Type: application/xml" -H "Accept: application/xml" http://dev_server_host:8080/rest/process/list/template?process=notification_process | xmllint  --xpath "//proc:version" -

PFB, sample response of this curl command when I don't use xmllint.

<proc:basicProcessTemplate  xmlns:proc="http://www.example.com/bx/2009/management/processManagerType">
    <proc:processQName>
        <proc:moduleName>some_awesome_notification_module</proc:moduleName>
        <proc:processName>notification_process</proc:processName>
        <proc:version>1.0.0.20220215185833172</proc:version>
    </proc:processQName>
    <proc:description>sample process to send notifications</proc:description>
</proc:basicProcessTemplate>

However, when I use xmllint as mentioned above, below error is shown in terminal:

XPath error : Undefined namespace prefix
xmlXPathEval: evaluation failed
XPath evaluation failure

Can you please help to identify correct xpath which I can send in xmllint command to retrieve value of 'version'.

Please Note: As I am using query parameter 'process', only one 'proc:processQName' element will be returned in response. Array is not expected in response for 'proc:processQName' element.

CodePudding user response:

The namespace is used but not defined in the node you are looking for.

Therefore you have to modify your query to check the node's name and namespace separately:

xmllint --xpath '//*[
  namespace-uri() = "http://www.example.com/bx/2009/management/processManagerType"
  and local-name() = "version"
]/text()'
1.0.0.20220215185833172

If the namespace is defined in a parent node (as it is the case in your root node), you can simplify the query by checking by reference:

xmllint --xpath '//*[
  namespace-uri() = namespace-uri(/*) and local-name() = "version"
]/text()'
1.0.0.20220215185833172

If your query doesn't rely on the specific namespace, you can also omit that part entirely and select nodes with any namespace (matching the name, though):

xmllint --xpath '//*[local-name() = "version"]/text()'
1.0.0.20220215185833172

You might also be interested in using another, less pedantic tool instead:

With XMLStarlet you can essentially use your original query string:

xmlstarlet sel -t -v "//proc:version"
1.0.0.20220215185833172

With xq, querying is a little bit different because under the hood it is actually running a jq query:

xq -r '.. | ."proc:version"? // empty'
1.0.0.20220215185833172
  • Related