I am new to XML and trying to parse the output of a API request for Splunk - here is the data output by the request:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xml" href="/static/atom.xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:s="http://dev.splunk.com/ns/rest" xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/">
<generator build="87e2dda940d1" version="8.2.4"/>
<opensearch:totalResults>1</opensearch:totalResults>
<entry>
<link href="/services/kvstore/status/status" rel="list"/>
<content type="text/xml">
<s:dict>
<s:key name="current">
<s:dict>
<s:key name="backupRestoreStatus">Ready</s:key>
<s:key name="date">Tue Nov 1 13:07:35 2022</s:key>
<s:key name="dateSec">1667326055.814</s:key>
<s:key name="disabled">0</s:key>
</s:dict>
</s:key>
</s:dict>
</content>
</entry>
</feed>
I am trying to drill down to the following line:
<s:key name="backupRestoreStatus">Ready</s:key>
and get the value of this and assign it to a variable.
So far I can run the curl command and get the output assigned to a variable. I have attempted to parse the data and received errors with no output to receiving a copy of the full output - but NO parsed information.
Here is the ansible code i have to try to parse for the requested data:
- name: Parse xml for Back-up Status
community.general.xml:
path: "{{ xml_status }}"
xpath: /feed/entry/content/key[@name=backupRestoreStatus]
attribute: value
content: attribute
register: backup_stat
The current error I am getting is as follows:
TASK [Parse xml for Back-up Status] *****************************
fatal: [dc1-splunk]: FAILED! => {"changed": false, "msg": "missing parameter(s) required by 'attribute': value"}
CodePudding user response:
You do have several issues here, upon which:
- a wrong usage of
content: attribute
, while what you want is the content of the node, not of one of one if its attributes, so you needcontent: text
- the usage of
attribute: value
, that is needed to target an attribute value to modify, while your goal is just to get some content - some missing nodes in your XPath, that should actually be
/ns:feed/ns:entry/ns:content /s:dict/s:key[@name='current'] /s:dict/s:key[@name='backupRestoreStatus']
- but, maybe the more important, and the one that is probably the more obscure, is the fact that you forgot about XML namespaces
So, about XML namespaces, you have to know that, when an XML includes namespaces definition, you have to address the nodes with their respective namespaces.
Here, your namespaces are defined on the feed
node:
<feed
xmlns="http://www.w3.org/2005/Atom"
xmlns:s="http://dev.splunk.com/ns/rest"
xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/"
>
This node actually defines three namespaces:
xmlns
, the default namespace, which applies to any node not having a prefix, like<feed>
,<entry>
or<content>
xmlns:s
, a namespace with prefixs
, like in<s:key>
xmlns:opensearch
, a namespace with prefixopensearch
, like in<opensearch:totalResults>
— which you can leave aside, since you do not have that namespace prefix in the XPath you are looking to query
And for Ansible to query your XML properly, you have to instruct it what are the namespaces, with the help of the namespaces
parameter.
So, given the two tasks:
- community.general.xml:
path: file.xml
xpath: >-
/ns:feed/ns:entry/ns:content
/s:dict/s:key[@name='current']
/s:dict/s:key[@name='backupRestoreStatus']
content: text
namespaces:
ns: http://www.w3.org/2005/Atom
s: http://dev.splunk.com/ns/rest
register: backup_stat
- set_fact:
backup_restore_status: >-
{{ backup_stat.matches.0['{http://dev.splunk.com/ns/rest}key'] }}
You will end up getting:
backup_restore_status: Ready