ANT: replace param in set of XML files based on XML file content
I have directory with subdirs with xml files in it with different extensions.
Start of updated part
Target dir: /some/path
Target files mask: *.load
Basic filterset we use to find *.load
files under /some/path
:
<fileset dir="/some/path">
<include name="**/*.load" />
</fileset>
There could by multiple subdirs under /some/path
and multiple *.load
files also.
But we need to enhance filtering based on XML content and params described in examples, use cases below.
Examples:
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>
Input data:
Ant param: Load_name = "Load name 1"
- used to find corresponding files
Ant param: Load_param_name_replace = "enable"
Ant param: Load_param_value_replace = "false"
NB! We always search for files based on value of //load/@name
attribute (hardcoded) inside them:
<load
id="ec9ca08d11ca34b42e13c5f21578d82c"
name="Load name 2"
order="0"
enable="true"
type="LoadType.base">
Problem (based on example of files above):
We should find files where
//load/@name = $Load_name
ANT param ("Load name 1")We should change in found files (could be multiple) XML attribute declared in
$Load_param_name_replace
ANT param ("enable") value to value of ANT param$Load_param_value_replace
("false")
Expected results:
- File(s) is found: load_file1.load
NB! please pay attention that in load_file2.load we have <default-property name="Load name 1" ...
that match combination name="Load name 1"
, but we need to distinguish between this invalid case and valid one in file load_file1.load.
- In found file(s) load_file1.load XML attribute defined in
$Load_param_name_replace
("enable") ANT param under//load
node should be changed to new value defined in ANT param$Load_param_value_replace
("false")
So after ANT task the file load_file1.load should look as:
<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>
End of updated part
As you can see xml files content is spread through multiple lines - that is the tricky part for me.
We tried ANT fileset
target with containsregexp
filters where searched for multiline regex with name="load_name1"
but without success. We used multiline=true
and singleline=true
- didnt work either.
After that we tried XMLtask - but there were not enough examples of how to replace xml property in multiple .XML files based on some fileset
.
So if you could p开发者_高级运维rovide a couple of examples - it'd be greatful!
Completely revised after updated problem description :
<project>
<taskdef name="xmltask" classname="com.oopsconsultancy.xmltask.ant.XmlTask"/>
<property name="editno" value='<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>
for a quick check of the contents of a fileset simply use the builtin property ${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>
see Ant manual Properties and PropertyHelpers
Use the Ant XSLT
task to apply a transform like the following:
<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>
This makes a copy of your input, replacing the from
attribute on the tags matching name="load_name1"
. Note that this may change the indentation, but will work no matter how the input is formatted, which may not be possible with regular expressions.
精彩评论