This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Ant string functions?
I am modifying a wxi file as part of a wix install and updating a guid. As part of the "pedantic" warning setting if a guid is in lowercase the wix build fails.
How can I convert the guid to an uppercase string in ant?
EDIT: The Ant string functions thread is definitly the way to go - Ant string functions?
You may use the Ant Plugin Flaka, no need to use a scripting language =
<project name="demo" xmlns:fl="antlib:it.haefelinger.flaka">
<fl:install-property-handler />
<property name="guid" value="a7655b5e-f074-4df1-9636-391aa234f4f4"/>
<!-- simple echo -->
<echo>
#{'${guid}'.toupper}
</echo>
<!-- create new property for further processing -->
<fl:let>
guidtoupper := '#{'${guid}'.toupper}'
</fl:let>
<echo> $${guid} before => ${guid}</echo>
<!-- overwrite existing property -->
<fl:let>
guid ::= '#{'${guid}'.toupper}'
</fl:let>
<echo> $${guid} after => ${guid}</echo>
</project>
output :
[echo] A7655B5E-F074-4DF1-9636-391AA234F4F4
[echo]
[echo] ${guid} before => a7655b5e-f074-4df1-9636-391aa234f4f4
[echo] ${guid} after => A7655B5E-F074-4DF1-9636-391AA234F4F4
Related
I have a requirement to get a substring out of a string in to ant property.
Example string:
1=tibunit-1.4.2.projlib\=
I want to extract the part before .projlib\= and after the first =.
The result should be:
tibunit-1.4.2
Any ideas?
Use script task with builtin javascript engine (JDK >= 1.6.0_06) and something like :
if you need substring 'tibunit-1.4.2.projlib\' :
<project>
<property name="foo" value="1=tibunit-1.4.2.projlib\="/>
<script language="javascript">
// simple echo
println(project.getProperty('foo').split('=')[1]);
// create property for later use
project.setProperty('foobar', project.getProperty('foo').split('=')[1]);
</script>
<echo>$${foobar} => ${foobar}</echo>
</project>
output :
[script] tibunit-1.4.2.projlib\
[echo] ${foobar} => tibunit-1.4.2.projlib\
if you need substring 'tibunit-1.4.2' :
<project>
<property name="foo" value="1=tibunit-1.4.2.projlib\="/>
<script language="javascript">
s = project.getProperty('foo').split('=')[1];
// simple echo
println(s.substring(0, s.lastIndexOf(".")));
// create property for later use
project.setProperty('foobar', s.substring(0, s.lastIndexOf(".")));
</script>
<echo>$${foobar} => ${foobar}</echo>
</project>
output:
[script] tibunit-1.4.2
[echo] ${foobar} => tibunit-1.4.2
For reuse put that stuff into a macrodef.
Use the ant-contrib task PropertyRegex :
<propertyregex property="tibunit.version"
input="1=tibunit-1.4.2.projlib\="
regexp="1=(tibnunit-[0-9]+.[0-9]+.[0-9]+).+"
select="\1"
casesensitive="false" />
Can the token itself be parsed from other values from within the property file?
Is it possible to evaluate the token key, without hardcoding the token? Can the token itself be parsed from other values from within the property file?
For example, if the properties file has the following tokens (test.properties):
module_no = 01
module_code = bb
title_01_aa = ABC
title_02_aa = DEF
title_03_aa = GHI
title_01_bb = JKL
title_02_bb = MNO
title_03_bb = PQR
Contents of build.xml
<?xml version="1.0" encoding="utf-8"?>
<project default="repl">
<property file="test.properties" />
<target name="repl">
<replace file="test.txt" token="module_title" value="title_${module_no}_${module_code}" />
</target>
</project>
Sample content with text:
Welcome to module_title.
The replace task will result in:
Welcome to title_01_bb.
How to achieve this instead?
Welcome to JKL.
This might be very basic, but please do guide me in the right direction. Thank you.
Nested property expansion does not work by default in Ant as described in the documentation:
Nesting of Braces
In its default configuration Ant will not try to balance braces in property expansions, it will only consume the text up to the first closing brace when creating a property name. I.e. when expanding something like ${a${b}} it will be translated into two parts:
the expansion of property a${b - likely nothing useful.
the literal text } resulting from the second closing brace
This means you can't use easily expand properties whose names are given by properties, but there are some workarounds for older versions of Ant. With Ant 1.8.0 and the the props Antlib you can configure Ant to use the NestedPropertyExpander defined there if you need such a feature.
If you check the workarounds link, one solution is to use a macrodef to copy the property:
<property file="test.properties" />
<target name="repl">
<gettitleprop name="titleprop" moduleno="${module_no}" modulecode="${module_code}" />
<replace file="test.txt" token="module_title" value="${titleprop}" />
</target>
<macrodef name="gettitleprop">
<attribute name="name"/>
<attribute name="moduleno"/>
<attribute name="modulecode"/>
<sequential>
<property name="#{name}" value="${title_#{moduleno}_#{modulecode}}"/>
</sequential>
</macrodef>
I have a properties file:
custom.properties
the content of this properties file is:
id=sf2j2345kkklljhlaasfsdfafsf543
name=SOME_NAME
The value of id is a long random string.
I want to make an Ant script to replace/over-write the value of id to another one, I tried with Ant <replace> syntax:
<target name="change-id">
<replace file="custom.properties" token="id" value="aaa" />
</target>
I run ant change-id , the content of the properties file becomes:
aaa=sf2j2345kkklljhlaasfsdfafsf543
name=SOME_NAME
That's the key "id" get replaced instead of its value. But I need to replace the value to "aaa" , how to achieve this in Ant?
Please do not recommend me to set token to id's random value, because that value is random generated and put there. I only want to over-write the random value of "id" by Ant script, how to achieve this?.
You can do it using replaceregexp task. Try to do it like in this example
conf.ini (utf-8)
aaa=sf2j2345kkklljhlaasfsdfafsf543
name=SOME_NAME
build.xml
<project name="regexp.replace.test" default="test">
<target name="test">
<replaceregexp file="conf.ini" match="^aaa=.*" replace="aaa=newId" encoding="UTF-8" />
</target>
</project>
I don't know exactly if this regular expression is correct but this is the way you can do it.
I need to retrieve some values from an HTML file. I need to use Ant so I can use these values in other parts of my script.
Can this even be achieved in Ant?
As stated in the other answers you can't do this in "pure" XML. You need to embed a programming language. My personal favourite is Groovy, it's integration with ANT is excellent.
Here's a sample which retrieves the logo URL, from the groovy homepage:
parse:
print:
[echo]
[echo] Logo URL: http://groovy.codehaus.org/images/groovy-logo-medium.png
[echo]
build.xml
Build uses the ivy plug-in to retrieve all 3rd party dependencies.
<project name="demo" default="print" xmlns:ivy="antlib:org.apache.ivy.ant">
<target name="resolve">
<ivy:resolve/>
<ivy:cachepath pathid="build.path" conf="build"/>
</target>
<target name="parse" depends="resolve">
<taskdef name="groovy" classname="org.codehaus.groovy.ant.Groovy" classpathref="build.path"/>
<groovy>
import org.htmlcleaner.*
def address = 'http://groovy.codehaus.org/'
// Clean any messy HTML
def cleaner = new HtmlCleaner()
def node = cleaner.clean(address.toURL())
// Convert from HTML to XML
def props = cleaner.getProperties()
def serializer = new SimpleXmlSerializer(props)
def xml = serializer.getXmlAsString(node)
// Parse the XML into a document we can work with
def page = new XmlSlurper(false,false).parseText(xml)
// Retrieve the logo URL
properties["logo"] = page.body.div[0].div[1].div[0].div[0].div[0].img.#src
</groovy>
</target>
<target name="print" depends="parse">
<echo>
Logo URL: ${logo}
</echo>
</target>
</project>
The parsing logic is pure groovy programming. I love the way you can easily walk the page's DOM tree:
// Retrieve the logo URL
properties["logo"] = page.body.div[0].div[1].div[0].div[0].div[0].img.#src
ivy.xml
Ivy is similar to Maven. It manages your dependencies on 3rd party software. Here it's being used to pull down groovy and the HTMLCleaner library the groovy logic is using:
<ivy-module version="2.0">
<info organisation="org.myspotontheweb" module="demo"/>
<configurations defaultconfmapping="build->default">
<conf name="build" description="ANT tasks"/>
</configurations>
<dependencies>
<dependency org="org.codehaus.groovy" name="groovy-all" rev="1.8.2"/>
<dependency org="net.sourceforge.htmlcleaner" name="htmlcleaner" rev="2.2"/>
</dependencies>
</ivy-module>
How to install ivy
Ivy is a standard ANT plugin. Download it's jar and place it in one of the following directories:
$HOME/.ant/lib
$ANT_HOME/lib
I don't know why the ANT project doesn't ship with ivy.
Yes this is very possible.
Note that in order to use this solution you will need to set your JAVA_HOME variable to JRE 1.6 or later.
<project name="extractElement" default="test">
<!--Extract element from html file-->
<scriptdef name="findelement" language="javascript">
<attribute name="tag" />
<attribute name="file" />
<attribute name="property" />
<![CDATA[
var tag = attributes.get("tag");
var file = attributes.get("file");
var regex = "<" + tag + "[^>]*>(.*?)</" + tag + ">";
var patt = new RegExp(regex,"g");
project.setProperty(attributes.get("property"), patt.exec(file));
]]>
</scriptdef>
<!--Only available target...-->
<target name="test">
<!--Load html file into property-->
<loadfile srcFile="D:\Tools\CruiseControl\Build\artifacts\RECO\20110831100942\RECO_merged_report.html" property="html.file"/>
<!--Find element with specific tag and save it to property element-->
<findelement tag="title" file="${html.file}" property="element"/>
<echo message="File : ${html.file}"/>
<echo message="Title : ${element}"/>
</target>
</project>
Output : [echo] Title : <title>Test Report</title>,Test Report
As I don't know what exactly variables you were looking for this particular solution will find all elements that you specify in the tag attribute. Of course you could modify the regex to suit your own specific needs.
Also this is pure build.xml ant with no external dependencies whatsoever.
Sure, but you have to write your own task for it. Visit http://ant.apache.org/manual/develop.html#writingowntask for more information about writing own tasks for Ant. In your Ant task you may parse your HTML file as needed.
I claim, that it is not directly possible with "pure" XML (build.xml) to achieve what you want.
Take a look at the (http://ant.apache.org/manual/Tasks/xmlproperty.html) task and see if it'll work for you. It's pretty straight forward:
<xmlProperty file="${html.file}"
prefix="html."/>
After all, HTML is just a subset of XML. I've used it before to do this very task. No need to write your own task or script.
I'm trying to debug a macrodef in Ant. I cannot seem to find a way to display the contents of a parameter sent as an element.
<project name='debug.macrodef'>
<macrodef name='def.to.debug'>
<attribute name='attr' />
<element name='elem' />
<sequential>
<echo>Sure, the attribute is easy to debug: #{attr}</echo>
<echo>The element works only in restricted cases: <elem /> </echo>
<!-- This works only if <elem /> doesn't contain anything but a
textnode, if there were any elements in there echo would
complain it doesn't understand them. -->
</sequential>
</macrodef>
<target name='works'>
<def.to.debug attr='contents of attribute'>
<elem>contents of elem</elem>
</def.to.debug>
</target>
<target name='does.not.work'>
<def.to.debug attr='contents of attribute'>
<elem><sub.elem>contents of sub.elem</sub.elem></elem>
</def.to.debug>
</target>
</project>
Example run:
$ ant works
...
works:
[echo] Sure, the attribute is easy to debug: contents of attribute
[echo] The element works only in restricted cases: contents of elem
...
$ ant does.not.work
...
does.not.work:
[echo] Sure, the attribute is easy to debug: contents of attribute
BUILD FAILED
.../build.xml:21: The following error occurred while executing this line:
.../build.xml:7: echo doesn't support the nested "sub.elem" element.
...
So I guess I need either a way to get the contents of the <elem /> into a property somehow (some extended macrodef implementation might have that), or I need a sort of <element-echo><elem /></element-echo> that could print out whatever XML tree you put inside. Does anyone know of an implementation of either of these? Any third, unanticipated way of getting the data out is of course also welcome.
How about the echoxml task?
In your example build file replacing the line
<echo>The element works only in restricted cases: <elem /> </echo>
with
<echoxml><elem /></echoxml>
results in
$ ant does.not.work
...
does.not.work:
[echo] Sure, the attribute is easy to debug: contents of attribute
<?xml version="1.0" encoding="UTF-8"?>
<sub.elem>contents of sub.elem</sub.elem>
Perhaps the XML declaration is not wanted though. You might use the echoxml file attribute to put the output to a temporary file, then read that file and remove the declaration, or reformat the information as you see fit.
edit
On reflection, you can probably get close to what you describe, for example this sequential body of your macrodef
<sequential>
<echo>Sure, the attribute is easy to debug: #{attr}</echo>
<echoxml file="macro_elem.xml"><elem /></echoxml>
<loadfile property="elem" srcFile="macro_elem.xml">
<filterchain>
<LineContainsRegexp negate="yes">
<regexp pattern=".xml version=.1.0. encoding=.UTF-8..." />
</LineContainsRegexp>
</filterchain>
</loadfile>
<echo message="${elem}" />
</sequential>
gives
$ ant does.not.work
...
does.not.work:
[echo] Sure, the attribute is easy to debug: contents of attribute
[echo] <sub.elem>contents of sub.elem</sub.elem>