# escaping text for inclusion in an xml template

**URL:** <https://forum.ansible.com/t/escaping-text-for-inclusion-in-an-xml-template/22972>\
**Category:** Ansible Project\
**Created:** [November 7, 2016, 12:42pm UTC](https://forum.ansible.com/t/escaping-text-for-inclusion-in-an-xml-template/22972 "2016-11-07T12:42:31Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![sebastien.barthelemy](https://avatars.discourse-cdn.com/v4/letter/s/da6949/32.png) [@sebastien.barthelemy](https://forum.ansible.com/u/sebastien.barthelemy)\
**Post date:** [November 7, 2016, 12:42pm UTC](https://forum.ansible.com/t/escaping-text-for-inclusion-in-an-xml-template/22972/1 "2016-11-07T12:42:31Z")

</div>

Hello,

I’m trying to use ansible to set up a small team buildfarm with jenkins. This is my first use of ansible.

I’m successfully using ansible 2.2’s[jenkins\_job module](http://docs.ansible.com/ansible/jenkins_job_module.html) as in:

> tasks:
> 
> - jenkins\_job:  
> name: feeds  
> config: “{{ lookup(‘file’, ‘…/jenkins/jobs/feeds/config.xml’) }}”

The job is defined by the xml, which the module caries over to jenkins using jenkins’ rest API. This is great.

Now, most of my jobs are written as [jenkins “pipeline” jobs](https://jenkins.io/doc/book/pipeline/overview/). The job xml mostly holds and wraps a [groovy script](http://www.groovy-lang.org/), like this (dumb) one:

> node (‘linux’){  
> sh ‘test -d .qi || (rm -rf .qi; mkdir -p .qi && touch .qi/stamp)’  
> checkout scm sh ‘make’  
> }

Instead of editing the job/config.xml, I would prefer to edit the job/script.groovy, and embed it in the xml.

I tried using a role to do so:

> - { role: jenkinspipelinejob, name: ‘feeds’, script: “{{ lookup(‘file’, ‘jenkins/jobs/feeds/script.groovy’) }}” }

With

$ cat roles/jenkinspipelinejob/tasks/main.yaml

> - debug: msg=“CONFIG {{ lookup(‘template’, ‘config.xml.j2’) }}”
> - jenkins\_job:  
> name: “{{ name }}”  
> config: “{{ lookup(‘template’, ‘config.xml.j2’) }}”

and

$ cat roles/jenkinspipelinejob/templates/config.xml.j2

> \<?xml version='1.0' encoding='UTF-8'?\> false true

It does work, but requires me to escape my script.groovy for xml inclusion. For instance, instead of

> ```auto
> sh 'test -d .qi || (rm -rf .qi; mkdir -p .qi **&&** touch .qi/stamp)'
> 
> ```

I need to write

> ```auto
> sh 'test -d .qi || (rm -rf .qi; mkdir -p .qi **&amp;&amp;** touch .qi/stamp)'
> 
> ```

I would like this escaping to be done automatically, how should I proceed?

I guess I could write a module, but there might be a simpler way.

I’ve looked for “xml escaping jinja filter” without any luck.

---

<div class="post-metadata">

**Author:** ![sebastien.barthelemy](https://avatars.discourse-cdn.com/v4/letter/s/da6949/32.png) [@sebastien.barthelemy](https://forum.ansible.com/u/sebastien.barthelemy)\
**Post date:** [November 30, 2016, 2:41pm UTC](https://forum.ansible.com/t/escaping-text-for-inclusion-in-an-xml-template/22972/2 "2016-11-30T14:41:16Z")

</div>

For the record, the solution was to write my own xml-escaping filter plugin.

Which is easy enough:

$ cat filter\_plugins/myfilters.py

# Make coding more python3-ish

from **future** import (absolute\_import, division, print\_function)  
**metaclass** = type  
import xml.sax.saxutils  
class FilterModule(object):  
‘’’ my jinja2 filters for ansible’‘’  
def filters(self):  
return {‘escape\_xml\_attr’ : xml.sax.saxutils.quoteattr,  
‘escape\_xml\_data’ : xml.sax.saxutils.escape}

Then, use it like this

- { role: jenkinspipelinejob, name: ‘feeds’, script: “{{ lookup(‘file’, ‘jenkins/jobs/feeds/script.groovy’) | escape\_xml\_data }}” }

---

<div class="post-metadata">

**Author:** ![asavtch](https://avatars.discourse-cdn.com/v4/letter/a/ecd19e/32.png) [@asavtch](https://forum.ansible.com/u/asavtch)\
**Post date:** [April 12, 2017, 8:19am UTC](https://forum.ansible.com/t/escaping-text-for-inclusion-in-an-xml-template/22972/3 "2017-04-12T08:19:29Z")

</div>

As far as I can see the built-in Jinja filter escape does this, so for example

- name: escape  
command: echo “{{ ‘a&b’ | escape }}”

produces

TASK [test : escape] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
changed: [localhost] =\> {“changed”: true, “cmd”: [“echo”, “a&b”], “delta”: “0:00:00.018286”, “end”: “2017-04-12 11:16:17.629886”, “rc”: 0, “start”: “2017-04-12 11:16:17.611600”, “stderr”: “”, “stdout”: “a&b”, “stdout\_lines”: [“a&b”], “warnings”: }

Alexey

---

<div class="post-metadata">

**Author:** ![sebastien.barthelemy](https://avatars.discourse-cdn.com/v4/letter/s/da6949/32.png) [@sebastien.barthelemy](https://forum.ansible.com/u/sebastien.barthelemy)\
**Post date:** [May 29, 2017, 3:47pm UTC](https://forum.ansible.com/t/escaping-text-for-inclusion-in-an-xml-template/22972/4 "2017-05-29T15:47:38Z")

</div>

> As far as I can see the built-in Jinja filter escape does this, so for example
> 
> - name: escape  
> command: echo “{{ ‘a&b’ | escape }}”

Indeed yes, thank you Alexey!

> > Then, use it like this
> > 
> > - { role: jenkinspipelinejob, name: ‘feeds’, script: “{{ lookup(‘file’, ‘jenkins/jobs/feeds/script.groovy’) | escape\_xml\_data }}” }

So this should become

- { role: jenkinspipelinejob, name: ‘feeds’, script: “{{ lookup(‘file’, ‘jenkins/jobs/feeds/script.groovy’) **| escape** }}” }

but an even better way is to keep the “script” variable content unescaped, like:

- { role: jenkinspipelinejob, name: ‘feeds’, script: “{{ lookup(‘file’, ‘jenkins/jobs/feeds/script.groovy’) }}” }

and escape it from the xml template:

$ cat roles/jenkinspipelinejob/  
templates/config.xml.j2
