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