如何在 ansible 中解析 URI 的 XML 响应
How to Parse the XML response of a URI in ansible
有调用应用程序网络服务的代码。
- 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>"
我想在我的下一个代码块中访问列表响应。就像我只需要 "customerId" 的值一样。如何使用 anisble
实现这一点
开箱即用的 Ansible 中没有 XML 支持。
您可以使用正则表达式过滤器在 XML 数据中进行一些简单的搜索。
在你的例子中:
- debug: msg="{{ customerId.content | regex_findall('customerId=\"(\d+)\"') }}"
将搜索 customerId=\"<number>\"
字符串和 return 引号中的数字列表。
更新:完整的示例:
- 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
.
为此值得一看 ansible-xml。它不是 Ansible 的一部分,但它是一个非常有用的解析模块 xml,它在后台使用 lxml
Python 库。
从 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
这类似于 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
我刚刚在 uri 模块中添加了 XML 解析支持,因为我也需要它。
https://github.com/ansible/ansible/pull/53045
就像JSON支持一样,它将return一个'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'
}
}
}
因为这相当复杂,所以我想我会 post 我的 Ansible - XML 用于解析 SOAP 响应的参数:
<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>
诀窍是让命名空间和 xpath 正确。另外,因为我想要我需要的实际名称 content: text
- 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
我仍然不明白为什么最后的 xpath 部分不能像 Ansible - XML docs 示例所建议的那样与 .../ns2:return/ns2:name
一起工作。上面用(简化)填充ldap_name
:
"ldap_name": {
"matches": [
{
"name": "soapui_test"
}
],
}
有调用应用程序网络服务的代码。
- 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>"
我想在我的下一个代码块中访问列表响应。就像我只需要 "customerId" 的值一样。如何使用 anisble
实现这一点开箱即用的 Ansible 中没有 XML 支持。
您可以使用正则表达式过滤器在 XML 数据中进行一些简单的搜索。
在你的例子中:
- debug: msg="{{ customerId.content | regex_findall('customerId=\"(\d+)\"') }}"
将搜索 customerId=\"<number>\"
字符串和 return 引号中的数字列表。
更新:完整的示例:
- 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
.
为此值得一看 ansible-xml。它不是 Ansible 的一部分,但它是一个非常有用的解析模块 xml,它在后台使用 lxml
Python 库。
从 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
这类似于 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
我刚刚在 uri 模块中添加了 XML 解析支持,因为我也需要它。 https://github.com/ansible/ansible/pull/53045
就像JSON支持一样,它将return一个'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'
}
}
}
因为这相当复杂,所以我想我会 post 我的 Ansible - XML 用于解析 SOAP 响应的参数:
<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>
诀窍是让命名空间和 xpath 正确。另外,因为我想要我需要的实际名称 content: text
- 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
我仍然不明白为什么最后的 xpath 部分不能像 Ansible - XML docs 示例所建议的那样与 .../ns2:return/ns2:name
一起工作。上面用(简化)填充ldap_name
:
"ldap_name": {
"matches": [
{
"name": "soapui_test"
}
],
}