community.general icon indicating copy to clipboard operation
community.general copied to clipboard

xml add_children cant add <a href="foo">bar</a> using yaml

Open Daniel-Sanchez-Fabregas opened this issue 3 years ago • 9 comments

Summary

I can't find a way to add the xml node4 in the question of the example:

- hosts: localhost
  gather_facts: no
  vars:
    ansible_python_interpreter: /usr/bin/python3
  tasks:
  - name: Creating xml file
    copy:
      dest: out.xml
      content: |-
        <?xml version='1.0' encoding='UTF-8'?>
        <root>
        </root>
  - xml:
      path: out.xml
      xpath: /root
      add_children:
        - node:
            attribute: attribute_text
            _:
              - sub_node:
        - node2: node2_text
        - node3: "1"  # Only strings are valid
        # How to add here <node4 attribute="attribute_text">node4_text</node4> in yaml?
        # Analogous to: <a href="foo">bar</a>

Is is possible? Is it documented?

Issue Type

Feature Request

Component Name

xml

Ansible Version

$ ansible --version                                                                                                                                                               
ansible 2.10.5
  config file = /home/user/.ansible.cfg
  configured module search path = ['~/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /var/lib/ansible/venv/lib/python3.8/site-packages/ansible
  executable location = /var/lib/ansible/venv/bin/ansible
  python version = 3.8.9 (default, Apr  6 2021, 00:00:00) [GCC 10.2.1 20201125 (Red Hat 10.2.1-9)]

Configuration

$ ansible-config dump --only-changed
ANSIBLE_PIPELINING(/home/user/.ansible.cfg) = True
ANSIBLE_SSH_ARGS(/home/user/.ansible.cfg) = -F /home/user/.ssh/config -o ControlMaster=auto -o ControlPersist=30m
ANSIBLE_SSH_CONTROL_PATH(/home/user/.ansible.cfg) = ~/.ssh/master-%%r@%%h:%%p
CACHE_PLUGIN(/home/user/.ansible.cfg) = memory
DEFAULT_ACTION_PLUGIN_PATH(/home/user/.ansible.cfg) = ['/home/user/.ansible/plugins/action_plugins']
DEFAULT_CALLBACK_PLUGIN_PATH(/home/user/.ansible.cfg) = ['/home/user/.ansible/plugins/callback_plugins']
DEFAULT_CONNECTION_PLUGIN_PATH(/home/user/.ansible.cfg) = ['/home/user/.ansible/plugins/connection_plugins']
DEFAULT_FILTER_PLUGIN_PATH(/home/user/.ansible.cfg) = ['/home/user/.ansible/plugins/filter_plugins']
DEFAULT_FORKS(/home/user/.ansible.cfg) = 10
DEFAULT_GATHERING(/home/user/.ansible.cfg) = implicit
DEFAULT_HOST_LIST(/home/user/.ansible.cfg) = ['/home/user/.ansible/inventory']
DEFAULT_JINJA2_EXTENSIONS(/home/user/.ansible.cfg) = jinja2.ext.do, jinja2.ext.i18n, jinja2.ext.loopcontrols
DEFAULT_JINJA2_NATIVE(/home/user/.ansible.cfg) = False
DEFAULT_LOG_PATH(/home/user/.ansible.cfg) = /home/user/.ansible/log/ansible.log
DEFAULT_LOOKUP_PLUGIN_PATH(/home/user/.ansible.cfg) = ['/home/user/.ansible/plugins/lookup_plugins']
DEFAULT_MANAGED_STR(/home/user/.ansible.cfg) = Ansible managed. Don't modify it directly.
DEFAULT_POLL_INTERVAL(/home/user/.ansible.cfg) = 15
DEFAULT_ROLES_PATH(/home/user/.ansible.cfg) = ['/home/user/srv/ansible/roles']
DEFAULT_TIMEOUT(/home/user/.ansible.cfg) = 60
DEFAULT_TRANSPORT(/home/user/.ansible.cfg) = smart
DEFAULT_VARS_PLUGIN_PATH(/home/user/.ansible.cfg) = ['/home/user/.ansible/plugins/vars_plugins']
HOST_KEY_CHECKING(/home/user/.ansible.cfg) = False
INJECT_FACTS_AS_VARS(/home/user/.ansible.cfg) = False
INVENTORY_ENABLED(/home/user/.ansible.cfg) = ['host_list', 'script', 'yaml', 'ini']

OS / Environment

$ inxi --system --filter                                                                                                                                                          
System:    Kernel: 5.11.16-100.fc32.x86_64 x86_64 bits: 64 Desktop: MATE 1.24.2 
           Distro: Fedora release 32 (Thirty Two) 

Steps to Reproduce

- hosts: localhost
  gather_facts: no
  vars:
    ansible_python_interpreter: /usr/bin/python3
  tasks:
  - name: Creating xml file
    copy:
      dest: out.xml
      content: |-
        <?xml version='1.0' encoding='UTF-8'?>
        <root>
        </root>
  - xml:
      path: out.xml
      xpath: /root
      add_children:
        - node:
            attribute: attribute_text
            _:
              - sub_node:
        - node2: node2_text
        - node3: "1"  # Only strings are valid
        # How to add here <node4 attribute="attribute_text">node4_text</node4> in yaml?
        # Analogous to: <a href="foo">bar</a>

        # My best try:
        - node4:
              attribute: attribute_text
              _:
                - ~: node4_text

Expected Results

Output file:

<?xml version='1.0' encoding='UTF-8'?>
<root>
  <node attribute="attribute_text">
    <sub_node/>
  </node>
  <node2>node2_text</node2>
  <node3>1</node3>
  <node4 attribute="attribute_text">
    node4_text
  </node4>
</root>

Actual Results

Output file:

<?xml version='1.0' encoding='UTF-8'?>
<root>
  <node attribute="attribute_text">
    <sub_node/>
  </node>
  <node2>node2_text</node2>
  <node3>1</node3>
  <node4 attribute="attribute_text">
    <null>node4_text</null>
  </node4>
</root>

Code of Conduct

  • [x] I agree to follow the Ansible Code of Conduct

Daniel-Sanchez-Fabregas avatar Apr 28 '21 11:04 Daniel-Sanchez-Fabregas

Files identified in the description:

If these files are inaccurate, please update the component name section of the description or use the !component bot command.

click here for bot help

ansibullbot avatar Apr 28 '21 11:04 ansibullbot

cc @cmprescott @dagwieers @sm4rk0 @tbielawa click here for bot help

ansibullbot avatar Apr 28 '21 11:04 ansibullbot

@Daniel-Sanchez-Fabregas has this been resolved by #2371?

felixfontein avatar May 04 '21 20:05 felixfontein

The example in #2371:

- name: Adding building nodes with floor subnodes from a YAML variable
  community.general.xml:
    path: /foo/bar.xml
    xpath: /business
    add_children:
      - building:
          # Attributes
          name: Scumm bar
          location: Monkey island
          # Subnodes
          _:
            - floor: Pirate hall
            - floor: Grog storage
            - construction_date: "1990"  # Only strings are valid
      - building: Grog factory

The xml task creates:

<business>
  ...
  <building name="Scumm bar" location="Monkey island">
    <floor>Pirate hall</floor>
    <floor>Grog storage</floor>
    <construction_date>1990</construction_date>
  </building>
<business>

But, if you try to add a node like:

<a href: "http://127.0.0.1">localhost<a>

in the same way as the example:

- xml:
    path: /foo/bar.xml
    xpath: /business
    add_children:
      - a:
          href: "http://127.0.0.1"
          _: localhost

It fails:

TASK [xml] ***********************************************************************************************************************************************************************
fatal: [localhost]: FAILED! => {"changed": false, "msg": "Invalid children type: <class 'str'>, must be list."}

Daniel-Sanchez-Fabregas avatar May 19 '21 10:05 Daniel-Sanchez-Fabregas

What you are trying to do is not supported by the module.

felixfontein avatar May 19 '21 11:05 felixfontein

If someone is interested in implementing this: it probably needs another special key similar to _ at https://github.com/ansible-collections/community.general/blob/main/plugins/modules/files/xml.py#L729

felixfontein avatar May 19 '21 11:05 felixfontein

needs_contributor

aminvakil avatar May 23 '21 09:05 aminvakil

Files identified in the description:

If these files are incorrect, please update the component name section of the description or use the !component bot command.

click here for bot help

ansibullbot avatar Nov 11 '22 01:11 ansibullbot

Hello,

Has anyone found a solution?

ktibi avatar Sep 20 '23 15:09 ktibi