如何在Ansible中获取XML元素的纯文本值(以rating为例)
如何从Ansible xml模块的输出中提取纯文本值?
问题场景
需要从以下XML内容中提取<rating>元素的纯值10:
<business type="bar"> <name>Tasty Beverage Co.</name> <beers> <beer>Rochefort 10</beer> <beer>St. Bernardus Abbot 12</beer> <beer>Schlitz</beer> </beers> <rating subjective="true">10</rating> <website> <mobilefriendly/> <address>http://tastybeverageco.com</address> </website> </business>
使用Ansible xml模块编写的代码如下:
- hosts: localhost tasks: - name: Read an element's attribute values xml: path: /tmp/test.xml xpath: /business/rating content: text register: xmlresp - name: Show an attribute value debug: var: xmlresp.matches
执行后输出为:
PLAY [localhost] ******************************************************************************************************************************************** TASK [Read an element's attribute values] ******************************************************************************************************************* ok: [localhost] TASK [Show an attribute value] ****************************************************************************************************************************** ok: [localhost] => xmlresp.matches: - rating: '10'
需求是获取纯值10,而非带键的字典结构,同时需要支持遍历多个XML文件路径列表,将提取的所有值存入一个列表。尝试用regex_replace处理未成功:
- debug: msg: "{{ xmlresp.matches | map('regex_replace', 'rating ', '') | list }}" register: op
输出结果:
TASK [debug] ************************************************************************************************************************************************ ok: [localhost] => msg: - '{u''rating'': u''10''}'
解决方案
1. 提取单个匹配的纯值
xmlresp.matches是一个列表,每个元素是包含rating键的字典,直接通过索引+键名即可提取值:
- name: 提取单个rating纯值 debug: var: xmlresp.matches.0.rating
执行后会直接输出'10'。
2. 用过滤器批量提取值(适合多匹配/循环场景)
如果需要处理多个匹配结果,或者后续要收集多个文件的值到列表,使用map结合attribute过滤器提取每个字典的rating值:
- name: 将所有rating值提取为纯值列表 set_fact: rating_list: "{{ xmlresp.matches | map(attribute='rating') | list }}"
此时rating_list的值为['10'],是纯字符串组成的列表。
3. 遍历多个XML文件的完整示例
针对遍历XML文件列表并收集所有rating值的场景,完整代码如下:
- hosts: localhost vars: # 定义要处理的XML文件路径列表 xml_files: - /tmp/test1.xml - /tmp/test2.xml - /tmp/test3.xml tasks: - name: 逐个处理XML文件提取rating xml: path: "{{ item }}" xpath: /business/rating content: text register: xml_task_results loop: "{{ xml_files }}" - name: 收集所有rating纯值到统一列表 set_fact: all_rating_values: "{{ xml_task_results.results | map(attribute='matches.0.rating') | list }}" - name: 展示最终收集的结果 debug: var: all_rating_values
执行后all_rating_values会包含所有XML文件中提取的rating纯值,比如['10', '9', '8']。
注意事项
之前使用regex_replace失败的原因是:xmlresp.matches中的元素是字典对象,不是字符串,正则替换无法直接处理字典结构,必须先提取字典对应的value值。
内容的提问来源于stack exchange,提问作者kart1657
相关产品推荐
相关产品推荐

