一般的文本搜索替换操作,使用Ant中的<replace>任务就够用了,但在现代Java框架中,用户更可能需要强大的XML操作能力来修改servlet描述符、Spring配置等,就需要用到xmlTask了。
首先,在%ANT_HOME%\lib下添加xmltask.jar,下面为ant工程的目录结构图以及address.xml、address.properties、build.xml内容。
<!-- address.xml --> <?xml version="1.0" encoding="UTF-8" standalone="no"?> <a> <b> <address url="myURL">myaddress</address> </b> </a>
#address.properties address.url = localhost:8080 address.text = myaddressChange xml.location = ./source_folder
<?xml version="1.0" encoding="UTF-8"?> <project name="test" basedir="."> <taskdef name="xmltask" classname="com.oopsconsultancy.xmltask.ant.XmlTask"/> <property file="address.properties"></property> <macrodef name="replaceXML"> <attribute name="replaceAttributeValue"/> <attribute name="replaceTextValue"/> <sequential> <xmltask source="${xml.location}/address.xml" dest="${xml.location}/address.xml"> <replace path="a/b/address/@url" withText="@{replaceAttributeValue}"/> <replace path="a/b/address/text()" withText="@{replaceTextValue}"/> </xmltask> </sequential> </macrodef> <replaceXML replaceAttributeValue="${address.url}" replaceTextValue="${address.text}" /> </project>
分析:
1. <taskdef name="xmltask" classname="com.oopsconsultancy.xmltask.ant.XmlTask"/>: 使用xmltask检索xml,需要在ant_home\lib中加入xmltask.jar.
2.<macrodef name="replaceXML">...:相当于JAVA中的方法,<attribute name="replaceAttributeValue"/>相当于方法中的形式参数。
3. @{replaceAttributeValue}: 代表<macrodef>下的属性名为replaceAttributeValue的<attribute/>, 即<attribute name="replaceAttributeValue"/>。
4. @url::代表address节点下的url属性,即<address url="xxx"></address>。@...在xpath中定义就是为选取属性,这里xmltask延用xpath。
5. test(): 代表address节点下的值,即<address>xxx</address>
------------------------------------------------------------------------------------------------------------------------------
xmltask使用xpath查询,而xpath查询仅限于没有命名空间的xml(即没有xmlns属性),一旦遇到有命名空间的xml,对于xpath查询就会没有结果。
如上案例: 如果address.xml变为:
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <a xmlns="xmlNameSpace"> <b> <address url="localhost:8080">myaddress</address> </b> </a>
此时使用xpath查询a/b会返回null,即找不到节点。
解决方案: 将build.xml中a/b/address替换成/*[local-name()='a']/*[local-name()='b']/*[local-name()='address']
<?xml version="1.0" encoding="UTF-8"?> <project name="test" basedir="."> <taskdef name="xmltask" classname="com.oopsconsultancy.xmltask.ant.XmlTask"/> <property file="address.properties"></property> <macrodef name="replaceXML"> <attribute name="replaceAttributeValue"/> <attribute name="replaceTextValue"/> <sequential> <xmltask source="${xml.location}/address.xml" dest="${xml.location}/address.xml"> <replace path="/*[local-name()='a']/*[local-name()='b']/*[local-name()='address']/@url" withText="@{replaceAttributeValue}"/> <replace path="/*[local-name()='a']/*[local-name()='b']/*[local-name()='address']/text()" withText="@{replaceTextValue}"/> </xmltask> </sequential> </macrodef> <replaceXML replaceAttributeValue="${address.url}" replaceTextValue="${address.text}" /> </project>