ant-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From peter reilly <peter.rei...@corvil.com>
Subject Re: Mixed content problem with literal XML data via DynamicConfigurator
Date Fri, 31 Oct 2003 17:16:35 GMT
No,
it is not possible with the current ant internal data structures
to do this.
Peter

On Friday 31 October 2003 17:13, Patrick Surry wrote:
> Thanks to feedback from the list, I've got a slightly modified version of
> Dominique's code working (see end) that builds a DOM document to house
> whatever 'literal' XML data I want within my task, including property
> substitution for attribute values and text nodes.  The only problem now is
> that it doesn't seem to work well for 'mixed' content (ie. mixed elements
> and text) since all the child elements seem to get create'd prior to any of
> the text-node siblings. For example if I have:
>
>
>    <target name="main">
>      <property name="foo" value="something"/>
>      <mytask in="foo.ftr" out="bar.ftr">
>        <fields>
> 	 xyz
>          <something foo="bar${foo}">
> 	   again
> 	   <whatever/>
> 	   And ${foo} more...
> 	 </something>
>          abc
>          <another/>
>          def
>        </fields>
>      </mytask>
>    </target>
>
> where the MyTask class has a createFields() method which generates an
> XMLFragment (see end), the XMLFragment ends up containing the following
> document - all text nodes have moved after their sibling elements:
>
> <?xml version="1.0" encoding="UTF-8"?>
> <fields>
>
>   <something foo="barsomething">
>
>     <whatever></whatever>
>
> againAnd something more...  </something>
>
>   <another></another>
>
> xyzabcdef</fields>
>
>
> Any thoughts?  I'm guessing it's because all createDynamicElement() calls
> happen before any addText() calls - should I be able to createText() to
> preserve the sequencing?
>
> Thanks,
> Patrick
>
> /*
>
> List:     ant-dev
> Subject:  RE: Questions: A Cocoon Ant task
> From:     Dominique Devienne <DDevienne () lgc ! com>
> Date:     2003-10-08 19:04:21
>
> You can use DynamicConfigurator to intercept attribute/elements, and build
> the DOM tree yourself
>
> The code below should get you a leg up. Provided with no warranties
> whatsoever ;-) I wrote this a long time ago, on a weekend, with little Ant
> experience. --DD
>
> */
>
> package com.quadstone.ext.qsbuild.ant;
>
> import java.io.File;
> import java.io.FileOutputStream;
> import java.io.IOException;
> import java.io.ByteArrayOutputStream;
>
> import org.w3c.dom.Node;
> import org.w3c.dom.Element;
> import org.w3c.dom.Document;
> import org.w3c.dom.DocumentFragment;
> import org.w3c.dom.NodeList;
> import org.w3c.dom.DOMException;
>
> import javax.xml.parsers.DocumentBuilder;
> import javax.xml.parsers.DocumentBuilderFactory;
> import javax.xml.parsers.ParserConfigurationException;
>
> import org.apache.tools.ant.Project;
> import org.apache.tools.ant.BuildException;
> import org.apache.tools.ant.DynamicConfigurator;
>
> import org.apache.tools.ant.types.DataType;
> import org.apache.tools.ant.util.DOMElementWriter;
>
> /**
>  * Base class for those classes that can appear inside the build file
>  * as stand alone data types.
>  *
>  * <p><em>My very first data type ;-)</em></p>
>  *
>  * @author <a href="mailto:ddevienne@lgc.com">Dominique Devienne</a>
>  */
> public class XMLFragment
>              extends DataType
>              implements DynamicConfigurator {
>
>     /**
>      * A dyna'tor for each element.
>      */
>     public class ElementWrapper
>                          implements DynamicConfigurator {
>
>         /** The XML DOM node */
>         private Node _node;
>
>         /** Instantiate a child wrapper */
>         private ElementWrapper(Node parent, String childName) {
>             Document document = parent.getOwnerDocument();
>             if (document == null) {
>               document = (Document)parent; // Node is the document!
>             }
>             _node = document.createElement(childName);
>             parent.appendChild(_node);
>         }
>
>         //
>         // interface DynamicConfigurator
>         //
>
>         public void setDynamicAttribute(String name, String value)
>                     throws BuildException {
> 	    String subst = getProject().replaceProperties(value);
>             // Never called for anything by Element wrappers
>             Element element = (Element)_node;
>             element.setAttribute(name, subst);
>         }
>
>         public Object createDynamicElement(String name)
>                       throws BuildException {
>             return new ElementWrapper(_node, name);
>         }
>
> 	// Unfortunately, all text nodes get added after other sibling elements
> 	// I suspect due to createDynamicElement getting called early and
> 	// addText gettting called late
> 	public void addText(String text) {
> 	    String subst = getProject().replaceProperties(text);
> 	    _node.appendChild(_node.getOwnerDocument().createTextNode(subst));
> 	}
>
>     } // END class XMLFragment.ElementWrapper
>
>
>     //    private DocumentFragment _fragment;
>     private Document _fragment;
>     private ElementWrapper _wrapper;
>
>     /**
>      * Instanciate a new DOM document fragment wrapped in an Ant data type.
>      */
>     public XMLFragment(String name) {
>         try {
>             DocumentBuilder builder =
> DocumentBuilderFactory.newInstance().newDocumentBuilder();
>             _fragment = builder.newDocument(); //.createDocumentFragment();
>             _wrapper = new ElementWrapper(_fragment,name);
>         }
>         catch (ParserConfigurationException e) {
>             throw new BuildException(e);
>         }
>     }
>
>     /**
>      * Sets the name of the top-level DOM node, the xml fragment, to use.
>      *
>      * @param  name the xml fragment node name. Defaults to "xmlfragment".
>     public void setName(String name) {
>         _wrapper._tagname = name;
>     }
>      */
>
>     public String toString() {
> 	ByteArrayOutputStream ostream = new ByteArrayOutputStream();
> 	try {
> 	    new DOMElementWriter().write(_fragment.getDocumentElement(), ostream);
> 	    return ostream.toString();
> 	}
> 	catch (IOException e) {
> 	    throw new BuildException(e);
> 	}
>     }
>
>     public File writeTemp() {
> 	FileOutputStream os = null;
> 	File tmpFile = null;
> 	try {
> 	    tmpFile = File.createTempFile("qsinterp",".xml",null);
> 	    System.out.println("Temp file = " + tmpFile.getPath());
> 		// tmpfile.deleteOnExit();
> 	    os = new java.io.FileOutputStream(tmpFile);
> 	    String xml = toString();
> 	    os.write(xml.getBytes(), 0, xml.length());
> 	} catch (Exception e) {
> 	    throw new BuildException(e);
> 	} finally {
> 	    try { os.close(); } catch (Exception e) {}
> 	}
> 	return tmpFile;
>     }
>
>     //
>     // interface DynamicConfigurator
>     //
>
>     public void setDynamicAttribute(String name, String value)
>                 throws BuildException {
>         // The root only supports explicit 'normal' attributes!
>         throw new BuildException("attribute "+name+" not supported!");
>     }
>
>     public Object createDynamicElement(String name)
>                   throws BuildException {
>         return _wrapper.createDynamicElement(name);
>     }
>
>     public void addText(String text) {
> 	_wrapper.addText(text);
>     }
>
> } // END class XMLFragment
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@ant.apache.org
> For additional commands, e-mail: user-help@ant.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@ant.apache.org
For additional commands, e-mail: user-help@ant.apache.org


Mime
View raw message