Ant:如何在使用“过滤”复制 xml 文件时对属性值进行 xml 转义

Posted

技术标签:

【中文标题】Ant:如何在使用“过滤”复制 xml 文件时对属性值进行 xml 转义【英文标题】:Ant: How to xml-escape property values when copying xml files with "filtering" 【发布时间】:2014-05-12 20:56:15 【问题描述】:

这个问题最近出现了。我一直在使用 ant 并知道我可以“破解”这个问题,但想问:ant 是否为这个用例提供了一个优雅的解决方案?

问题

当我使用 ant 复制 xml 文件并使用“过滤”属性“填充值”时,如何使其自动转义 & 符号(和其他 xml '特殊字符')?

上下文

我们让安装人员/实施人员手动编辑所有各种应用程序服务器特定的配置文件,而不是让他们在应用程序的根目录中编辑“build.properties”文件。 Ant 将文件的预配置“源”版本复制到“目标”目录,同时从属性文件中填充值

1) Build.properties 有这个值:

JDBC_PASSWORD=smith&wesson

2) “源”配置文件有这个元素:

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

3) Ant 复制“源”配置目录中的 xml 文件并使用“过滤”属性填充“JDBC_PASSWORD”(以及其他属性):

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

4) 因为该属性有一个 & 符号,所以生成的“目标”xml 文件是无效的。 (“&”应该是“&”)

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

期望的结果

我想要这个而不是 4:

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

附加

我需要担心整个“字符类型”,即小于、大于等,以及与号。

提前致谢

【问题讨论】:

我也有同样的问题。你是怎么解决你的?您是否编写了自定义编码器?谢谢。 【参考方案1】:
 JDBC_PASSWORD=smith&amp;wesson

将导致:

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

将被解析为:

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

JDBC_PASSWORD=smith&amp;amp;wesson

将导致:

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

将被解析为:

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

类似:

less-than : &amp;lt;

greater-than : &amp;gt;

【讨论】:

【参考方案2】:

您可以使用 Ant-Contrib 任务 URLEncode(是的,标题上写着 Foreach,但这只是为了引发 热度 偏离轨道。)。

您可以使用它来确保您通过 &lt;filterset/&gt; 传递给标记化 XML 文件的任何值格式正确。

您必须为 Ant-Contrib 任务定义 &lt;taskdef/&gt; 并包含 Ant Contrib jar。

【讨论】:

URL 编码不同于 XML 编码。这是正确的方向,我相信人们需要一个自定义编码器。【参考方案3】:

如果您不替换属性值,则始终可以使用CDATA 部分来代替。 CDATA 中的 & 号、小于号等不需要进行实体转义。

<local-tx-datasource>
  ...
  <password><![CDATA[@JDBC_PASSWORD@]]></password>
  ...
</local-tx-datasource>

【讨论】:

【参考方案4】:

将您的问题与another SO answer 放在一起可以得到您想要的。

首先,转换属性值:

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

现在,使用更新后的属性值:

<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>

您可能需要调整上述内容以适合您的实际属性名称等,但这应该会让您继续前进。

【讨论】:

以上是关于Ant:如何在使用“过滤”复制 xml 文件时对属性值进行 xml 转义的主要内容,如果未能解决你的问题,请参考以下文章

ant过滤 - 如果未设置属性,则失败

Android中用ANT打包如何将内容复制到AndroidManifest文件中

如何使用ant在war文件中创建和复制模板

米家插件怎么改顺序

ANT:如何从 Java 调用 ANT build.xml 文件

Ant默认配置文件不是build.xml该如何编写命令进行编译打包