Синтаксический анализ сложного XML с использованием Ansible

#xml #ansible

#xml #ansible

Вопрос:

Я пытаюсь проанализировать вывод XML с помощью скрипта powershell, который мне нужно проанализировать следующим образом, и за который я борюсь уже несколько недель. Пожалуйста, кто-нибудь, помогите мне. xyz.yml, который выводит XML

 ---
- hosts: win
  tasks:
    - name: Run the SPLAT PS with args
      win_command: powershell.exe D:xyz.ps1 
      args:
        chdir: D:
      register: splat
    - debug:
        var: splat.stdout_lines
  

XML, который возвращается с помощью this, выглядит следующим образом:

     ok: [198.175.95.23] => {
    "splat.stdout_lines": [
        "<?xml version="1.0" encoding="utf-8" standalone="yes"?>",
        "<HostDiscovery>",
        "  <Host>",
        "    <MacAddress>33:77:90:88</MacAddress>",
        "    <DevicesPolled>78</DevicesPolled>",
        "    <ElapsedSearchTime>5.4112303</ElapsedSearchTime>",
        "    <ElapsedLookupTime>0.4844849</ElapsedLookupTime>",
        "    <Connection>",
        "      <NetworkDevice>",
        "        <MacAddress>33:77:90:88</MacAddress>",
        "        <DeviceName>sdd</DeviceName>",
        "        <Interface>Te1/1/1</Interface>",
        "        <IfType>6</IfType>",
        "        <AddressCount>189</AddressCount>",
        "        <Uplink>true</Uplink>",
        "        <Seen>true</Seen>",
        "        <Candidate>false</Candidate>",
        "      </NetworkDevice>",
        "      <NetworkDevice>",
        "        <MacAddress>33:77:90:88</MacAddress>",
        "        <DeviceName>kscjdsc</DeviceName>",
        "        <Interface>Gi6/36</Interface>",
        "        <IfType>6</IfType>",
        "        <AddressCount>8</AddressCount>",
        "        <Uplink>false</Uplink>",
        "        <Seen>true</Seen>",
        "        <Candidate>true</Candidate>",
        "      </NetworkDevice>",
        "      <NetworkDevice>",
        "        <MacAddress>33:77:90:88</MacAddress>",
        "        <DeviceName>ksxsk</DeviceName>",
        "        <Interface>Te1/1</Interface>",
        "        <IfType>6</IfType>",
        "        <AddressCount>327</AddressCount>",
        "        <Uplink>true</Uplink>",
        "        <Seen>true</Seen>",
        "        <Candidate>false</Candidate>",
        "      </NetworkDevice>",
        "      <NetworkDevice>",
        "        <MacAddress>33:77:90:88</MacAddress>",
        "        <DeviceName>fvfv</DeviceName>",
        "        <Interface>Gi1/0</Interface>",
        "        <IfType>6</IfType>",
        "        <AddressCount>176</AddressCount>",
        "        <Uplink>true</Uplink>",
        "        <Seen>true</Seen>",
        "        <Candidate>false</Candidate>",
        "      </NetworkDevice>",
        "      <NetworkDevice>",
        "        <MacAddress>33:77:90:88</MacAddress>",
        "        <DeviceName>vfevfvf</DeviceName>",
        "        <Interface>Te1/1</Interface>",
        "        <IfType>6</IfType>",
        "        <AddressCount>170</AddressCount>",
        "        <Uplink>true</Uplink>",
        "        <Seen>true</Seen>",
        "        <Candidate>false</Candidate>",
        "      </NetworkDevice>",
        "      <NetworkDevice>",
        "        <MacAddress>33:77:90:88</MacAddress>",
        "        <DeviceName>fvefvfev</DeviceName>",
        "        <Interface>Gi1/0</Interface>",
        "        <IfType>6</IfType>",
        "        <AddressCount>168</AddressCount>",
        "        <Uplink>true</Uplink>",
        "        <Seen>true</Seen>",
        "        <Candidate>false</Candidate>",
        "      </NetworkDevice>",
        "    </Connection>",
        "  </Host>",
        "</HostDiscovery>"
    ]
}
  

Мне нужно получить devicename из приведенного выше xml, где candidate == true и uplink == false.В основном выходные данные должны выдавать выходные данные как devicename=kscjdsc в приведенном выше примере, поскольку именно там кандидат == true, а восходящая ссылка == false.
Кто-нибудь может мне помочь, как я могу это сделать с помощью ansible playbook. Спасибо за ваше время.

Комментарии:

1. Что вы уже пробовали? В Ansible есть модуль xml , который позволяет анализировать XML с помощью выражений XPath.

2. Я попытался присвоить переменной register значение, используя xmlstring=splat в приведенном ниже формате xmlstring=»{{splat}}» и упомянул xpath =/HostDiscovery / Host / Connection, но до сих пор это никогда не работало. Не могли бы вы сказать мне, как я могу использовать модуль XML для достижения вышеуказанной функциональности.

3. Удалите мой последний комментарий, который оказался неверным, чтобы он не смущал следующих пользователей.

Ответ №1:

xml Модуль может возвращать либо текстовое содержимое элемента, либо значение атрибута из элемента. Если ваше выражение xpath было /HostDiscovery/Host/Connection таким, как вы указали, то вы не получите желаемых результатов: DeviceName атрибут вложен на несколько уровней ниже этой точки. Что-то вроде этого может сработать:

 - xml:
    xmlstring: "{{ data.content|b64decode }}"
    xpath: "/HostDiscovery/Host/Connection/NetworkDevice[Candidate='true' and Uplink='false']/DeviceName"
    content: text
  register: result

- debug:
    var: result.matches|default([])
  

С вашим примером ввода это привело бы к:

 TASK [get device name] ************************************************************************
ok: [localhost]

TASK [debug] **********************************************************************************
ok: [localhost] => {
    "devicenames.matches|default([])": [
        {
            "DeviceName": "kscjdsc"
        }
    ]
}
  

Комментарии:

1. Не редактируйте чей-либо ответ, чтобы ответить на него. Оставляйте комментарии и / или обновляйте свой вопрос. Ошибки, которые вы видите, похоже, не имеют никакого отношения к XML.

2. @pinkbask. сегодня вы снова задали тот же вопрос в новом сообщении. Почему вы дублируете? Ваша проблема в том, что вы используете splat.stdout_lines (который содержит список всех строк в вашем выводе) вместо splat.stdout (самого вывода) в качестве вашей xmlstring.