Ansible Module xml: Difference between revisions

From NovaOrdis Knowledge Base
Jump to navigation Jump to search
 
(98 intermediate revisions by the same user not shown)
Line 8: Line 8:
=Example=
=Example=
<syntaxhighlight lang='xml'>
<syntaxhighlight lang='xml'>
<root>
<box>
     <child name="A" color="red">square</child>
     <object name="A" color="red">square</child>
     <child name="B" color="green">circle</child>
     <object name="B" color="green">circle</child>
     <child name="C" color="blue">triangle</child>
     <object name="C" color="blue">triangle</child>
</root>
</box>
</syntaxhighlight>
</syntaxhighlight>
<syntaxhighlight lang='yaml'>
<syntaxhighlight lang='yaml'>
Line 18: Line 18:
   xml:
   xml:
     path: /tmp/test.xml # the file must exist
     path: /tmp/test.xml # the file must exist
     xpath: /root/child[@name='B']
     xpath: /box/object[@name='B']
</syntaxhighlight>
</syntaxhighlight>


=Module Parameters=
=Module Parameters=
==<tt>path</tt>==
==<span id='path'></span><tt>path</tt> (<tt>dest</tt>, <tt>file</tt>)==
The path to the file to operate on. The file must exists, otherwise the module will fail, with a message similar to:
The path to the file to operate on. The file must exists, otherwise the module will fail, with a message similar to:
<code><font color=red>The target XML source '...' does not exist.</font></code>.
<code><font color=red>The target XML source '...' does not exist.</font></code>.
The parameter is required unless <code>[[#xmlstring|xmlstring]]</code> is provided.
The parameter is required unless <code>[[#xmlstring|xmlstring]]</code> is provided.
<syntaxhighlight lang='yaml'>
- name: test
  xml:
    path: /tmp/test.xml # the file must exist
    ...
</syntaxhighlight>


==<tt>xpath</tt>==
==<tt>xpath</tt>==
A valid [[XPath]] expression describing the file item(s) to manipulate. Operates on the document root, /, by default.
A valid [[XPath]] expression describing the file item(s) to manipulate. Operates on the document root, /, by default.
==<tt>content</tt>==
<syntaxhighlight lang='yaml'>
Return the content of the matching XPath expression. <code>[[#xpath|xpath]]</code> must be set. It can have to values:
- name: test
===<tt>attribute</tt>===
  xml:
    ...
    xpath: /box/object[@name='B']
    ...
</syntaxhighlight>
⚠️ Important: the attribute values to query on must be quoted. This is correct:
<syntaxhighlight lang='yaml'>
xpath: /box/object[@name='B']
</syntaxhighlight>
This is not:
<syntaxhighlight lang='yaml'>
xpath: /box/object[@name=B]
</syntaxhighlight>
and will cause a failure: <code><font color=red>Xpath /box/object[@name=B] does not reference a node!</font></code>.
 
==<tt>count</tt>==
Boolean. Configure the module to provide the xpath match count. By default is turned off.
==<tt>xmlstring</tt>==
A string containing in-line XML content on which to operate. This parameter is required, unless <code>[[#path|path]]</code> is given.
==<tt>pretty_print</tt>==
A boolean value ("yes", "no") that tells whether to pretty print the content of the generated files. By default, pretty printing is turned off.
==<tt>backup</tt>==
Boolean (yes, no). Create a backup file including timestamp information so the original file can be recovered in case the transformation is wrong.
==<tt>namespaces</tt>==
==<tt>print_match</tt>==
Boolean, by default is turned off. Search for a given XPath and print out any matches. This parameter requires <code>[[#xpath|xpath]]</code> to be set.
==<span id='state'></span><tt>state</tt> (<tt>ensure</tt>)==
Used to set or remove an xpath selection. Can be used to update or remove nodes and attributes. String value: 'absent', 'present'. Default value: 'present'.
 
Examples:
* [[#Remove_an_Attribute_with_state|Remove an attribute from the matching element]].
 
==<tt>strip_cdata_tags</tt>==
==<tt>content</tt>: Query with XPath and Specifying what Kind of Result to Provide==
Specifies the kind of content we want to get from the matching XPath expression:
* <code>[[#content_attribute|attribute]]</code> or
* <code>[[#text|text]]</code>.  
<code>[[#xpath|xpath]]</code> must be set.
===<span id='content_attribute'></span><tt>attribute</tt>===
The <code>matches</code> result key contains a JSON document listing the matching elements and the value of all their attributes. The <code>count</code> result key contains the number of matching elements.
The <code>matches</code> result key contains a JSON document listing the matching elements and the value of all their attributes. The <code>count</code> result key contains the number of matching elements.
<syntaxhighlight lang='yaml'>
<syntaxhighlight lang='yaml'>
Line 37: Line 81:
   xml:
   xml:
     path: test.xml
     path: test.xml
     xpath: /root/child[@name='B']
     xpath: /box/object[@name='B']
     content: attribute
     content: 'attribute'
   register: xpath_result
   register: xpath_result
</syntaxhighlight>
</syntaxhighlight>
produces the following <code>xpath_result.matches</code>:
produces the following <code>xpath_result.matches</code>:
<syntaxhighlight lang=JSON>
<syntaxhighlight lang=JSON>
{
[
  "child": {
  {
    "color": "green",
    "object": {
    "name": "B"
      "color": "green",
      "name": "B"
    }
   }
   }
}
]
</syntaxhighlight>
The value of a specific attribute can be displayed with <code>'{{ xpath_result.matches[0].object.color }}'</code>.
===<tt>text</tt>===
The <code>matches</code> result key contains a JSON document listing the matching elements name and its element text. The <code>count</code> result key contains the number of matching elements.
<syntaxhighlight lang='yaml'>
- name: test
  xml:
    path: test.xml
    xpath: /box/object[@name='B']
    content: 'text'
  register: xpath_result
</syntaxhighlight>
produces the following <code>xpath_result.matches</code>:
<syntaxhighlight lang=JSON>
[
  {
    "object": "circle"
  }
]
</syntaxhighlight>
The value of a specific element can be displayed with <code>'{{ result.matches[0].object }}'</code>.
 
==Updating Attribute and Element with <tt>attribute</tt>/<tt>value</tt> Usage Pattern==
<code>attribute</code>/<code>value</code> can be used to add, update and delete XML elements and their attributes. Elements can also be [[#Remove_an_Attribute_with_state|deleted]] using <code>[[#state_.28ensure.29|state]]</code>. Use the <code>[[#xpath|xpath]]</code> to match the element(s), use the <code>[[#value_attribute|attribute]]</code> element to specify the element whose value must be modified or deleted, and use the <code>[[#value|value]]</code> element to provide the new value (desired state) as a string. Use None to remove the attribute. The update is idempotent. This pattern can be used to update, add and remove elements and attributes.
 
Updating an attribute:
<syntaxhighlight lang='yaml'>
- name: test
  xml:
    file: test.xml
    xpath: /box/object[@name='B']
    attribute: 'color'
    value: 'fuchsia'
</syntaxhighlight>
Removing an attribute: <font color=darkgray>TODO, did not work.</font>
 
Updating an element:
<syntaxhighlight lang='yaml'>
- name: test
  xml:
    file: test.xml
    xpath: /box/object[@name='B']
    value: 'rectangle'
</syntaxhighlight>
</syntaxhighlight>


===<tt>text</tt>===
===<span id='value_attribute'></span><tt>attribute</tt>===
Specify the name of the attribute to select, as string, when using parameter <code>[[#value|value]]</code>. Do not prepend with '@'. If <code>attribute:</code> is not specified at all, the module [[#Update_the_Value_of_an_Element|updates the element value]].
 
===<tt>value</tt>===
Configuration element useful when updating or deleting XML content. <code>value</code> represents the desired state of the attribute specified in <code>[[#value_attribute|attribute]]</code>. It could be either a string, <font color=darkgray>or to unset a value, the Python None keyword (YAML Equivalent, null)</font>.


==<tt>xmlstring</tt>==
Elements default to no value (but present). Attributes default to an empty string.


==Children Manipulation==
Children can be added with <code>[[#add_children|add_children]]</code> or updated with <code>[[#set_children|set_children]]</code>:
===<tt>input_type</tt>===
"xml" or "yaml": the input type for <code>[[#add_children|add_children]]</code>, <code>[[#set_children|set_children]]</code>.
===<tt>add_children</tt>===
Add additional child element(s) to the element that matched <code>[[#xpath|xpath]]</code>. The elements to be added must be given in a list. Each item may be either a string (example: <code>children=ansible</code> to add an empty <code><ansible/></code> child or a hash where the key is an element name and the value is the element value. <code>[[#xpath|xpath]]</code> must be set if <code>add_children</code> is used.
<syntaxhighlight lang='yaml'>
- name: test
  xml:
    file: test.xml
    xpath: /box
    pretty_print: true
    add_children:
      # Add a new <object>rectangle</rectangle> <box> sub-element 
      - object: rectangle
      # Add a new <object>ellipse</rectangle> <box> sub-element 
      - object: ellipse
</syntaxhighlight>
This will modify the file and add the following content:
<syntaxhighlight lang='xml'>
<box>
...
<object>rectangle</object><object>ellipse</object></box>
</syntaxhighlight>
The output is not "pretty printed", to pretty print, use <code>[[#pretty_print|pretty_print]]: yes</code>


=Use Cases=
For this syntax:
==Query==
<syntaxhighlight lang='yaml'>
==Insertion==
add_children:
==Update==
  - object: ""
==Deletion==
</syntaxhighlight>
we get:
<syntaxhighlight lang='xml'>
<box>
  ...
  <object></object>
</syntaxhighlight>
For this syntax:
<syntaxhighlight lang='yaml'>
add_children:
  - object: # nothing else
</syntaxhighlight>
we get:
<syntaxhighlight lang='xml'>
<box>
  ...
  <object/>
</syntaxhighlight>
For more complex examples of how to add elements with attributes and recursive elements, see:
* [[#Add_Elements_with_Values|Add Elements with Values]]
* [[#Add_an_Element_with_Attributes|Add an Element with Attributes]]
* [[#Add_an_Element_with_Attributes_and_Value|Add an Element with Attributes and Value]]
* [[#Add_a_Complex.2C_Hierarchical_Element|Add a Complex, Hierarchical Element]]


===<tt>set_children</tt>===
Set the child element(s) of a selected element for a given xpath. Removes any existing children. Child elements must be specified as in [[#add_children|add_children]].
===<tt>insertbefore</tt>===
Add additional child element(s) before the first selected element for a given xpath.
Child elements must be given in a list and each item may be either a string (eg. children=ansible to add an empty <ansible/> child element), or a hash where the key is an element name and the value is the element value.
This parameter requires xpath to be set.
===<tt>insertafter</tt>===
Add additional child element(s) after the last selected element for a given xpath. Child elements must be given in a list and each item may be either a string (eg. children=ansible to add an empty <ansible/> child element), or a hash where the key is an element name and the value is the element value. This parameter requires xpath to be set.


=Playground=
{{External|https://github.com/ovidiuf/playground/tree/master/ansible/modules/community.general.xml}}
=Use Cases=
{{External|https://docs.ansible.com/ansible/latest/collections/community/general/xml_module.html#examples}}
====Add Elements with Values====
<syntaxhighlight lang='yaml'>
- name: test
  xml:
    file: test.xml
    xpath: /box
    pretty_print: true
    add_children:
      - object: 'rectangle'
      - object: 'ellipsis'
</syntaxhighlight> adds:
<syntaxhighlight lang='xml'>
<box>
  ...
  <object>rectangle</object>
  <object>ellipsis</object>
</box>
</syntaxhighlight>
====Add an Element with Attributes====
<syntaxhighlight lang='yaml'>
- name: test
  xml:
    file: test.xml
    xpath: /box
    pretty_print: true
    add_children:
      - object:
          name: 'D'
          color: 'yellow'
</syntaxhighlight> adds:
<syntaxhighlight lang='xml'>
<box>
  ...
  <object name="D" color="yellow"/>
</box>
</syntaxhighlight>


====Add an Element with Attributes and Value====
<font color=darkgray>There is no obvious way</font> to add an element that has specific attributes and a specific value in one operation. This is how it's done in two operations: add the element with attributes and then update it with the correct value.
<syntaxhighlight lang='yaml'>
- name: Add an element with the required attributes
  xml:
    file: test.xml
    xpath: /box
    pretty_print: true
    add_children:
      - object:
          name: 'D'
          color: 'yellow'
- name: Update added element with the correct value
  xml:
    file: test.xml
    xpath: /box/object[@name='D' and @color='yellow']
    value: 'rectangle'
</syntaxhighlight> adds:
<syntaxhighlight lang='xml'>
<box>
  ...
  <object name="D" color="yellow">rectangle</object>
</box>
</syntaxhighlight>


====Add a Complex, Hierarchical Element====
<syntaxhighlight lang='yaml'>
- name: test playbook
  hosts: localhost
  tasks:
    - name: test
      xml:
        file: /Users/ovidiu/tmp/jdk.table.2.xml
        xpath: /application/component[@name='ProjectJdkTable']
        pretty_print: true
        add_children:
          - jdk:
              # <jdk> attributes
              version: "2"
              # <jdk> sub-nodes <name>, <type>, ... <roots>
              _:
                - name:
                    value: "corretto-12"
                - type:
                    value: "JavaSDK"
                - version:
                    value: "Amazon Corretto version 12.0.77"
                - homePath:
                    value: "/Library/Java/JavaVirtualMachines/amazon-corretto-12.jdk/Contents/Home"
                - roots:
                    # <roots> sub-nodes <annotationPath>, <classPath>, ...
                    _:
                      - annotationsPath:
                          # <annotationsPath> sub-node <root>
                          _:
                            - root:
                                # <root> attributes
                                type: "composite"
                                # <root> sub-nodes <root>
                                _:
                                  - root:
                                      # <root> attributes
                                      url: "jar://$APPLICATION_HOME_DIR$/plugins/java/lib/jdkAnnotations.jar!/"
                                      type: "simple"
                      - classPath:
                          _:
                            - root:
                                type: "composite"
                                _:
                                  - root:
                                      url: "jrt:///Library/Java/JavaVirtualMachines/amazon-corretto-11.jdk/Contents/Home!/java.base"
                                      type: "simple"
                                  - root:
                                      url: "jrt:///Library/Java/JavaVirtualMachines/amazon-corretto-11.jdk/Contents/Home!/java.compiler"
                                      type: "simple"
                      - javadocPath:
                          _:
                            - root:
                                type: "composite"
                      - sourcePath:
                          _:
                            - root:
                                type: "composite"
                                _:
                                  - root:
                                      url: "jar:///Library/Java/JavaVirtualMachines/amazon-corretto-11.jdk/Contents/Home/lib/src.zip!/java.se"
                                      type: "simple"
                                  - root:
                                      url: "jar:///Library/Java/JavaVirtualMachines/amazon-corretto-11.jdk/Contents/Home/lib/src.zip!/jdk.aot"
                                      type: "simple"
                - additional:
</syntaxhighlight>
produces:
<syntaxhighlight lang='xml'>
<?xml version='1.0' encoding='UTF-8'?>
<application>
  <component name="ProjectJdkTable">
    <jdk version="2">
      <name value="corretto-12"/>
      <type value="JavaSDK"/>
      <version value="Amazon Corretto version 12.0.77"/>
      <homePath value="/Library/Java/JavaVirtualMachines/amazon-corretto-12.jdk/Contents/Home"/>
      <roots>
        <annotationsPath>
          <root type="composite">
            <root url="jar://$APPLICATION_HOME_DIR$/plugins/java/lib/jdkAnnotations.jar!/" type="simple"/>
          </root>
        </annotationsPath>
        <classPath>
          <root type="composite">
            <root url="jrt:///Library/Java/JavaVirtualMachines/amazon-corretto-11.jdk/Contents/Home!/java.base" type="simple"/>
            <root url="jrt:///Library/Java/JavaVirtualMachines/amazon-corretto-11.jdk/Contents/Home!/java.compiler" type="simple"/>
          </root>
        </classPath>
        <javadocPath>
          <root type="composite"/>
        </javadocPath>
        <sourcePath>
          <root type="composite">
            <root url="jar:///Library/Java/JavaVirtualMachines/amazon-corretto-11.jdk/Contents/Home/lib/src.zip!/java.se" type="simple"/>
            <root url="jar:///Library/Java/JavaVirtualMachines/amazon-corretto-11.jdk/Contents/Home/lib/src.zip!/jdk.aot" type="simple"/>
          </root>
        </sourcePath>
      </roots>
      <additional/>
    </jdk>
  </component>
</application>


</syntaxhighlight>
====<span id='Update_the_Value_of_an_Attribute'></span>Update an Attribute====
<syntaxhighlight lang='yaml'>
<syntaxhighlight lang='yaml'>
- name: Bump Java build heap size to {{build.jvm.heap_max}} MB
- name: test
   xml:
   xml:
     path: "{{ansible_env.PROJECT_ROOT}}/.idea/compiler.xml"
     file: test.xml
     xpath: /project/component[@name='CompilerConfiguration']/option[@name='BUILD_PROCESS_HEAP_SIZE']
     xpath: /box/object[@name='B']
     attribute: "value"
     attribute: 'color'
     value: "{{build.jvm.heap_max}}"
     value: 'fuchsia'
</syntaxhighlight>
</syntaxhighlight>
Also see "[[#Updating_Attribute_and_Element_with_attribute.2Fvalue_Usage_Pattern|Updating Attributes and Elements with attribute/value Usage Pattern]]" above.


====Update the Value of an Element====
<syntaxhighlight lang='yaml'>
<syntaxhighlight lang='yaml'>
- name: Set Eclipse as default compiler
- name: test
   xml:
   xml:
     path: "{{idea_path}}/.idea/compiler.xml"
     path: "{{idea_path}}/.idea/compiler.xml"
     xpath: /project/component[@name='CompilerConfiguration']/option[@name='DEFAULT_COMPILER']
     xpath: /box/object[@name='B']
     attribute: "value"
    value: "hexagon"
    value: "Eclipse"
</syntaxhighlight>
====Remove an Attribute with <tt>state</tt>====
Remove the 'color' attribute from matching elements.
<syntaxhighlight lang='yaml'>
- name: test
  xml:
    file: /Users/ovidiu/tmp/test.xml
    xpath: /box/object[@name='B']/@color
     state: 'absent'
</syntaxhighlight>
</syntaxhighlight>
Also see <code>[[#state|state]]</code> above.
====Remove an Element with <tt>state</tt>====
Remove the 'color' attribute from matching elements.
<syntaxhighlight lang='yaml'>
- name: test
  xml:
    file: /Users/ovidiu/tmp/test.xml
    xpath: /box/object[@name='B']
    state: 'absent'
</syntaxhighlight>
To remove the parent element, add "/.." to the XPath.
Also see <code>[[#state|state]]</code> above.
====Build a list of Elements from a Loop====

Latest revision as of 22:48, 6 July 2021

External

Internal

Overview

The plugin is named community.general.xml and it offers functionality aimed at interacting with XML files, using XPath.

Example

<box>
    <object name="A" color="red">square</child>
    <object name="B" color="green">circle</child>
    <object name="C" color="blue">triangle</child>
</box>
- name: XML manipulation
  xml:
    path: /tmp/test.xml # the file must exist
    xpath: /box/object[@name='B']

Module Parameters

path (dest, file)

The path to the file to operate on. The file must exists, otherwise the module will fail, with a message similar to: The target XML source '...' does not exist.. The parameter is required unless xmlstring is provided.

- name: test
  xml:
    path: /tmp/test.xml # the file must exist
    ...

xpath

A valid XPath expression describing the file item(s) to manipulate. Operates on the document root, /, by default.

- name: test
  xml:
    ...
    xpath: /box/object[@name='B']
    ...

⚠️ Important: the attribute values to query on must be quoted. This is correct:

xpath: /box/object[@name='B']

This is not:

xpath: /box/object[@name=B]

and will cause a failure: Xpath /box/object[@name=B] does not reference a node!.

count

Boolean. Configure the module to provide the xpath match count. By default is turned off.

xmlstring

A string containing in-line XML content on which to operate. This parameter is required, unless path is given.

pretty_print

A boolean value ("yes", "no") that tells whether to pretty print the content of the generated files. By default, pretty printing is turned off.

backup

Boolean (yes, no). Create a backup file including timestamp information so the original file can be recovered in case the transformation is wrong.

namespaces

print_match

Boolean, by default is turned off. Search for a given XPath and print out any matches. This parameter requires xpath to be set.

state (ensure)

Used to set or remove an xpath selection. Can be used to update or remove nodes and attributes. String value: 'absent', 'present'. Default value: 'present'.

Examples:

strip_cdata_tags

content: Query with XPath and Specifying what Kind of Result to Provide

Specifies the kind of content we want to get from the matching XPath expression:

xpath must be set.

attribute

The matches result key contains a JSON document listing the matching elements and the value of all their attributes. The count result key contains the number of matching elements.

- name: test
  xml:
    path: test.xml
    xpath: /box/object[@name='B']
    content: 'attribute'
  register: xpath_result

produces the following xpath_result.matches:

[
  {
    "object": {
      "color": "green",
       "name": "B"
    }
  }
]

The value of a specific attribute can be displayed with '{{ xpath_result.matches[0].object.color }}'.

text

The matches result key contains a JSON document listing the matching elements name and its element text. The count result key contains the number of matching elements.

- name: test
  xml:
    path: test.xml
    xpath: /box/object[@name='B']
    content: 'text'
  register: xpath_result

produces the following xpath_result.matches:

[
  {
    "object": "circle"
  }
]

The value of a specific element can be displayed with '{{ result.matches[0].object }}'.

Updating Attribute and Element with attribute/value Usage Pattern

attribute/value can be used to add, update and delete XML elements and their attributes. Elements can also be deleted using state. Use the xpath to match the element(s), use the attribute element to specify the element whose value must be modified or deleted, and use the value element to provide the new value (desired state) as a string. Use None to remove the attribute. The update is idempotent. This pattern can be used to update, add and remove elements and attributes.

Updating an attribute:

- name: test
  xml:
    file: test.xml
    xpath: /box/object[@name='B']
    attribute: 'color'
    value: 'fuchsia'

Removing an attribute: TODO, did not work.

Updating an element:

- name: test
  xml:
    file: test.xml
    xpath: /box/object[@name='B']
    value: 'rectangle'

attribute

Specify the name of the attribute to select, as string, when using parameter value. Do not prepend with '@'. If attribute: is not specified at all, the module updates the element value.

value

Configuration element useful when updating or deleting XML content. value represents the desired state of the attribute specified in attribute. It could be either a string, or to unset a value, the Python None keyword (YAML Equivalent, null).

Elements default to no value (but present). Attributes default to an empty string.

Children Manipulation

Children can be added with add_children or updated with set_children:

input_type

"xml" or "yaml": the input type for add_children, set_children.

add_children

Add additional child element(s) to the element that matched xpath. The elements to be added must be given in a list. Each item may be either a string (example: children=ansible to add an empty <ansible/> child or a hash where the key is an element name and the value is the element value. xpath must be set if add_children is used.

- name: test
  xml:
    file: test.xml
    xpath: /box
    pretty_print: true
    add_children:
      # Add a new <object>rectangle</rectangle> <box> sub-element  
      - object: rectangle
      # Add a new <object>ellipse</rectangle> <box> sub-element  
      - object: ellipse

This will modify the file and add the following content:

<box>
...
<object>rectangle</object><object>ellipse</object></box>

The output is not "pretty printed", to pretty print, use pretty_print: yes

For this syntax:

add_children:
  - object: ""

we get:

<box>
  ...
  <object></object>

For this syntax:

add_children:
  - object: # nothing else

we get:

<box>
  ...
  <object/>

For more complex examples of how to add elements with attributes and recursive elements, see:

set_children

Set the child element(s) of a selected element for a given xpath. Removes any existing children. Child elements must be specified as in add_children.

insertbefore

Add additional child element(s) before the first selected element for a given xpath. Child elements must be given in a list and each item may be either a string (eg. children=ansible to add an empty <ansible/> child element), or a hash where the key is an element name and the value is the element value. This parameter requires xpath to be set.

insertafter

Add additional child element(s) after the last selected element for a given xpath. Child elements must be given in a list and each item may be either a string (eg. children=ansible to add an empty <ansible/> child element), or a hash where the key is an element name and the value is the element value. This parameter requires xpath to be set.

Playground

https://github.com/ovidiuf/playground/tree/master/ansible/modules/community.general.xml

Use Cases

https://docs.ansible.com/ansible/latest/collections/community/general/xml_module.html#examples

Add Elements with Values

- name: test
  xml:
    file: test.xml
    xpath: /box
    pretty_print: true
    add_children:
      - object: 'rectangle'
      - object: 'ellipsis'

adds:

<box>
  ...
  <object>rectangle</object>
  <object>ellipsis</object>
</box>

Add an Element with Attributes

- name: test
  xml:
    file: test.xml
    xpath: /box
    pretty_print: true
    add_children:
      - object:
          name: 'D'
          color: 'yellow'

adds:

<box>
  ...
  <object name="D" color="yellow"/>
</box>

Add an Element with Attributes and Value

There is no obvious way to add an element that has specific attributes and a specific value in one operation. This is how it's done in two operations: add the element with attributes and then update it with the correct value.

- name: Add an element with the required attributes
  xml:
    file: test.xml
    xpath: /box
    pretty_print: true
    add_children:
      - object:
          name: 'D'
          color: 'yellow'
- name: Update added element with the correct value
  xml:
    file: test.xml
    xpath: /box/object[@name='D' and @color='yellow']
    value: 'rectangle'

adds:

<box>
  ...
  <object name="D" color="yellow">rectangle</object>
</box>

Add a Complex, Hierarchical Element

- name: test playbook
  hosts: localhost
  tasks:
    - name: test
      xml:
        file: /Users/ovidiu/tmp/jdk.table.2.xml
        xpath: /application/component[@name='ProjectJdkTable']
        pretty_print: true
        add_children:
          - jdk:
              # <jdk> attributes
              version: "2"
              # <jdk> sub-nodes <name>, <type>, ... <roots>
              _:
                - name:
                    value: "corretto-12"
                - type:
                    value: "JavaSDK"
                - version:
                    value: "Amazon Corretto version 12.0.77"
                - homePath:
                    value: "/Library/Java/JavaVirtualMachines/amazon-corretto-12.jdk/Contents/Home"
                - roots:
                    # <roots> sub-nodes <annotationPath>, <classPath>, ...
                    _:
                      - annotationsPath:
                          # <annotationsPath> sub-node <root>
                          _:
                            - root:
                                # <root> attributes
                                type: "composite"
                                # <root> sub-nodes <root>
                                _:
                                  - root:
                                      # <root> attributes
                                      url: "jar://$APPLICATION_HOME_DIR$/plugins/java/lib/jdkAnnotations.jar!/"
                                      type: "simple"
                      - classPath:
                          _:
                            - root:
                                type: "composite"
                                _:
                                  - root:
                                      url: "jrt:///Library/Java/JavaVirtualMachines/amazon-corretto-11.jdk/Contents/Home!/java.base"
                                      type: "simple"
                                  - root:
                                      url: "jrt:///Library/Java/JavaVirtualMachines/amazon-corretto-11.jdk/Contents/Home!/java.compiler"
                                      type: "simple"
                      - javadocPath:
                          _:
                            - root:
                                type: "composite"
                      - sourcePath:
                          _:
                            - root:
                                type: "composite"
                                _:
                                  - root:
                                      url: "jar:///Library/Java/JavaVirtualMachines/amazon-corretto-11.jdk/Contents/Home/lib/src.zip!/java.se"
                                      type: "simple"
                                  - root:
                                      url: "jar:///Library/Java/JavaVirtualMachines/amazon-corretto-11.jdk/Contents/Home/lib/src.zip!/jdk.aot"
                                      type: "simple"
                - additional:

produces:

<?xml version='1.0' encoding='UTF-8'?>
<application>
  <component name="ProjectJdkTable">
    <jdk version="2">
      <name value="corretto-12"/>
      <type value="JavaSDK"/>
      <version value="Amazon Corretto version 12.0.77"/>
      <homePath value="/Library/Java/JavaVirtualMachines/amazon-corretto-12.jdk/Contents/Home"/>
      <roots>
        <annotationsPath>
          <root type="composite">
            <root url="jar://$APPLICATION_HOME_DIR$/plugins/java/lib/jdkAnnotations.jar!/" type="simple"/>
          </root>
        </annotationsPath>
        <classPath>
          <root type="composite">
            <root url="jrt:///Library/Java/JavaVirtualMachines/amazon-corretto-11.jdk/Contents/Home!/java.base" type="simple"/>
            <root url="jrt:///Library/Java/JavaVirtualMachines/amazon-corretto-11.jdk/Contents/Home!/java.compiler" type="simple"/>
          </root>
        </classPath>
        <javadocPath>
          <root type="composite"/>
        </javadocPath>
        <sourcePath>
          <root type="composite">
            <root url="jar:///Library/Java/JavaVirtualMachines/amazon-corretto-11.jdk/Contents/Home/lib/src.zip!/java.se" type="simple"/>
            <root url="jar:///Library/Java/JavaVirtualMachines/amazon-corretto-11.jdk/Contents/Home/lib/src.zip!/jdk.aot" type="simple"/>
          </root>
        </sourcePath>
      </roots>
      <additional/>
    </jdk>
  </component>
</application>

Update an Attribute

- name: test
  xml:
    file: test.xml
    xpath: /box/object[@name='B']
    attribute: 'color'
    value: 'fuchsia'

Also see "Updating Attributes and Elements with attribute/value Usage Pattern" above.

Update the Value of an Element

- name: test
  xml:
    path: "{{idea_path}}/.idea/compiler.xml"
    xpath: /box/object[@name='B']
    value: "hexagon"

Remove an Attribute with state

Remove the 'color' attribute from matching elements.

- name: test
  xml:
    file: /Users/ovidiu/tmp/test.xml
    xpath: /box/object[@name='B']/@color
    state: 'absent'

Also see state above.

Remove an Element with state

Remove the 'color' attribute from matching elements.

- name: test
  xml:
    file: /Users/ovidiu/tmp/test.xml
    xpath: /box/object[@name='B']
    state: 'absent'

To remove the parent element, add "/.." to the XPath. Also see state above.

Build a list of Elements from a Loop