Home > Software engineering >  Parsing curl response - XML returned value in Ansible
Parsing curl response - XML returned value in Ansible

Time:11-03

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 need content: 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 prefix s, like in <s:key>
  • xmlns:opensearch, a namespace with prefix opensearch, 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
  • Related