6

This issue came up recently. I've been using ant for eons and know I could 'hack around' this issue, but thought to ask: does ant offer an elegant solution for this usecase?

Problem

When I use ant to copy xml files and "populate values" using the "filtering" attribute, how can I make it automatically escape ampersands (and other xml 'special characters')?

Context

Rather than have installers/implementers hand-edit all the various application-server specific configuration files, we have them edit a 'build.properties' files in our application's root directory. Ant copies a pre-configured 'source' version of the file to a 'target' directory whilst populating values from the properties files

1) Build.properties has this value:

JDBC_PASSWORD=smith&wesson

2) "Source" configuration file has this element:

  <local-tx-datasource>
    ...
    <password>@JDBC_PASSWORD@</password>
    ...
  </local-tx-datasource>

3) Ant copies the xml files from the 'source' configuration directory and populates the 'JDBC_PASSWORD' (among others properties) with the 'filtering' attribute:

<copy todir="${appserver.home.dir}" filtering="yes">
   <fileset dir="${appserver.conf.dir}">
      <include name="**/*.xml"/>
   </fileset>
</copy>

4) Because the property has an ampersand, the resulting 'target' xml file is invalid. (The '&' should be '&amp;')

  <local-tx-datasource>
    ...
    <password>smith&wesson</password>
    ...
  </local-tx-datasource>

Desired Result

Instead of 4, I would like this:

  <local-tx-datasource>
    ...
    <password>smith&amp;wesson</password>
    ...
  </local-tx-datasource>

Additional

I need to worry about the whole 'cast of characters', i.e. less-than, greater-than, etc., as well as the ampersand.

Thanks in advance

user331465
  • 2,984
  • 13
  • 47
  • 77

4 Answers4

0
 JDBC_PASSWORD=smith&amp;wesson

will result in :

 <local-tx-datasource>
  <password>smith&amp;wesson</password>
 </local-tx-datasource>

will get parsed as :

 <local-tx-datasource>
  <password>smith&wesson</password>
 </local-tx-datasource>


JDBC_PASSWORD=smith&amp;amp;wesson

will result in :

 <local-tx-datasource>
  <password>smith&amp;amp;wesson</password>
 </local-tx-datasource>

will get parsed as :

 <local-tx-datasource>
  <password>smith&amp;wesson</password>
 </local-tx-datasource>

Similar :

less-than : &lt;

greater-than : &gt;

Rebse
  • 10,307
  • 2
  • 38
  • 66
0

You can use the Ant-Contrib task URLEncode (Yes, it says Foreach on the heading, but that's only to throw the heat off the trail.).

You can use that to make sure that any values you're passing via <filterset/> to a tokenized XML file is correctly formatted.

You'll have to define a <taskdef/> for the Ant-Contrib tasks and include the Ant Contrib jar.

David W.
  • 105,218
  • 39
  • 216
  • 337
  • URL encoding differs from XML encoding. This is the right direction, I believe as one would need a custom encoder. – user331465 May 14 '14 at 14:28
0

If you aren't replacing an attribute value, you can always use a CDATA section instead. Ampersand, less-than, etc. within the CDATA don't need to be entity escaped.

<local-tx-datasource>
  ...
  <password><![CDATA[@JDBC_PASSWORD@]]></password>
  ...
</local-tx-datasource>
Kevin Krouse
  • 610
  • 6
  • 9
0

Putting your question together with another SO answer can get you what you want.

First, convert the property value:

<loadresource property="jdbc.password.escaped">
  <propertyresource name="jdbc.password"/>
  <filterchain>
    <tokenfilter>
      <replacestring from="&amp;" to="&amp;amp;"/><!-- note: double escape -->
    </tokenfilter>
  </filterchain>
</loadresource>

Now, use the updated property value:

<filter token="JDBC_PASSWORD" value="${jdbc.password.escaped}" />

<copy todir="${appserver.home.dir}" filtering="yes">
<fileset dir="${appserver.conf.dir}">
    <include name="**/*.xml"/>
  </fileset>
</copy>

You may have to adapt the above to suit your actual property names, etc. but that should get you going.

Christopher Schultz
  • 20,221
  • 9
  • 60
  • 77