如何在ansible中解析URI的XML响应

时间:2016-09-23 10:11:35

标签: ansible ansible-playbook

有一个代码可以调用应用程序的Web服务。

 - uri:
         url: http://10.164.52.61:8080/ems/v74/ws/customer.ws?customerRefId=f4XXXb15d69c3
         method: GET
         content_as_json: true
         password: admin
         user: admin
         validate_certs: no
         return_content: yes
         HEADER_Cookie: "{{login.set_cookie}}"
        register: customerId

      - debug:
          var: customerId.content

样本回复是

"customerId.content": "<listResponse type=\"customer\" count=\"1\"><instance customerId=\"28\" name=\"abc\" customerRefId=\"xyz\" refId1=\"12\" type=\"org\" enabled=\"true\" phone=\"\" fax=\"\" billingZip=\"\" billingAddress=\"\" billingCity=\"\" billingCountry=\"\" billingState=\"\" vendor=\"1\" defaultEmail=\"test\" defaultContactName=\"test\"/></listResponse>"

我想在下一段代码中访问列表响应。就像我只需要&#34; customerId&#34;的价值。如何使用anisble

实现这一目标

6 个答案:

答案 0 :(得分:2)

Ansible中没有XML支持。开箱即用 您可以使用正则表达式过滤器在XML数据中进行一些简单的搜索 在您的示例中:

- debug: msg="{{ customerId.content | regex_findall('customerId=\"(\d+)\"') }}"

将搜索customerId=\"<number>\"字符串并返回引号中的数字列表。

更新:完整的工作示例:

- hosts: localhost
  gather_facts: no
  vars:
    myvar: "<listResponse type=\"customer\" count=\"1\"><instance customerId=\"28\" name=\"abc\" customerRefId=\"xyz\" refId1=\"12\" type=\"org\" enabled=\"true\" phone=\"\" fax=\"\" billingZip=\"\" billingAddress=\"\" billingCity=\"\" billingCountry=\"\" billingState=\"\" vendor=\"1\" defaultEmail=\"test\" defaultContactName=\"test\"/></listResponse>"
  tasks:
    - debug: msg="{{ myvar | regex_findall('customerId=\"(\d+)\"') }}"

我使用ansible 2.1.1.0

答案 1 :(得分:2)

这与sebaszw的答案类似,但是不需要将xml响应写入文件,而是将其存储在变量中。

- uri:
    url: http://10.164.52.61:8080/ems/v74/ws/customer.ws?customerRefId=f4XXXb15d69c3
    method: GET
    content_as_json: true
    password: admin
    user: admin
    validate_certs: no
    return_content: yes
    HEADER_Cookie: "{{login.set_cookie}}"
  register: customerId

- xml:
    xmlstring: "{{customerId.content}}"
    xpath: /listResponse/instance
    content: attribute
  register: instance_attributes

- debug:
    var: instance_attributes.matches.0.instance.customerId 

答案 2 :(得分:1)

从Ansible 2.4你可以这样做:

- get_url:
    url: http://10.164.52.61:8080/ems/v74/ws/customer.ws?customerRefId=f4XXXb15d69c3
    dest: ./response.xml
    url_password: admin
    url_user: admin
    validate_certs: no
    headers:
      Cookie: "{{login.set_cookie}}"

- xml:
    path: ./response.xml
    xpath: /listResponse/instance
    content: attribute
  register: instance_attributes

- debug:
    var: instance_attributes.matches.0.instance.customerId

答案 3 :(得分:0)

值得关注ansible-xml。它不是Ansible的一部分,但它是一个非常有用的解析xml的模块,它使用了lxml Python库。

答案 4 :(得分:0)

我刚刚在uri模块中添加了XML解析支持,因为我也需要它。 https://github.com/ansible/ansible/pull/53045

就像JSON支持一样,它将返回带有包含XML内容的字典的'xml'键,以方便访问有效负载中的数据。

您的示例如下所示:

 - uri:
     url: http://10.164.52.61:8080/ems/v74/ws/customer.ws?customerRefId=f4XXXb15d69c3
     method: GET
     password: admin
     user: admin
     validate_certs: no
     HEADER_Cookie: "{{login.set_cookie}}"
    register: customerId

  - debug:
      var: customerId.xml.listResponse.instance['@customerId']

customerId.xml的输出为:

{
    'listResponse': {
        '@type': 'customer',
        '@count', '1',
        'instance': {
            '@customerId': '28',
            '@name': 'abc'
            '@customerRefId': 'xyz',
            '@refId1': '12',
            '@type': 'org',
            '@enabled': 'true',
            '@phone': '',
            '@fax': '',
            '@billingZip': '',
            '@billingAddress': '',
            '@billingCity': '',
            '@billingCountry': '',
            '@billingState': '',
            '@vendor': '1',
            '@defaultEmail': 'test',
            '@defaultContactName': 'test'
        }
    }
}

答案 5 :(得分:0)

因为要使其正常工作这是相当复杂的,所以我认为我应该发布Ansible-XML参数来解析SOAP响应:

describe_security_groups

诀窍是正确命名空间和xpath。另外,由于我需要真实的名字,所以我需要<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Header/> <S:Body xmlns:ns2="http://ws.coverity.com/v9"> <ns2:getLdapServerDomainsResponse> <return> <name>soapui_test</name> </return> </ns2:getLdapServerDomainsResponse> </S:Body> </S:Envelope>

content: text

我仍然不明白为什么最后的xpath节不能与Ansible - XML docs示例所暗示的- name: Extract the name from the SOAP xml: xmlstring: "{{ ldap_response.content }}" xpath: "/S:Envelope/S:Body/ns2:getLdapServerDomainsResponse/return/name" namespaces: S: "http://schemas.xmlsoap.org/soap/envelope/" SOAP-ENV: "http://schemas.xmlsoap.org/soap/envelope/" ns2: "http://ws.coverity.com/v9" content: text register: ldap_name 一起使用。上面的.../ns2:return/ns2:name用(简体)填充:

ldap_name