xmlfor-loopantant-contrib

looping through an xml file combining lists in ANT


I have this xml:

<?xml version="1.0" encoding="UTF-8"?>
<projects>
  <project action="D">Project1</project>
  <project action="M">Project2</project>
</projects>

I want to use ant to loop trough the projects and execute a piece of code when the action is D, and an other piece of code when the action is not D.

My progress so far is:

<target name="test">
  <xmlproperty file="changeList.xml"/>
  <for list="${projects.project}" param="project">
    <sequential>
      <echo>The project name is @{project} Action @{project.action}</echo>
    </sequential>
  </for>
</target>

result now is:

 [echo] Project name is Project1 Action is @{project.action}
 [echo] Project name is Project2 Action is @{project.action}

I understand that I have 2 separate lists and that I'm not getting the action in the result. I need to loop trough my xml file having both property's available (project name, and the action) to pass as a parameter to the next target.


Solution

  • With ant addon task xmltask you have two possibilities.

    xmltask with nested action => run all tasks contained in the action task container for every match of the xpath expression (attribute action = D in this example) :

    <project>
     <!-- Import XMLTask -->
     <taskdef name="xmltask" classname="com.oopsconsultancy.xmltask.ant.XmlTask"/>
    
     <!-- loop over all projects with attribute action=D --> 
     <xmltask source="changeList.xml">
      <call path="//projects/project[@action='D']">
       <param path="text()" name="projname"/>
       <!-- define other params if needed .. -->
       <param value="bar" name="foo"/>
       <!-- inside action adress params with @{..} syntax ! -->
        <actions>
          <echo>Action D => @{projname}${line.separator}Param @@{foo} => @{foo}</echo>
       </actions>
      </call>
     </xmltask>
    
    </project>
    

    xmltask calling ant target for every match of the xpath expression (attribute action != D in this example).
    In this case you have to use the xmltask from a target (target main in this snippet) otherwise you'll get a BuildFailed => xmltask task at the top level must not invoke its own build file.

    <project  default="main">
     <!-- Import XMLTask -->
     <taskdef name="xmltask" classname="com.oopsconsultancy.xmltask.ant.XmlTask"/>
    
    <target name="main">
     <xmltask source="changeList.xml">
      <call path="//projects/project[@action != 'D']" target="foo">
       <param path="text()" name="projname"/>
       <param value="bar" name="foo"/>
      </call>
     </xmltask>
    </target>
    
    <!-- you have to use the propertysyntax ${...} in the called target
         for the params ! -->
    
    <target name="foo">
     <echo>
     ${projname} => Action != D
     Param $${foo} is ${foo}
     </echo>
    </target>
    
    </project>