[SOLVED] How do you edit XML file with Ansible module community.general.xml

Issue

Using the Ansible module community.general.xml, I am attempting to add a child node to the following XML data: (saved into namespace-test.xml)

<configuration xmlns="urn:activemq" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xi="http://www.w3.org/2001/XInclude" xsi:schemaLocation="urn:activemq /schema/artemis-configuration.xsd">
  <core xmlns="urn:activemq:core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:activemq:core ">
  </core>
</configuration>

The data I would like to add, under the core node, is:

<xi:include href="/conf/xmlconfig-to-include.xml"/>

The Ansible task I am running is:

- name: include modular XML configuration file
  community.general.xml:
    path: namespace-test.xml
    xpath: /conf:configuration/core:core
    input_type: xml
    add_children:
      - '<xi:include href="/conf/xmlconfig-to-include.xml"/>'
    namespaces:
      conf: urn:activemq
      core: urn:activemq:core
      xi: "http://www.w3.org/2001/XInclude"
    pretty_print: yes

I am expecting to get this result:

<configuration xmlns="urn:activemq" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xi="http://www.w3.org/2001/XInclude" xsi:schemaLocation="urn:activemq /schema/artemis-configuration.xsd">
  <core xmlns="urn:activemq:core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:activemq:core ">
    <xi:include href="/conf/xmlconfig-to-include.xml"/>
  </core>
</configuration>

But I am getting the following error message, instead:

Error while parsing child element: Namespace prefix xi on include is not defined


More information after the very usefull options suggested by β.εηοιτ.βε.

The idempotent option did not meet the additionnal requirements (non-specified initially) that I need more than one include in the XML block.

This is really what I was aiming for:

<configuration xmlns="urn:activemq" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xi="http://www.w3.org/2001/XInclude" xsi:schemaLocation="urn:activemq /schema/artemis-configuration.xsd">
  <core xmlns="urn:activemq:core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:activemq:core ">
    <xi:include href="/conf/addresses.xml"/>
    <xi:include href="/conf/address-settings.xml"/>
    <xi:include href="/conf/security-settings.xml"/>
  </core>
</configuration>

Solution

There are really two approaches for your issue at hand:

  1. the highly recommended one: constructing the xpath with the node you are expecting — /conf:configuration/core:core/xi:include — and just adding the required attribute.
  2. in the line with your actual trial, using an add_children, but in a yaml form, because the XML form does not seems to cope well with namespace reference.

Why is the first one highly recommended? Because it makes your task idempotent, so, re-running your playbook won’t keep on adding the same node over and over again, if it exists with the right attribute already.

So, here is the idempotent task:

- name: include modular XML configuration file
  community.general.xml:
    path: namespace-test.xml
    xpath: /conf:configuration/core:core/xi:include
    attribute: href
    value: /conf/xmlconfig-to-include.xml
    namespaces:
      conf: urn:activemq
      core: urn:activemq:core
      xi: "http://www.w3.org/2001/XInclude"
    pretty_print: yes

Which would give your expected XML.


And regarding the fact that you do need multiple include, the trick, then is to further specialize your xpath expression, for example:

/conf:configuration
  /core:core
    /xi:include[@href='/conf/xmlconfig-to-include.xml']

So, your task to add the three include nodes could end up in a loop:

- name: include modular XML configuration file
  community.general.xml:
    path: namespace-test.xml
    xpath: /conf:configuration/core:core/xi:include[@href='{{ item }}']
    namespaces:
      conf: urn:activemq
      core: urn:activemq:core
      xi: "http://www.w3.org/2001/XInclude"
    pretty_print: yes
  loop:
    - /conf/addresses.xml
    - /conf/address-settings.xml
    - /conf/security-settings.xml

And if you really want the non-idempotent option, here it is:

- name: include modular XML configuration file
  community.general.xml:
    path: namespace-test.xml
    xpath: /conf:configuration/core:core
    add_children:
      - "{http://www.w3.org/2001/XInclude}include":
          href: /conf/xmlconfig-to-include.xml
    namespaces:
      conf: urn:activemq
      core: urn:activemq:core
      xi: "http://www.w3.org/2001/XInclude"
    pretty_print: yes

Answered By – β.εηοιτ.βε

Answer Checked By – Marie Seifert (BugsFixing Admin)

Leave a Reply

Your email address will not be published.