diff --git a/README.md b/README.md
index 45001d5..f67ddfe 100644
--- a/README.md
+++ b/README.md
@@ -21,9 +21,11 @@ PEP440 is the schema used to describe the versions of Ansible.
### Filter plugins
Name | Description
--- | ---
+[ansible.utils.from_xml](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.from_xml_filter.rst)|Convert given XML string to native python dictionary.
[ansible.utils.get_path](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.get_path_filter.rst)|Retrieve the value in a variable using a path
[ansible.utils.index_of](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.index_of_filter.rst)|Find the indices of items in a list matching some criteria
[ansible.utils.to_paths](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.to_paths_filter.rst)|Flatten a complex object into a dictionary of paths and values
+[ansible.utils.to_xml](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.to_xml_filter.rst)|Convert given JSON string to XML
[ansible.utils.validate](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.validate_filter.rst)|Validate data with provided criteria
### Lookup plugins
diff --git a/changelogs/fragments/add-xmltojson-and-jsontoxml-filter.yaml b/changelogs/fragments/add-xmltojson-and-jsontoxml-filter.yaml
new file mode 100644
index 0000000..556fde8
--- /dev/null
+++ b/changelogs/fragments/add-xmltojson-and-jsontoxml-filter.yaml
@@ -0,0 +1,3 @@
+---
+minor_changes:
+ - Add from_xml and to_xml fiter plugin (https://github.com/ansible-collections/ansible.utils/pull/56).
diff --git a/docs/ansible.utils.from_xml_filter.rst b/docs/ansible.utils.from_xml_filter.rst
new file mode 100644
index 0000000..d1d43d4
--- /dev/null
+++ b/docs/ansible.utils.from_xml_filter.rst
@@ -0,0 +1,173 @@
+.. _ansible.utils.from_xml_filter:
+
+
+**********************
+ansible.utils.from_xml
+**********************
+
+**Convert given XML string to native python dictionary.**
+
+
+Version added: 2.0.2
+
+.. contents::
+ :local:
+ :depth: 1
+
+
+Synopsis
+--------
+- This plugin converts the XML string to a native python dictionary.
+- Using the parameters below- ``data|ansible.utils.from_xml``
+
+
+
+
+Parameters
+----------
+
+.. raw:: html
+
+
+
+ Parameter |
+ Choices/Defaults |
+ Configuration |
+ Comments |
+
+
+
+
+ data
+
+
+ string
+ / required
+
+ |
+
+ |
+
+ |
+
+ The input XML string.
+ This option represents the XML value that is passed to the filter plugin in pipe format.
+ For example config_data|ansible.utils.from_xml , in this case config_data represents this option.
+ |
+
+
+
+
+ engine
+
+
+ string
+
+ |
+
+ Default:
"xmltodict"
+ |
+
+ |
+
+ Conversion library to use within the filter plugin.
+ |
+
+
+
+
+
+
+
+Examples
+--------
+
+.. code-block:: yaml
+
+ #### Simple examples with out any engine. plugin will use default value as xmltodict
+
+ tasks:
+ - name: convert given XML to native python dictionary
+ ansible.builtin.set_fact:
+ data: "
+
+ "
+
+ - debug:
+ msg: "{{ data|ansible.utils.from_xml }}"
+
+ ##TASK######
+ # TASK [convert given XML to native python dictionary] *****************************************************************************************************
+ # task path: /Users/amhatre/ansible-collections/playbooks/test_utils.yaml:5
+ # ok: [localhost] => {
+ # "ansible_facts": {
+ # "data": " "
+ # },
+ # "changed": false
+ # }
+ #
+ # TASK [debug] *************************************************************************************************************************
+ # task path: /Users/amhatre/ansible-collections/playbooks/test_utils.yaml:13
+ # Loading collection ansible.utils from /Users/amhatre/ansible-collections/collections/ansible_collections/ansible/utils
+ # ok: [localhost] => {
+ # "msg": {
+ # "netconf-state": {
+ # "@xmlns": "urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring",
+ # "schemas": {
+ # "schema": null
+ # }
+ # }
+ # }
+ # }
+
+ #### example2 with engine=xmltodict
+
+ tasks:
+ - name: convert given XML to native python dictionary
+ ansible.builtin.set_fact:
+ data: "
+
+ "
+
+ - debug:
+ msg: "{{ data|ansible.utils.from_xml('xmltodict') }}"
+
+ ##TASK######
+ # TASK [convert given XML to native python dictionary] *****************************************************************************************************
+ # task path: /Users/amhatre/ansible-collections/playbooks/test_utils.yaml:5
+ # ok: [localhost] => {
+ # "ansible_facts": {
+ # "data": " "
+ # },
+ # "changed": false
+ # }
+ #
+ # TASK [debug] *************************************************************************************************************************
+ # task path: /Users/amhatre/ansible-collections/playbooks/test_utils.yaml:13
+ # Loading collection ansible.utils from /Users/amhatre/ansible-collections/collections/ansible_collections/ansible/utils
+ # ok: [localhost] => {
+ # "msg": {
+ # "netconf-state": {
+ # "@xmlns": "urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring",
+ # "schemas": {
+ # "schema": null
+ # }
+ # }
+ # }
+ # }
+
+
+
+
+Status
+------
+
+
+Authors
+~~~~~~~
+
+- Ashwini Mhatre (@amhatre)
+
+
+.. hint::
+ Configuration entries for each entry type have a low to high priority order. For example, a variable that is lower in the list will override a variable that is higher up.
diff --git a/docs/ansible.utils.to_xml_filter.rst b/docs/ansible.utils.to_xml_filter.rst
new file mode 100644
index 0000000..40d3490
--- /dev/null
+++ b/docs/ansible.utils.to_xml_filter.rst
@@ -0,0 +1,166 @@
+.. _ansible.utils.to_xml_filter:
+
+
+********************
+ansible.utils.to_xml
+********************
+
+**Convert given JSON string to XML**
+
+
+Version added: 2.0.2
+
+.. contents::
+ :local:
+ :depth: 1
+
+
+Synopsis
+--------
+- This plugin converts the JSON string to XML.
+- Using the parameters below- ``data|ansible.utils.to_xml``
+
+
+
+
+Parameters
+----------
+
+.. raw:: html
+
+
+
+ Parameter |
+ Choices/Defaults |
+ Configuration |
+ Comments |
+
+
+
+
+ data
+
+
+ dictionary
+ / required
+
+ |
+
+ |
+
+ |
+
+ The input JSON string .
+ This option represents the JSON value that is passed to the filter plugin in pipe format.
+ For example config_data|ansible.utils.to_xml , in this case config_data represents this option.
+ |
+
+
+
+
+ engine
+
+
+ string
+
+ |
+
+ Default:
"xmltodict"
+ |
+
+ |
+
+ Conversion library to use within the filter plugin.
+ |
+
+
+
+
+
+
+
+Examples
+--------
+
+.. code-block:: yaml
+
+ #### Simple examples with out any engine. plugin will use default value as xmltodict
+
+ - name: Define JSON data
+ ansible.builtin.set_fact:
+ data:
+ "interface-configurations":
+ "@xmlns": "http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg"
+ "interface-configuration":
+ - debug:
+ msg: "{{ data|ansible.utils.to_xml }}"
+
+ # TASK [Define JSON data ] *************************************************************************
+ # task path: /Users/amhatre/ansible-collections/playbooks/test_utils_json_to_xml.yaml:5
+ # ok: [localhost] => {
+ # "ansible_facts": {
+ # "data": {
+ # "interface-configurations": {
+ # "@xmlns": "http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg",
+ # "interface-configuration": null
+ # }
+ # }
+ # },
+ # "changed": false
+ # }
+ #
+ # TASK [debug] ***********************************************************************************************************
+ # task path: /Users/amhatre/ansible-collections/playbooks/test_utils_json_to_xml.yaml:13
+ # Loading collection ansible.utils from /Users/amhatre/ansible-collections/collections/ansible_collections/ansible/utils
+ # ok: [localhost] => {
+ # "msg": "\n\n\t\n"
+ # }
+
+ #### example2 with engine=xmltodict
+
+ - name: Define JSON data
+ ansible.builtin.set_fact:
+ data:
+ "interface-configurations":
+ "@xmlns": "http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg"
+ "interface-configuration":
+ - debug:
+ msg: "{{ data|ansible.utils.to_xml('xmltodict') }}"
+
+ # TASK [Define JSON data ] *************************************************************************
+ # task path: /Users/amhatre/ansible-collections/playbooks/test_utils_json_to_xml.yaml:5
+ # ok: [localhost] => {
+ # "ansible_facts": {
+ # "data": {
+ # "interface-configurations": {
+ # "@xmlns": "http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg",
+ # "interface-configuration": null
+ # }
+ # }
+ # },
+ # "changed": false
+ # }
+ # TASK [debug] ***********************************************************************************************************
+ # task path: /Users/amhatre/ansible-collections/playbooks/test_utils_json_to_xml.yaml:13
+ # Loading collection ansible.utils from /Users/amhatre/ansible-collections/collections/ansible_collections/ansible/utils
+ # ok: [localhost] => {
+ # "msg": "\n\n\t\n"
+ # }
+
+
+
+
+Status
+------
+
+
+Authors
+~~~~~~~
+
+- Ashwini Mhatre (@amhatre)
+
+
+.. hint::
+ Configuration entries for each entry type have a low to high priority order. For example, a variable that is lower in the list will override a variable that is higher up.
diff --git a/plugins/filter/from_xml.py b/plugins/filter/from_xml.py
new file mode 100644
index 0000000..d2f8b70
--- /dev/null
+++ b/plugins/filter/from_xml.py
@@ -0,0 +1,145 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2021 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+#
+
+"""
+The from_xml filter plugin
+"""
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+DOCUMENTATION = """
+ name: from_xml
+ author: Ashwini Mhatre (@amhatre)
+ version_added: "2.0.2"
+ short_description: Convert given XML string to native python dictionary.
+ description:
+ - This plugin converts the XML string to a native python dictionary.
+ - Using the parameters below- C(data|ansible.utils.from_xml)
+ options:
+ data:
+ description:
+ - The input XML string.
+ - This option represents the XML value that is passed to the filter plugin in pipe format.
+ - For example C(config_data|ansible.utils.from_xml), in this case C(config_data) represents this option.
+ type: str
+ required: True
+ engine:
+ description:
+ - Conversion library to use within the filter plugin.
+ type: str
+ default: xmltodict
+"""
+
+EXAMPLES = r"""
+
+#### Simple examples with out any engine. plugin will use default value as xmltodict
+
+tasks:
+ - name: convert given XML to native python dictionary
+ ansible.builtin.set_fact:
+ data: "
+
+ "
+
+ - debug:
+ msg: "{{ data|ansible.utils.from_xml }}"
+
+##TASK######
+# TASK [convert given XML to native python dictionary] *****************************************************************************************************
+# task path: /Users/amhatre/ansible-collections/playbooks/test_utils.yaml:5
+# ok: [localhost] => {
+# "ansible_facts": {
+# "data": " "
+# },
+# "changed": false
+# }
+#
+# TASK [debug] *************************************************************************************************************************
+# task path: /Users/amhatre/ansible-collections/playbooks/test_utils.yaml:13
+# Loading collection ansible.utils from /Users/amhatre/ansible-collections/collections/ansible_collections/ansible/utils
+# ok: [localhost] => {
+# "msg": {
+# "netconf-state": {
+# "@xmlns": "urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring",
+# "schemas": {
+# "schema": null
+# }
+# }
+# }
+# }
+
+#### example2 with engine=xmltodict
+
+tasks:
+ - name: convert given XML to native python dictionary
+ ansible.builtin.set_fact:
+ data: "
+
+ "
+
+ - debug:
+ msg: "{{ data|ansible.utils.from_xml('xmltodict') }}"
+
+##TASK######
+# TASK [convert given XML to native python dictionary] *****************************************************************************************************
+# task path: /Users/amhatre/ansible-collections/playbooks/test_utils.yaml:5
+# ok: [localhost] => {
+# "ansible_facts": {
+# "data": " "
+# },
+# "changed": false
+# }
+#
+# TASK [debug] *************************************************************************************************************************
+# task path: /Users/amhatre/ansible-collections/playbooks/test_utils.yaml:13
+# Loading collection ansible.utils from /Users/amhatre/ansible-collections/collections/ansible_collections/ansible/utils
+# ok: [localhost] => {
+# "msg": {
+# "netconf-state": {
+# "@xmlns": "urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring",
+# "schemas": {
+# "schema": null
+# }
+# }
+# }
+# }
+"""
+
+from ansible.errors import AnsibleFilterError
+from jinja2.filters import environmentfilter
+from ansible_collections.ansible.utils.plugins.plugin_utils.from_xml import (
+ from_xml,
+)
+from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import (
+ AnsibleArgSpecValidator,
+)
+
+
+@environmentfilter
+def _from_xml(*args, **kwargs):
+ """Convert the given data from xml to json."""
+
+ keys = ["data", "engine"]
+ data = dict(zip(keys, args[1:]))
+ data.update(kwargs)
+ aav = AnsibleArgSpecValidator(
+ data=data, schema=DOCUMENTATION, name="from_xml"
+ )
+ valid, errors, updated_data = aav.validate()
+ if not valid:
+ raise AnsibleFilterError(errors)
+ return from_xml(**updated_data)
+
+
+class FilterModule(object):
+ """ from_xml """
+
+ def filters(self):
+
+ """a mapping of filter names to functions"""
+ return {"from_xml": _from_xml}
diff --git a/plugins/filter/to_xml.py b/plugins/filter/to_xml.py
new file mode 100644
index 0000000..5e27aef
--- /dev/null
+++ b/plugins/filter/to_xml.py
@@ -0,0 +1,138 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2021 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+#
+
+
+"""
+The to_xml filter plugin
+"""
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+DOCUMENTATION = """
+ name: to_xml
+ author: Ashwini Mhatre (@amhatre)
+ version_added: "2.0.2"
+ short_description: Convert given JSON string to XML
+ description:
+ - This plugin converts the JSON string to XML.
+ - Using the parameters below- C(data|ansible.utils.to_xml)
+ options:
+ data:
+ description:
+ - The input JSON string .
+ - This option represents the JSON value that is passed to the filter plugin in pipe format.
+ - For example C(config_data|ansible.utils.to_xml), in this case C(config_data) represents this option.
+ type: dict
+ required: True
+ engine:
+ description:
+ - Conversion library to use within the filter plugin.
+ type: str
+ default: xmltodict
+"""
+
+EXAMPLES = r"""
+
+#### Simple examples with out any engine. plugin will use default value as xmltodict
+
+- name: Define JSON data
+ ansible.builtin.set_fact:
+ data:
+ "interface-configurations":
+ "@xmlns": "http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg"
+ "interface-configuration":
+- debug:
+ msg: "{{ data|ansible.utils.to_xml }}"
+
+# TASK [Define JSON data ] *************************************************************************
+# task path: /Users/amhatre/ansible-collections/playbooks/test_utils_json_to_xml.yaml:5
+# ok: [localhost] => {
+# "ansible_facts": {
+# "data": {
+# "interface-configurations": {
+# "@xmlns": "http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg",
+# "interface-configuration": null
+# }
+# }
+# },
+# "changed": false
+# }
+#
+# TASK [debug] ***********************************************************************************************************
+# task path: /Users/amhatre/ansible-collections/playbooks/test_utils_json_to_xml.yaml:13
+# Loading collection ansible.utils from /Users/amhatre/ansible-collections/collections/ansible_collections/ansible/utils
+# ok: [localhost] => {
+# "msg": "\n\n\t\n"
+# }
+
+#### example2 with engine=xmltodict
+
+- name: Define JSON data
+ ansible.builtin.set_fact:
+ data:
+ "interface-configurations":
+ "@xmlns": "http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg"
+ "interface-configuration":
+- debug:
+ msg: "{{ data|ansible.utils.to_xml('xmltodict') }}"
+
+# TASK [Define JSON data ] *************************************************************************
+# task path: /Users/amhatre/ansible-collections/playbooks/test_utils_json_to_xml.yaml:5
+# ok: [localhost] => {
+# "ansible_facts": {
+# "data": {
+# "interface-configurations": {
+# "@xmlns": "http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg",
+# "interface-configuration": null
+# }
+# }
+# },
+# "changed": false
+# }
+# TASK [debug] ***********************************************************************************************************
+# task path: /Users/amhatre/ansible-collections/playbooks/test_utils_json_to_xml.yaml:13
+# Loading collection ansible.utils from /Users/amhatre/ansible-collections/collections/ansible_collections/ansible/utils
+# ok: [localhost] => {
+# "msg": "\n\n\t\n"
+# }
+
+"""
+
+from ansible.errors import AnsibleFilterError
+from jinja2.filters import environmentfilter
+from ansible_collections.ansible.utils.plugins.plugin_utils.to_xml import (
+ to_xml,
+)
+from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import (
+ AnsibleArgSpecValidator,
+)
+
+
+@environmentfilter
+def _to_xml(*args, **kwargs):
+ """Convert the given data from json to xml."""
+ keys = ["data", "engine"]
+ data = dict(zip(keys, args[1:]))
+ data.update(kwargs)
+ aav = AnsibleArgSpecValidator(
+ data=data, schema=DOCUMENTATION, name="to_xml"
+ )
+ valid, errors, updated_data = aav.validate()
+ if not valid:
+ raise AnsibleFilterError(errors)
+ return to_xml(**updated_data)
+
+
+class FilterModule(object):
+ """ to_xml """
+
+ def filters(self):
+ """a mapping of filter names to functions"""
+ return {"to_xml": _to_xml}
diff --git a/plugins/plugin_utils/from_xml.py b/plugins/plugin_utils/from_xml.py
new file mode 100644
index 0000000..c8578b4
--- /dev/null
+++ b/plugins/plugin_utils/from_xml.py
@@ -0,0 +1,52 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2021 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+#
+
+"""
+The from_xml plugin code
+"""
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+import json
+from ansible.errors import AnsibleFilterError
+
+try:
+ import xmltodict
+
+ HAS_XMLTODICT = True
+except ImportError:
+ HAS_XMLTODICT = False
+
+
+def _raise_error(msg):
+ """Raise an error message, prepend with filter name
+ :param msg: The message
+ :type msg: str
+ :raises: AnsibleError
+ """
+ error = "Error when using plugin 'from_xml': {msg}".format(msg=msg)
+ raise AnsibleFilterError(error)
+
+
+def from_xml(data, engine):
+ """Convert data which is in xml to json"
+ :param data: The data passed in (data|from_xml(...))
+ :type data: xml
+ :param engine: Conversion library default=xml_to_dict
+ """
+ if engine == "xmltodict":
+ if not HAS_XMLTODICT:
+ _raise_error("Missing required library xmltodict")
+ try:
+ res = json.dumps(xmltodict.parse(data))
+ except Exception:
+ _raise_error("Input Xml is not valid")
+ return res
+ else:
+ error = "engine: {engine} is not supported ".format(engine=engine)
+ _raise_error(error)
diff --git a/plugins/plugin_utils/to_xml.py b/plugins/plugin_utils/to_xml.py
new file mode 100644
index 0000000..4c42827
--- /dev/null
+++ b/plugins/plugin_utils/to_xml.py
@@ -0,0 +1,53 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2021 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+#
+
+"""
+The to_xml plugin
+"""
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+from ansible.errors import AnsibleFilterError
+
+try:
+ import xmltodict
+
+ HAS_XMLTODICT = True
+except ImportError:
+ HAS_XMLTODICT = False
+
+
+def _raise_error(msg):
+ """Raise an error message, prepend with filter name
+
+ :param msg: The message
+ :type msg: str
+ :raises: AnsibleError
+ """
+ error = "Error when using plugin 'to_xml': {msg}".format(msg=msg)
+ raise AnsibleFilterError(error)
+
+
+def to_xml(data, engine):
+ """Convert data which is in json to xml"
+
+ :param data: The data passed in (data|to_xml(...))
+ :type data: xml
+ :param engine: Conversion library default=xmltodict
+ """
+ if engine == "xmltodict":
+ if not HAS_XMLTODICT:
+ _raise_error("Missing required library xmltodict")
+ try:
+ res = xmltodict.unparse(data, pretty=True)
+ except Exception:
+ _raise_error("Input json is not valid")
+ return res
+ else:
+ error = "engine: {engine} is not supported ".format(engine=engine)
+ _raise_error(error)
diff --git a/tests/integration/targets/from_xml/tasks/include/simple.yaml b/tests/integration/targets/from_xml/tasks/include/simple.yaml
new file mode 100644
index 0000000..c7135ee
--- /dev/null
+++ b/tests/integration/targets/from_xml/tasks/include/simple.yaml
@@ -0,0 +1,39 @@
+---
+- name: Setup xml and expected json
+ ansible.builtin.set_fact:
+ data: "
+
+ "
+ output: {
+ "netconf-state": {
+ "@xmlns": "urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring",
+ "schemas": {
+ "schema": null
+ }
+ }
+ }
+
+- debug:
+ msg: "{{ data|ansible.utils.from_xml() }}"
+
+- name: Integration tests with and without default engine as xmltodict and
+ assert:
+ that: "{{ output == item.test }}"
+ loop:
+ - test: "{{ data|ansible.utils.from_xml() }}"
+ - test: "{{ data|ansible.utils.from_xml('xmltodict') }}"
+
+- name: Setup invalid xml as input to ansible.utils.from_xml.
+ ansible.builtin.set_fact:
+ data: ""
+
+- name: validate input xml
+ ansible.builtin.set_fact:
+ _result: "{{ data|ansible.utils.from_xml() }}"
+ ignore_errors: true
+ register: result
+
+- assert:
+ that: "{{ msg in result.msg }}"
+ vars:
+ msg: "Error when using plugin 'from_xml': Input Xml is not valid"
diff --git a/tests/integration/targets/from_xml/tasks/main.yaml b/tests/integration/targets/from_xml/tasks/main.yaml
new file mode 100644
index 0000000..4274d75
--- /dev/null
+++ b/tests/integration/targets/from_xml/tasks/main.yaml
@@ -0,0 +1,13 @@
+---
+- name: Recursively find all test files
+ find:
+ file_type: file
+ paths: "{{ role_path }}/tasks/include"
+ recurse: true
+ use_regex: true
+ patterns:
+ - '^(?!_).+$'
+ register: found
+
+- include: "{{ item.path }}"
+ loop: "{{ found.files }}"
diff --git a/tests/integration/targets/to_xml/tasks/include/simple.yaml b/tests/integration/targets/to_xml/tasks/include/simple.yaml
new file mode 100644
index 0000000..1f7a412
--- /dev/null
+++ b/tests/integration/targets/to_xml/tasks/include/simple.yaml
@@ -0,0 +1,35 @@
+---
+- name: Setup xml and expected json
+ ansible.builtin.set_fact:
+ data:
+ "interface-configurations":
+ "@xmlns": "http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg"
+ "interface-configuration":
+ output: "\n\n\t\n"
+
+- debug:
+ msg: "{{ data|ansible.utils.to_xml() }}"
+
+- name: Integration tests with and without default engine as xmltodict and
+ assert:
+ that: "{{ output == item.test }}"
+ loop:
+ - test: "{{ data|ansible.utils.to_xml() }}"
+ - test: "{{ data|ansible.utils.to_xml('xmltodict') }}"
+
+- name: test for supported engine for to_xml filter
+ ansible.builtin.set_fact:
+ data:
+ "interface-configurations":
+ "@xmlns": "http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg"
+
+- name: validate input xml
+ ansible.builtin.set_fact:
+ _result: "{{ data|ansible.utils.to_xml('dicttoxml') }}"
+ ignore_errors: true
+ register: result
+
+- assert:
+ that: "{{ msg in result.msg }}"
+ vars:
+ msg: "Error when using plugin 'to_xml': engine: dicttoxml is not supported"
\ No newline at end of file
diff --git a/tests/integration/targets/to_xml/tasks/main.yaml b/tests/integration/targets/to_xml/tasks/main.yaml
new file mode 100644
index 0000000..4274d75
--- /dev/null
+++ b/tests/integration/targets/to_xml/tasks/main.yaml
@@ -0,0 +1,13 @@
+---
+- name: Recursively find all test files
+ find:
+ file_type: file
+ paths: "{{ role_path }}/tasks/include"
+ recurse: true
+ use_regex: true
+ patterns:
+ - '^(?!_).+$'
+ register: found
+
+- include: "{{ item.path }}"
+ loop: "{{ found.files }}"
diff --git a/tests/unit/plugins/filter/test_from_xml.py b/tests/unit/plugins/filter/test_from_xml.py
new file mode 100644
index 0000000..0ff51fe
--- /dev/null
+++ b/tests/unit/plugins/filter/test_from_xml.py
@@ -0,0 +1,49 @@
+# -*- coding: utf-8 -*-
+# Copyright 2020 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+import unittest
+from ansible.errors import AnsibleError
+from ansible_collections.ansible.utils.plugins.filter.from_xml import from_xml
+
+INVALID_DATA = ''
+
+VALID_DATA = (
+ ''
+ ""
+)
+
+OUTPUT = """{"netconf-state": \
+{"@xmlns": "urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring", "schemas": {"schema": null}}}"""
+
+
+class TestFromXml(unittest.TestCase):
+ def setUp(self):
+ pass
+
+ def test_invalid_data(self):
+ """Check passing invalid argspec"""
+
+ # missing required arguments
+ args = [INVALID_DATA, "xmltodict"]
+ kwargs = {}
+ with self.assertRaises(AnsibleError) as error:
+ from_xml(*args, **kwargs)
+ print(str(error.exception))
+ self.assertIn(
+ "Error when using plugin 'from_xml': Input Xml is not valid",
+ str(error.exception),
+ )
+
+ def test_valid_data(self):
+ """Check passing valid data as per criteria"""
+ self.maxDiff = None
+ args = [VALID_DATA, "xmltodict"]
+ result = from_xml(*args)
+ print(result)
+ self.assertEqual(result, OUTPUT)
diff --git a/tests/unit/plugins/filter/test_to_xml.py b/tests/unit/plugins/filter/test_to_xml.py
new file mode 100644
index 0000000..48cf7e8
--- /dev/null
+++ b/tests/unit/plugins/filter/test_to_xml.py
@@ -0,0 +1,50 @@
+# -*- coding: utf-8 -*-
+# Copyright 2020 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+import unittest
+from ansible.errors import AnsibleError
+from ansible_collections.ansible.utils.plugins.filter.to_xml import to_xml
+
+INVALID_DATA = ''
+
+VALID_DATA = {
+ "interface-configurations": {
+ "@xmlns": "http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg"
+ }
+}
+
+OUTPUT = """
+"""
+
+
+class TestToXml(unittest.TestCase):
+ def setUp(self):
+ pass
+
+ def test_invalid_data(self):
+ """Check passing invalid argspec"""
+
+ # missing required arguments
+ args = [INVALID_DATA, "xmltodict"]
+ kwargs = {}
+ with self.assertRaises(AnsibleError) as error:
+ to_xml(*args, **kwargs)
+ print(str(error.exception))
+ self.assertIn(
+ "Error when using plugin 'to_xml': Input json is not valid",
+ str(error.exception),
+ )
+
+ def test_valid_data(self):
+ """Check passing valid data as per criteria"""
+ self.maxDiff = None
+ args = [VALID_DATA, "xmltodict"]
+ result = to_xml(*args)
+ print(result)
+ self.assertEqual(result, OUTPUT)