ant-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Hiroaki Nakamura" <hnaka...@v003.vaio.ne.jp>
Subject Re: [Proposal] ReadXML, XPathSingle, XPathForEach Task
Date Sat, 01 Feb 2003 10:39:52 GMT
Hi, folks.

Is anybody interested in these tasks?
Or did I do something wrong?
Please someone give me some comments?

--
)Hiroaki Nakamura) hnakamur@v003.vaio.ne.jp

----- Original Message ----- 
From: "Hiroaki Nakamura" <hnakamur@v003.vaio.ne.jp>
To: "Ant Developers List" <ant-dev@jakarta.apache.org>
Sent: Thursday, January 30, 2003 12:10 PM
Subject: [Proposal] ReadXML, XPathSingle, XPathForEach Task


> Kirk,
> Sorry for my very late response, but shortly after using VPP I came to like
> your idea using XPath. However, I don't need jakarta-digester here personally,
> I think just DOM and XPath are enough. For XPath, Xalan's XPathAPI is very handy.
> 
> Kirk, Christopher wrote:
> > 1) I have found the real power of Ant+Velocity comes out when Ant is used to
> > load an XML file (that forms the velocity context) and then a set of XPath
> > mappers that specify when Velocity is to be fired and what file is to be
> > generated.
> 
> So I made a sample program for proof of concept. Please see an attached patch.
> - First you provide your configuration as a separate xml file,
>   like config.xml in the patch.
> - You read the xml with <readxml>, and add the DOM node (newly defined
>   <domnode> datatype) to a reference in the ant project (see "init_config" target).
> - You can reference a node dom value and set to a property by using
>   <xpathsingle> with property attribute (see "xpathsingle_example1" target).
> - You can add a reference by using <xpathsingle> with node attribute
>    (see "xpathsingle_example2" target).
> - You can loop on nodes by using <xpathforeach> with node attribute
>    (see "xpathforeach_example1" target).
> - You can loop on node values by using <xpathforeach> with property attribute
>    (see "xpathforeach_example2" target).
> - "xpathforeach_example3" target is a real life example. It loops on nodes and
>   for each loop it calls a task using VPP which references the node value by
>   using sample.velocity.XPathTool.
> 
>    <target name="xpathforeach_example3">
>      <xpathforeach node="ear" context="dom1" path="build_config/ears/ear">
>        <xpathsingle context="ear" path="@name" property="destdir"/>
>        <antcall target="vpp" inheritRefs="true">
>          <param name="srcdir" value="."/>
>          <param name="destdir" value="${destdir}"/>
>        </antcall>
>      </xpathforeach>
>    </target>
> 
> - Also, please see "wrong_example1" and "wrong_example2". It prints the
>   same value as the first iteration for each iteration. So you must use
>   <antcall> in the loopbody like "xpathforeach_example1".
> 
> Usage:
> (1) run ant
> (2) run ant test
> You must run (2) separately since (1) puts a jar file to ant lib directory.
> 
> So, what do you all people think about these tasks? I think these are good
> and welcome your feedbacks.
> 
> --
> )Hiroaki Nakamura) hnakamur@v003.vaio.ne.jp
> 
> 
> diff -ruN XPathForEachSample.orig/application.xml.vpp XPathForEachSample/application.xml.vpp
> --- XPathForEachSample.orig/application.xml.vpp 1970-01-01 09:00:00.000000000 +0900
> +++ XPathForEachSample/application.xml.vpp 2003-01-30 09:52:20.000000000 +0900
> @@ -0,0 +1,23 @@
> +<?xml version="1.0" encoding="UTF-8"?>
> +#set($ear = $project.getReference('ear').getNode())
> +
> +<!DOCTYPE application PUBLIC
> +    "-//Sun Microsystems, Inc.//DTD J2EE Application 1.3//EN"
> +    "http://java.sun.com/dtd/application_1_3.dtd">
> +
> +<application>
> +  <display-name>$xp.value($ear, '@name')</display-name>
> +#foreach($w in $xp.list($ear, 'war'))
> +  <module>
> +    <web>
> +      <web-uri>$xp.value($w, '@filename')</web-uri>
> +      <context-root>$xp.value($w, '@context_root')</context-root>
> +    </web>
> +  </module>
> +#end
> +#foreach($e in $xp.list($ear, 'ejb'))
> +  <module>
> +    <ejb>$xp.value($e, '@filename')</ejb>
> +  </module>
> +#end
> +</application>
> diff -ruN XPathForEachSample.orig/build.xml XPathForEachSample/build.xml
> --- XPathForEachSample.orig/build.xml 1970-01-01 09:00:00.000000000 +0900
> +++ XPathForEachSample/build.xml 2003-01-30 11:30:06.000000000 +0900
> @@ -0,0 +1,134 @@
> +<?xml version="1.0" encoding="UTF-8"?>
> +
> +<project name="XPathForEachSample" default="deploy" basedir=".">
> +  <property name="ANT_HOME" value="C:/jakarta-ant-1.5.1"/>
> +
> +  <target name="compile">
> +    <mkdir dir="classes"/>
> +    <javac srcdir="src"
> +           destdir="classes"
> +           debug="true"
> +           deprecation="true"
> +           optimize="true" >
> +      <classpath>
> +        <pathelement location="${ANT_HOME}/lib/ant.jar"/>
> +      </classpath>
> +    </javac>
> +  </target>
> +
> +  <target name="build" depends="compile">
> +    <jar jarfile="mysample.jar" basedir="classes"/>
> +  </target>
> +
> +  <target name="deploy" depends="build">
> +    <copy file="mysample.jar" todir="${ANT_HOME}/lib"/>
> +  </target>
> +
> +  <target name="init_config">
> +    <typedef name="domnode"      classname="sample.ant.types.DOMNode"/>
> +
> +    <taskdef name="readxml"      classname="sample.ant.taskdefs.ReadXML"/>
> +    <taskdef name="xpathsingle"  classname="sample.ant.taskdefs.XPathSingle"/>
> +    <taskdef name="xpathforeach" classname="sample.ant.taskdefs.XPathForEach"/>
> +
> +    <readxml domid="dom1" file="config.xml"/>
> +  </target>
> +
> +  <target name="test" depends="init_config">
> +    <antcall target="xpathsingle_example1" inheritRefs="true"/>
> +    <antcall target="xpathsingle_example2" inheritRefs="true"/>
> +    <antcall target="xpathforeach_example1" inheritRefs="true"/>
> +    <antcall target="xpathforeach_example2" inheritRefs="true"/>
> +    <antcall target="xpathforeach_example3" inheritRefs="true"/>
> +    <antcall target="wrong_example1" inheritRefs="true"/>
> +    <antcall target="wrong_example2" inheritRefs="true"/>
> +  </target>
> +
> +  <target name="xpathsingle_example1">
> +    <xpathsingle context="dom1" path="build_config/ears/ear[1]/@name"
> +        property="earname"/>
> +    <echo message="earname=${earname}"/>
> +  </target>
> +
> +  <target name="xpathsingle_example2">
> +    <xpathsingle context="dom1" path="build_config/ears/ear[2]" node="ear"/>
> +    <xpathsingle context="ear" path="@name" property="earname"/>
> +    <echo message="earname=${earname}"/>
> +  </target>
> +
> +  <target name="xpathforeach_example1">
> +    <xpathforeach node="ear" context="dom1" path="build_config/ears/ear">
> +      <xpathsingle context="ear" path="@name" property="earname"/>
> +      <antcall target="echo_earname"/>
> +    </xpathforeach>
> +  </target>
> +
> +  <target name="echo_earname">
> +    <echo message="earname=${earname}"/>
> +  </target>
> +
> +  <target name="xpathforeach_example2">
> +    <xpathforeach property="earname"
> +        context="dom1" path="build_config/ears/ear/@name">
> +      <antcall target="echo_earname"/>
> +    </xpathforeach>
> +  </target>
> +
> +  <target name="xpathforeach_example3">
> +    <xpathforeach node="ear" context="dom1" path="build_config/ears/ear">
> +      <xpathsingle context="ear" path="@name" property="destdir"/>
> +      <antcall target="vpp" inheritRefs="true">
> +        <param name="srcdir" value="."/>
> +        <param name="destdir" value="${destdir}"/>
> +      </antcall>
> +    </xpathforeach>
> +  </target>
> +
> +  <target name="wrong_example1">
> +    <xpathforeach node="ear" context="dom1" path="build_config/ears/ear">
> +      <xpathsingle context="ear" path="@name" property="earname"/>
> +      <echo message="unchanged_over_iteration -> ${earname}"/>
> +    </xpathforeach>
> +  </target>
> +
> +  <target name="wrong_example2">
> +   <xpathforeach property="earname"
> +       context="dom1" path="build_config/ears/ear/@name">
> +     <echo message="unchanged_over_iteration -> ${earname}"/>
> +   </xpathforeach>
> +  </target>
> +
> +  <target name="vpp">
> +    <mkdir dir="${destdir}"
> +        description="Creates destdir even if srcdir doesn't exist."/>
> +    <available property="vpp_srcdir_exists" file="${srcdir}" type="dir"/>
> +    <antcall target="vpp_helper" inheritRefs="true"/>
> +  </target>
> +  <target name="vpp_helper" if="vpp_srcdir_exists">
> +    <mkdir dir="${destdir}"/>
> +    <copy todir="${destdir}">
> +      <fileset dir="${srcdir}" includes="**/*.vpp"/>
> +      <mapper type="glob" from="*.vpp" to="*"/>
> +      <filterchain>
> +        <filterreader classname="foundrylogic.vpp.VPPFilter">
> +          <param type="engine" name="runtime.log" value="vpp.log"/>
> +          <param type="class" name="xp" value="sample.velocity.XPathTool"/>
> +        </filterreader>
> +      </filterchain>
> +    </copy>
> +  </target>
> +
> +  <target name="clean" depends="init_config">
> +    <xpathforeach property="earname"
> +        context="dom1" path="build_config/ears/ear/@name">
> +      <antcall target="delete_ear_dir"/>
> +    </xpathforeach>
> +    <delete file="vpp.log"/>
> +    <delete file="mysample.jar"/>
> +    <delete dir="classes"/>
> +  </target>
> +
> +  <target name="delete_ear_dir">
> +    <delete dir="${earname}"/>
> +  </target>
> +</project>
> diff -ruN XPathForEachSample.orig/config.xml XPathForEachSample/config.xml
> --- XPathForEachSample.orig/config.xml 1970-01-01 09:00:00.000000000 +0900
> +++ XPathForEachSample/config.xml 2003-01-30 07:18:21.000000000 +0900
> @@ -0,0 +1,20 @@
> +<?xml version="1.0" encoding="UTF-8"?>
> +
> +<build_config>
> +  <ears>
> +    <ear name="ear1" filename="ear1.ear">
> +      <war name="war1" filename="war1.war" context_root="/war1"/>
> +      <war name="war2" filename="war2.war" context_root="/war2"/>
> +      <ejb name="ejb1" filename="ejb1.jar"/>
> +      <ejb name="ejb2" filename="ejb2.jar"/>
> +      <ejb name="ejb3" filename="ejb3.jar"/>
> +    </ear>
> +    <ear name="ear2" filename="ear2.ear">
> +      <war name="war2" filename="war2.war" context_root="/war2"/>
> +      <war name="war3" filename="war3.war" context_root="/war3"/>
> +      <ejb name="ejb1" filename="ejb1.jar"/>
> +      <ejb name="ejb2" filename="ejb2.jar"/>
> +      <ejb name="ejb4" filename="ejb4.jar"/>
> +    </ear>
> +  </ears>
> +</build_config>
> diff -ruN XPathForEachSample.orig/src/sample/ant/taskdefs/ReadXML.java XPathForEachSample/src/sample/ant/taskdefs/ReadXML.java
> --- XPathForEachSample.orig/src/sample/ant/taskdefs/ReadXML.java 1970-01-01 09:00:00.000000000
+0900
> +++ XPathForEachSample/src/sample/ant/taskdefs/ReadXML.java 2003-01-30 11:07:39.000000000
+0900
> @@ -0,0 +1,59 @@
> +package sample.ant.taskdefs;
> +
> +import java.io.File;
> +import java.io.IOException;
> +
> +import javax.xml.parsers.DocumentBuilder;
> +import javax.xml.parsers.DocumentBuilderFactory;
> +import javax.xml.parsers.ParserConfigurationException;
> +
> +import org.apache.tools.ant.BuildException;
> +import org.apache.tools.ant.Project;
> +import org.apache.tools.ant.Task;
> +import sample.ant.types.DOMNode;
> +import org.w3c.dom.Document;
> +import org.xml.sax.SAXException;
> +
> +/**
> + *
> + */
> +public class ReadXML extends Task {
> +    protected String domID;
> +    protected File file;
> +
> +    public void setDomID(String domID) {
> +        this.domID = domID;
> +    }
> +
> +    public void setFile(File file) {
> +        this.file = file;
> +    }
> +
> +    /**
> +     * @see org.apache.tools.ant.Task#execute()
> +     */
> +    public void execute() throws BuildException {
> +        Project prj = getProject();
> +        DOMNode dom = (DOMNode)prj.createDataType("domnode");
> +        Document doc = parseXML(file);
> +        dom.setNode(doc);
> +        prj.addReference(domID, dom);
> +    }
> +
> +    protected Document parseXML(File file)  throws BuildException {
> +        Document doc = null;
> +        try {
> +            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
> +            DocumentBuilder db = dbf.newDocumentBuilder();
> +            doc = db.parse(file);
> +        } catch (ParserConfigurationException ex) {
> +            throw new BuildException(ex);
> +        } catch (IOException ex) {
> +            throw new BuildException(ex);
> +        } catch (SAXException ex) {
> +            throw new BuildException(ex);
> +        }
> +        return doc;
> +    }
> +
> +}
> diff -ruN XPathForEachSample.orig/src/sample/ant/taskdefs/XPathForEach.java
> XPathForEachSample/src/sample/ant/taskdefs/XPathForEach.java
> --- XPathForEachSample.orig/src/sample/ant/taskdefs/XPathForEach.java 1970-01-01 09:00:00.000000000
+0900
> +++ XPathForEachSample/src/sample/ant/taskdefs/XPathForEach.java 2003-01-30 10:49:20.000000000
+0900
> @@ -0,0 +1,145 @@
> +package sample.ant.taskdefs;
> +
> +import java.util.Enumeration;
> +import java.util.Vector;
> +
> +import org.apache.tools.ant.BuildException;
> +import org.apache.tools.ant.Project;
> +import org.apache.tools.ant.Task;
> +import org.apache.tools.ant.TaskContainer;
> +import sample.ant.types.DOMNode;
> +import sample.ant.util.XPathUtils;
> +import org.w3c.dom.Node;
> +import org.w3c.dom.traversal.NodeIterator;
> +
> +/**
> + *
> + */
> +public class XPathForEach extends Task implements TaskContainer {
> +    protected String node;
> +    protected String property;
> +    protected String context;
> +    protected String path;
> +
> +    /** Optional Vector holding the nested tasks */
> +    private Vector nestedTasks = new Vector();
> +
> +    /**
> +     * Sets the node.
> +     * @param node The node to set
> +     */
> +    public void setNode(String node) {
> +        this.node = node;
> +    }
> +
> +    /**
> +     * Sets the property.
> +     * @param property The property to set
> +     */
> +    public void setProperty(String property) {
> +        this.property = property;
> +    }
> +
> +    /**
> +     * Sets the context.
> +     * @param context The context to set
> +     */
> +    public void setContext(String context) {
> +        this.context = context;
> +    }
> +
> +    /**
> +     * Sets the path.
> +     * @param path The path to set
> +     */
> +    public void setPath(String path) {
> +        this.path = path;
> +    }
> +
> +    /**
> +     * Override {@link org.apache.tools.ant.Task#maybeConfigure
> +     * maybeConfigure} in a way that leaves the nested tasks
> +     * unconfigured until they get executed.
> +     *
> +     * @since Ant 1.5
> +     */
> +    public void maybeConfigure() throws BuildException {
> +        if (isInvalid()) {
> +            super.maybeConfigure();
> +        } else {
> +            getRuntimeConfigurableWrapper().maybeConfigure(getProject(), false);
> +        }
> +    }
> +
> +    /**
> +     * Add a nested task to Sequential.
> +     * <p>
> +     * @param nestedTask  Nested task to execute Sequential
> +     * <p>
> +     */
> +    public void addTask(Task nestedTask) {
> +        nestedTasks.addElement(nestedTask);
> +    }
> +
> +    /**
> +     * Execute all nestedTasks.
> +     */
> +    public void execute() throws BuildException {
> +        if (context == null) {
> +            throw new BuildException("context node must be set");
> +        }
> +        if (path == null) {
> +            throw new BuildException("path must be set");
> +        }
> +        if (property == null && node == null) {
> +            throw new BuildException("one of property or node must be set");
> +        }
> +        if (property != null && node != null) {
> +            throw new BuildException("property and node must not be both set");
> +        }
> +
> +        Project prj = getProject();
> +        Object savedNodeRef = null;
> +        if (node != null) {
> +            savedNodeRef = prj.getReference(node);
> +        }
> +        try {
> +            DOMNode contextDOMNode = (DOMNode)prj.getReference(context);
> +            if (contextDOMNode == null) {
> +                throw new BuildException("context node [" + context + "] does not exist.");
> +            }
> +            Node contextNode = contextDOMNode.getNode();
> +
> +            NodeIterator it = XPathUtils.selectNodeIterator(contextNode, path);
> +            Node n = null;
> +            while ((n = it.nextNode()) != null) {
> +                if (node != null) {
> +                    addNewDOMNodeReference(prj, node, n);
> +                } else if (property != null) {
> +                    prj.setProperty(property, n.getNodeValue());
> +                }
> +
> +                performNestedTasks();
> +            }
> +        } finally {
> +            if (savedNodeRef != null) {
> +                prj.addReference(node, savedNodeRef);
> +            }
> +        }
> +    }
> +
> +    protected DOMNode addNewDOMNodeReference(Project prj, String id, Node n) {
> +        DOMNode nDomNode = (DOMNode)prj.createDataType("domnode");
> +        nDomNode.setNode(n);
> +        prj.addReference(id, nDomNode);
> +        return nDomNode;
> +    }
> +
> +    protected void performNestedTasks()
> +        throws BuildException {
> +        for (Enumeration e = nestedTasks.elements(); e.hasMoreElements();) {
> +            Task nestedTask = (Task) e.nextElement();
> +            nestedTask.perform();
> +        }
> +    }
> +}
> diff -ruN XPathForEachSample.orig/src/sample/ant/taskdefs/XPathSingle.java
> XPathForEachSample/src/sample/ant/taskdefs/XPathSingle.java
> --- XPathForEachSample.orig/src/sample/ant/taskdefs/XPathSingle.java 1970-01-01 09:00:00.000000000
+0900
> +++ XPathForEachSample/src/sample/ant/taskdefs/XPathSingle.java 2003-01-30 10:49:20.000000000
+0900
> @@ -0,0 +1,92 @@
> +package sample.ant.taskdefs;
> +
> +import org.apache.tools.ant.BuildException;
> +import org.apache.tools.ant.Project;
> +import org.apache.tools.ant.Task;
> +import sample.ant.types.DOMNode;
> +import sample.ant.util.XPathUtils;
> +import org.w3c.dom.Node;
> +
> +/**
> + *
> + */
> +public class XPathSingle extends Task {
> +    protected String node;
> +    protected String property;
> +    protected String context;
> +    protected String path;
> +
> +    /**
> +     * Sets the node.
> +     * @param node The node to set
> +     */
> +    public void setNode(String node) {
> +        this.node = node;
> +    }
> +
> +    /**
> +     * Sets the property.
> +     * @param property The property to set
> +     */
> +    public void setProperty(String property) {
> +        this.property = property;
> +    }
> +
> +    /**
> +     * Sets the context.
> +     * @param context The context to set
> +     */
> +    public void setContext(String context) {
> +        this.context = context;
> +    }
> +
> +    /**
> +     * Sets the path.
> +     * @param path The path to set
> +     */
> +    public void setPath(String path) {
> +        this.path = path;
> +    }
> +
> +    /**
> +     * @see org.apache.tools.ant.Task#execute()
> +     */
> +    public void execute() throws BuildException {
> +        if (context == null) {
> +            throw new BuildException("context node must be set");
> +        }
> +        if (path == null) {
> +            throw new BuildException("path must be set");
> +        }
> +        if (property == null && node == null) {
> +            throw new BuildException("one of property or node must be set");
> +        }
> +        if (property != null && node != null) {
> +            throw new BuildException("property and node must not be both set");
> +        }
> +
> +        Project prj = getProject();
> +        DOMNode contextDOMNode = (DOMNode)prj.getReference(context);
> +        if (contextDOMNode == null) {
> +            throw new BuildException("context node [" + context + "] does not exist.");
> +        }
> +        Node contextNode = contextDOMNode.getNode();
> +        Node n = XPathUtils.selectSingleNode(contextNode, path);
> +        if (n == null) {
> +            throw new BuildException("exaclty one node must be selected by xpath");
> +        }
> +
> +        if (node != null) {
> +            addNewDOMNodeReference(prj, node, n);
> +        } else if (property != null) {
> +            prj.setProperty(property, n.getNodeValue());
> +        }
> +    }
> +
> +    protected DOMNode addNewDOMNodeReference(Project prj, String id, Node n) {
> +        DOMNode nDomNode = (DOMNode)prj.createDataType("domnode");
> +        nDomNode.setNode(n);
> +        prj.addReference(id, nDomNode);
> +        return nDomNode;
> +    }
> +}
> diff -ruN XPathForEachSample.orig/src/sample/ant/types/DOMNode.java XPathForEachSample/src/sample/ant/types/DOMNode.java
> --- XPathForEachSample.orig/src/sample/ant/types/DOMNode.java 1970-01-01 09:00:00.000000000
+0900
> +++ XPathForEachSample/src/sample/ant/types/DOMNode.java 2003-01-30 10:49:48.000000000
+0900
> @@ -0,0 +1,16 @@
> +package sample.ant.types;
> +
> +import org.apache.tools.ant.types.DataType;
> +import org.w3c.dom.Node;
> +
> +public class DOMNode extends DataType {
> +    protected Node node;
> +
> +    public void setNode(Node node) {
> +        this.node = node;
> +    }
> +
> +    public Node getNode() {
> +        return node;
> +    }
> +}
> diff -ruN XPathForEachSample.orig/src/sample/ant/util/XPathUtils.java XPathForEachSample/src/sample/ant/util/XPathUtils.java
> --- XPathForEachSample.orig/src/sample/ant/util/XPathUtils.java 1970-01-01 09:00:00.000000000
+0900
> +++ XPathForEachSample/src/sample/ant/util/XPathUtils.java 2003-01-30 10:48:49.000000000
+0900
> @@ -0,0 +1,32 @@
> +package sample.ant.util;
> +
> +import javax.xml.transform.TransformerException;
> +
> +import org.apache.tools.ant.BuildException;
> +import org.apache.xpath.XPathAPI;
> +import org.w3c.dom.Node;
> +import org.w3c.dom.traversal.NodeIterator;
> +
> +/**
> + *
> + */
> +public class XPathUtils {
> +    public static Node selectSingleNode(Node contextNode, String path)
> +        throws BuildException {
> +        try {
> +            return XPathAPI.selectSingleNode(contextNode, path);
> +        } catch (TransformerException ex) {
> +            throw new BuildException(ex);
> +        }
> +    }
> +
> +    public static NodeIterator selectNodeIterator(Node contextNode, String path)
> +        throws BuildException {
> +        try {
> +            return XPathAPI.selectNodeIterator(contextNode, path);
> +        } catch (TransformerException ex) {
> +            throw new BuildException(ex);
> +        }
> +    }
> +
> +}
> diff -ruN XPathForEachSample.orig/src/sample/velocity/XPathTool.java XPathForEachSample/src/sample/velocity/XPathTool.java
> --- XPathForEachSample.orig/src/sample/velocity/XPathTool.java 1970-01-01 09:00:00.000000000
+0900
> +++ XPathForEachSample/src/sample/velocity/XPathTool.java 2003-01-30 10:48:29.000000000
+0900
> @@ -0,0 +1,251 @@
> +package sample.velocity;
> +
> +import java.util.ArrayList;
> +import java.util.Iterator;
> +import java.util.List;
> +
> +import javax.xml.transform.TransformerException;
> +
> +import org.apache.xml.utils.PrefixResolver;
> +import org.apache.xpath.XPathAPI;
> +import org.apache.xpath.objects.XObject;
> +import org.w3c.dom.Node;
> +import org.w3c.dom.NodeList;
> +import org.w3c.dom.traversal.NodeIterator;
> +
> +/**
> + *
> + */
> +public class XPathTool {
> +    public XPathTool() {
> +    }
> +
> +    public String value(Node contextNode, String str)
> +        throws TransformerException {
> +        Node n = node(contextNode, str);
> +        return n == null ? null : n.getNodeValue();
> +    }
> +
> +    public String value(Node contextNode, String str, Node namespaceNode)
> +        throws TransformerException {
> +        Node n = node(contextNode, str, namespaceNode);
> +        return n == null ? null : n.getNodeValue();
> +    }
> +
> +    /**
> +     * Use an XPath string to select a single node. XPath namespace
> +     * prefixes are resolved from the context node, which may not
> +     * be what you want (see the next method).
> +     *
> +     * @param str A valid XPath string.
> +     * @return The first node found that matches the XPath, or null.
> +     *
> +     * @throws TransformerException
> +     */
> +    public Node node(Node contextNode, String str)
> +        throws TransformerException {
> +        return XPathAPI.selectSingleNode(contextNode, str);
> +    }
> +
> +    /**
> +     * Use an XPath string to select a single node. XPath namespace
> +     * prefixes are resolved from the context node, which may not
> +     * be what you want (see the next method).
> +     *
> +     * @param str A valid XPath string.
> +     * @return The first node found that matches the XPath, or null.
> +     *
> +     * @throws TransformerException
> +     */
> +    public Node node(Node contextNode, String str, Node namespaceNode)
> +        throws TransformerException {
> +        return XPathAPI.selectSingleNode(contextNode, str, namespaceNode);
> +    }
> +
> +    public Iterator iter(Node contextNode, String str)
> +        throws TransformerException {
> +        return asIterator(nodeIter(contextNode, str));
> +    }
> +
> +    public Iterator iter(Node contextNode, String str, Node namespaceNode)
> +        throws TransformerException {
> +        return asIterator(nodeIter(contextNode, str, namespaceNode));
> +    }
> +
> +    /**
> +     *  Use an XPath string to select a nodelist.
> +     *  XPath namespace prefixes are resolved from the contextNode.
> +     *
> +     *  @param str A valid XPath string.
> +     *  @return A NodeIterator, should never be null.
> +     *
> +     * @throws TransformerException
> +     */
> +    public NodeIterator nodeIter(Node contextNode, String str)
> +        throws TransformerException {
> +        return XPathAPI.selectNodeIterator(contextNode, str);
> +    }
> +
> +    /**
> +     *  Use an XPath string to select a nodelist.
> +     *  XPath namespace prefixes are resolved from the contextNode.
> +     *
> +     *  @param str A valid XPath string.
> +     *  @return A NodeIterator, should never be null.
> +     *
> +     * @throws TransformerException
> +     */
> +    public NodeIterator nodeIter(Node contextNode, String str, Node namespaceNode)
> +        throws TransformerException {
> +        return XPathAPI.selectNodeIterator(contextNode, str, namespaceNode);
> +    }
> +
> +    public List list(Node contextNode, String str)
> +        throws TransformerException {
> +        return asList(nodeList(contextNode, str));
> +    }
> +
> +    public List list(Node contextNode, String str, Node namespaceNode)
> +        throws TransformerException {
> +        return asList(nodeList(contextNode, str, namespaceNode));
> +    }
> +
> +    /**
> +     *  Use an XPath string to select a nodelist.
> +     *  XPath namespace prefixes are resolved from the contextNode.
> +     *
> +     *  @param str A valid XPath string.
> +     *  @return A NodeIterator, should never be null.
> +     *
> +     * @throws TransformerException
> +     */
> +    public NodeList nodeList(Node contextNode, String str)
> +        throws TransformerException {
> +        return XPathAPI.selectNodeList(contextNode, str);
> +    }
> +
> +    /**
> +     *  Use an XPath string to select a nodelist.
> +     *  XPath namespace prefixes are resolved from the contextNode.
> +     *
> +     *  @param str A valid XPath string.
> +     *  @return A NodeIterator, should never be null.
> +     *
> +     * @throws TransformerException
> +     */
> +    public NodeList nodeList(Node contextNode, String str, Node namespaceNode)
> +        throws TransformerException {
> +        return XPathAPI.selectNodeList(contextNode, str, namespaceNode);
> +    }
> +
> +    /**
> +     *  Evaluate XPath string to an XObject.  Using this method,
> +     *  XPath namespace prefixes will be resolved from the namespaceNode.
> +     *  @param str A valid XPath string.
> +     *  @return An XObject, which can be used to obtain a string, number, nodelist,
etc, should never be null.
> +     *  @see org.apache.xpath.objects.XObject
> +     *  @see org.apache.xpath.objects.XNull
> +     *  @see org.apache.xpath.objects.XBoolean
> +     *  @see org.apache.xpath.objects.XNumber
> +     *  @see org.apache.xpath.objects.XString
> +     *  @see org.apache.xpath.objects.XRTreeFrag
> +     *
> +     * @throws TransformerException
> +     */
> +    public XObject eval(Node contextNode, String str)
> +        throws TransformerException {
> +        return XPathAPI.eval(contextNode, str);
> +    }
> +
> +    /**
> +     *  Evaluate XPath string to an XObject.  Using this method,
> +     *  XPath namespace prefixes will be resolved from the namespaceNode.
> +     *  @param str A valid XPath string.
> +     *  @return An XObject, which can be used to obtain a string, number, nodelist,
etc, should never be null.
> +     *  @see org.apache.xpath.objects.XObject
> +     *  @see org.apache.xpath.objects.XNull
> +     *  @see org.apache.xpath.objects.XBoolean
> +     *  @see org.apache.xpath.objects.XNumber
> +     *  @see org.apache.xpath.objects.XString
> +     *  @see org.apache.xpath.objects.XRTreeFrag
> +     *
> +     * @throws TransformerException
> +     */
> +    public XObject eval(Node contextNode, String str, Node namespaceNode)
> +        throws TransformerException {
> +        return XPathAPI.eval(contextNode, str, namespaceNode);
> +    }
> +
> +    /**
> +     *   Evaluate XPath string to an XObject.
> +     *   XPath namespace prefixes are resolved from the namespaceNode.
> +     *   The implementation of this is a little slow, since it creates
> +     *   a number of objects each time it is called.  This could be optimized
> +     *   to keep the same objects around, but then thread-safety issues would arise.
> +     *
> +     *   @param contextNode The node to start searching from.
> +     *   @param str A valid XPath string.
> +     *   @param namespaceNode The node from which prefixes in the XPath will be resolved
to namespaces.
> +     *   @param prefixResolver Will be called if the parser encounters namespace
> +     *                         prefixes, to resolve the prefixes to URLs.
> +     *   @return An XObject, which can be used to obtain a string, number, nodelist,
etc, should never be null.
> +     *   @see org.apache.xpath.objects.XObject
> +     *   @see org.apache.xpath.objects.XNull
> +     *   @see org.apache.xpath.objects.XBoolean
> +     *   @see org.apache.xpath.objects.XNumber
> +     *   @see org.apache.xpath.objects.XString
> +     *   @see org.apache.xpath.objects.XRTreeFrag
> +     *
> +     * @throws TransformerException
> +     */
> +    public XObject eval(
> +        Node contextNode,
> +        String str,
> +        PrefixResolver prefixResolver)
> +        throws TransformerException {
> +        return XPathAPI.eval(contextNode, str, prefixResolver);
> +    }
> +
> +
> +    protected Iterator asIterator(NodeIterator nit) {
> +//        List list = new ArrayList();
> +//        Node n = null;
> +//        while ((n = nit.nextNode()) != null) {
> +//            list.add(n);
> +//        }
> +//        return list.iterator();
> +        final NodeIterator fnit = nit;
> +        return new Iterator() {
> +            protected Object savedNext;
> +
> +            public boolean hasNext() {
> +                if (savedNext == null) {
> +                    savedNext = fnit.nextNode();
> +                }
> +                return savedNext != null;
> +            }
> +            public Object next() {
> +                if (savedNext == null) {
> +                    return fnit.nextNode();
> +                } else {
> +                    Object n = savedNext;
> +                    savedNext = null;
> +                    return n;
> +                }
> +            }
> +            public void remove() {
> +                throw new UnsupportedOperationException();
> +            }
> +        };
> +    }
> +
> +    protected List asList(NodeList nl) {
> +        int len = nl.getLength();
> +        List list = new ArrayList(len);
> +        for (int i = 0; i < len; i++) {
> +            list.add(nl.item(i));
> +        }
> +        return list;
> +    }
> +
> +}
> 
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: ant-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: ant-dev-help@jakarta.apache.org
> 
> 
> 


Mime
View raw message