【问题标题】:ANT: replace param in set of XML files based on XML file contentANT:根据 XML 文件内容替换 XML 文件集中的参数
【发布时间】:2011-10-31 09:20:06
【问题描述】:

我的目录包含带有不同扩展名的 xml 文件的子目录。


更新部分开始


目标目录:/some/path

目标文件掩码:*.load

我们用来在/some/path 下查找*.load 文件的基本过滤器集:

<fileset dir="/some/path">
    <include name="**/*.load" />
</fileset>

/some/path 下可以有多个子目录,也可以有多个*.load 文件。

但我们需要根据示例中描述的 XML 内容和参数来增强过滤,下面的用例。

例子:

load_file1.load:

<load 
    id="0a0740d1fc1a33a28f1397b76cae48bc"
    order="9"
    enable="true"
    name="Load name 1"
    type="LoadType.custom">
    <parent />
    <default-property name="Property2"
                      type="java.lang.Integer"
                      value="0" />
    <default-property name="Property1"
                      type="java.lang.Boolean"
                      value="false" />
</load>

load_file2.load:

<load 
      id="ec9ca08d11ca34b42e13c5f21578d82c"
      name="Load name 2"
      order="0"
      enable="true"
      type="LoadType.base">
    <parent />
    <default-property name="Load name 1"
                      type="java.lang.String"
                      value="test3" />
    <default-property name="Property2"
                      type="java.lang.Integer"
                      value="0" />
    <!-- here could be any number of other sub-properties  -->
    <date-range end-date="1/31/1900"
                     start-date="1/31/1900" />
</load>

输入数据:

Ant 参数:Load_name = "Load name 1" - 用于查找对应文件

Ant 参数:Load_param_name_replace = "enable"

蚂蚁参数:Load_param_value_replace = "false"

注意!我们总是根据文件中//load/@name 属性(硬编码)的值来搜索文件:

<load 
      id="ec9ca08d11ca34b42e13c5f21578d82c"
      name="Load name 2"
      order="0"
      enable="true"
      type="LoadType.base">

问题(基于上述文件示例):

  1. 我们应该找到文件,其中//load/@name = $Load_name ANT param ("Load name 1")

  2. 我们应该将在$Load_param_name_replace ANT param ("enable") 值中声明的找到的文件(可能是多个)XML 属性更改为 ANT 参数 $Load_param_value_replace ("假")

预期结果

  1. 找到文件:load_file1.load

注意!请注意在load_file2.load中我们有&lt;default-property name="Load name 1" ...匹配组合name="Load name 1",但是我们需要区分这种无效的情况和有效的情况文件 load_file1.load 中的一个。

  1. 在找到的文件中 load_file1.load$Load_param_name_replace ("enable") ANT 参数中定义的 //load 节点下的 XML 属性应更改为新的ANT 参数中定义的值 $Load_param_value_replace ("false")

因此,在 ANT 任务之后,文件 load_file1.load 应如下所示:

<load 
    id="0a0740d1fc1a33a28f1397b76cae48bc"
    order="9"
    enable="false"
    name="Load name 1"
    type="LoadType.custom">
    <parent />
    <default-property name="Property2"
                      type="java.lang.Integer"
                      value="0" />
    <default-property name="Property1"
                      type="java.lang.Boolean"
                      value="false" />
</load>

更新部分结束


如您所见,xml 文件的内容分布在多行中 - 这对我来说是个棘手的部分。

我们尝试了 ANT fileset 目标和 containsregexp 过滤器,其中使用 name="load_name1" 搜索 多行正则表达式,但没有成功。我们使用了multiline=truesingleline=true - 也没有用。

之后我们尝试了 XMLtask - 但是没有足够的示例说明如何根据一些 fileset 替换多个 .XML 文件中的 xml 属性。

所以如果你能提供几个例子 - 那就太好了!

【问题讨论】:

    标签: xml ant


    【解决方案1】:

    更新问题描述后完全修改:

    <project>
    <taskdef name="xmltask" classname="com.oopsconsultancy.xmltask.ant.XmlTask"/>
    
    <property name="editno" value='&lt;default-property name="Load name 1"'/>
    <property name="edityes" value='name="Load name 1"'/>
    <property name="editxpath" value="//load/@enable"/>
    <property name="editnew" value="false"/>
    
     <xmltask todir="/some/path" report="true">
      <fileset dir="/some/path">
       <include name="**/*.load"/>
        <not>
         <contains text="${editno}" casesensitive="true"/>
        </not>
        <contains text="${edityes}" casesensitive="true"/>
       </fileset>
       <replace path="${editxpath}" withText="${editnew}"/>
      </xmltask>
    </project>
    

    要快速检查文件集的内容,只需使用内置属性 ${toString:filesetid}

     <fileset dir="/some/path" id="foobar">
      <include name="**/*.load" />
      <not>
       <contains text="${editno}" casesensitive="true" />
      </not>
      <contains text="${edityes}" casesensitive="true" />
     </fileset>
    
     <echo>${toString:foobar}</echo>
    

    见 Ant 手册Properties and PropertyHelpers

    【讨论】:

    • thx 例如提供。还有一点——我们不能只验证 XML 文件中是否存在字符串“name='value'”,因为它的结构可能更棘手,我们可以有一些其他节点,而不仅仅是具有键值的根 “名称='价值'”。所以我们想确定,我们检查那个参数是为了根节点。
    • 我更新了问题中的示例。这就是我们首先在 中尝试正则表达式的原因。
    • 您更新的更棘手的示例有点令人困惑:[1.]\\load\@name 不是有效的 xpath 表达式,有效的表达式 //load/@name 将产生 load_name2 [2.]您搜索 name="whatever" 仅作为加载标签中的属性,而不是作为属性标签中的属性,对吧?
    • 或者您更新的更棘手的示例是否意味着将这两个 xml sn-ps 与一个包含两个加载标签的 xmlsn-p 结合起来,其中第二个有一个带有多个属性标签的嵌套部分?跨度>
    • 抱歉混淆 - 我更新了 xpath 并提供了评论。棘手的是属性可以嵌套到 节点。
    【解决方案2】:

    使用 Ant XSLT 任务应用如下转换:

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
        <xsl:output method="xml" indent="yes"/>
        <xsl:template match="@*|node()">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
        </xsl:template>
    
        <xsl:template match="load[@name='load_name1']">
            <xsl:copy>
                <xsl:attribute name="from">date2</xsl:attribute>
                <xsl:apply-templates select="@*[name()!='from']"/>
            </xsl:copy>
        </xsl:template>
    </xsl:stylesheet>
    

    这会复制您的输入,替换匹配name="load_name1" 的标签上的from 属性。请注意,这可能会更改缩进,但无论输入的格式如何,这都可以正常工作,这对于正则表达式可能是不可能的。

    【讨论】:

    • 谢谢例如。我们也试试看!
    • @zmische - 要将此样式表用于更棘手的示例,您必须将“应用模板”更改为 &lt;xsl:apply-templates select="@*[name()!='from']|node()"/&gt;(添加 |node() 以选择)。您还必须将谓词中的“load_name1”更改为“load_name2”。
    猜你喜欢
    • 1970-01-01
    • 2012-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多