在 Ansible 剧本中使用 parse_xml
Using parse_xml in an Ansible playbook
我一直在尝试在 Ansible 中解析 XML 数据。我可以使用 xml 模块让它工作,但我认为使用 parse_xml 更适合我的需要。
我似乎无法将 xml 中的任何数据与我的规格文件相匹配。
这是 xml 数据:
<data xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">
<ntp xmlns=\"http://cisco.com/ns/yang/Cisco-IOS-XR-ip-ntp-oper\">
<nodes>
<node>
<node>0/0/CPU0</node>
<associations>
<is-ntp-enabled>true</is-ntp-enabled>
<sys-leap>ntp-leap-no-warning</sys-leap>
<peer-summary-info>
<peer-info-common>
<host-mode>ntp-mode-client</host-mode>
<is-configured>true</is-configured>
<address>10.1.1.1</address>
<reachability>0</reachability>
</peer-info-common>
<time-since>-1</time-since>
</peer-summary-info>
<peer-summary-info>
<peer-info-common>
<host-mode>ntp-mode-client</host-mode>
<is-configured>true</is-configured>
<address>172.16.252.29</address>
<reachability>255</reachability>
</peer-info-common>
<time-since>991</time-since>
</peer-summary-info>
</associations>
</node>
</nodes>
</ntp>
</data>
规范文件如下所示:
---
vars:
ntp_peers:
address: "{{ item.address }}"
reachability: "{{ item.reachability}}"
keys:
result:
value: "{{ ntp_peers }}"
top: data/ntp/nodes/node/associations
items:
address: peer-summary-info/peer-info-common/address
reachability: peer-summary-info/peer-info-common/reachability
和 yaml 文件中的任务:
- name: parse ntp reply
set_fact:
parsed_ntp_data: "{{ NTP_STATUS.stdout | parse_xml('specs/iosxr_ntp.yaml') }}"
但数据没有return任何结果:
TASK [debug parsed_ntp_data] **************************************************************************************************************************************************************************
ok: [core-rtr01] => {
"parsed_ntp_data": {
"result": []
}
}
ok: [dist-rtr01] => {
"parsed_ntp_data": {
"result": []
}
}
我以前从未见过parse_xml
,所以这是一次有趣的冒险
似乎有两件事对您不利:top:
密钥是从根元素 计算的 ,以及您的 XML(与其他元素不同示例)使用 XML 命名空间(xmlns=
位),这意味着您的 XPath 必须以 Element.findall
方式编码
对于第一部分,由于 Element.findall
在 <data>
元素上是 运行,这意味着不能在 XPath 中引用 data/...
,因为那将是适用于结构 <data><data>
。我试图通过使 XPath 绝对 /data/...
来偷偷摸摸,但是 Python 的 XPath 库在那种情况下抛出。所以,至少你的 top:
键不能以 data
任何东西开头
然后,你的代码片段中的 xmlns=
对我来说很突出,因为这意味着这些元素的名称实际上是每个元素的 NS+":"+localName
,因此 ntp
的 XPath 不匹配ns0:ntp
因为它们被认为是完全独立的名称(毕竟这是命名空间的重点)。很可能使用足够的 //*[localname() = "ntp"]
愚蠢来避免必须一遍又一遍地指定名称空间,但我没有尝试
同样,作为对 Python 的 XPath 库的让步,他们将 xpath 中的完全限定名称编码为 {the-namespace}local-name
并且除了修改 network.py
传递命名空间:-(
因此,我用来证实我的理论的“hello world”版本:
vars:
ntp_peers:
address: "{{ item.address }}"
keys:
result:
value: "{{ ntp_peers }}"
top: '{http://cisco.com/ns/yang/Cisco-IOS-XR-ip-ntp-oper}ntp/{http://cisco.com/ns/yang/Cisco-IOS-XR-ip-ntp-oper}nodes/{http://cisco.com/ns/yang/Cisco-IOS-XR-ip-ntp-oper}node'
items:
address: '{http://cisco.com/ns/yang/Cisco-IOS-XR-ip-ntp-oper}node'
开开心心制作
ok: [localhost] => {
"msg": {
"result": [
{
"address": "0/0/CPU0"
}
]
}
}
我一直在尝试在 Ansible 中解析 XML 数据。我可以使用 xml 模块让它工作,但我认为使用 parse_xml 更适合我的需要。
我似乎无法将 xml 中的任何数据与我的规格文件相匹配。
这是 xml 数据:
<data xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">
<ntp xmlns=\"http://cisco.com/ns/yang/Cisco-IOS-XR-ip-ntp-oper\">
<nodes>
<node>
<node>0/0/CPU0</node>
<associations>
<is-ntp-enabled>true</is-ntp-enabled>
<sys-leap>ntp-leap-no-warning</sys-leap>
<peer-summary-info>
<peer-info-common>
<host-mode>ntp-mode-client</host-mode>
<is-configured>true</is-configured>
<address>10.1.1.1</address>
<reachability>0</reachability>
</peer-info-common>
<time-since>-1</time-since>
</peer-summary-info>
<peer-summary-info>
<peer-info-common>
<host-mode>ntp-mode-client</host-mode>
<is-configured>true</is-configured>
<address>172.16.252.29</address>
<reachability>255</reachability>
</peer-info-common>
<time-since>991</time-since>
</peer-summary-info>
</associations>
</node>
</nodes>
</ntp>
</data>
规范文件如下所示:
---
vars:
ntp_peers:
address: "{{ item.address }}"
reachability: "{{ item.reachability}}"
keys:
result:
value: "{{ ntp_peers }}"
top: data/ntp/nodes/node/associations
items:
address: peer-summary-info/peer-info-common/address
reachability: peer-summary-info/peer-info-common/reachability
和 yaml 文件中的任务:
- name: parse ntp reply
set_fact:
parsed_ntp_data: "{{ NTP_STATUS.stdout | parse_xml('specs/iosxr_ntp.yaml') }}"
但数据没有return任何结果:
TASK [debug parsed_ntp_data] **************************************************************************************************************************************************************************
ok: [core-rtr01] => {
"parsed_ntp_data": {
"result": []
}
}
ok: [dist-rtr01] => {
"parsed_ntp_data": {
"result": []
}
}
我以前从未见过parse_xml
,所以这是一次有趣的冒险
似乎有两件事对您不利:top:
密钥是从根元素 计算的 ,以及您的 XML(与其他元素不同示例)使用 XML 命名空间(xmlns=
位),这意味着您的 XPath 必须以 Element.findall
方式编码
对于第一部分,由于 Element.findall
在 <data>
元素上是 运行,这意味着不能在 XPath 中引用 data/...
,因为那将是适用于结构 <data><data>
。我试图通过使 XPath 绝对 /data/...
来偷偷摸摸,但是 Python 的 XPath 库在那种情况下抛出。所以,至少你的 top:
键不能以 data
任何东西开头
然后,你的代码片段中的 xmlns=
对我来说很突出,因为这意味着这些元素的名称实际上是每个元素的 NS+":"+localName
,因此 ntp
的 XPath 不匹配ns0:ntp
因为它们被认为是完全独立的名称(毕竟这是命名空间的重点)。很可能使用足够的 //*[localname() = "ntp"]
愚蠢来避免必须一遍又一遍地指定名称空间,但我没有尝试
同样,作为对 Python 的 XPath 库的让步,他们将 xpath 中的完全限定名称编码为 {the-namespace}local-name
并且除了修改 network.py
传递命名空间:-(
因此,我用来证实我的理论的“hello world”版本:
vars:
ntp_peers:
address: "{{ item.address }}"
keys:
result:
value: "{{ ntp_peers }}"
top: '{http://cisco.com/ns/yang/Cisco-IOS-XR-ip-ntp-oper}ntp/{http://cisco.com/ns/yang/Cisco-IOS-XR-ip-ntp-oper}nodes/{http://cisco.com/ns/yang/Cisco-IOS-XR-ip-ntp-oper}node'
items:
address: '{http://cisco.com/ns/yang/Cisco-IOS-XR-ip-ntp-oper}node'
开开心心制作
ok: [localhost] => {
"msg": {
"result": [
{
"address": "0/0/CPU0"
}
]
}
}