Hi Cristoph, thank for your detailed reply. I will let you know how it turns out with your sample. Alessandro
On 9/13/07, [EMAIL PROTECTED] <[EMAIL PROTECTED]> wrote: > > Hi, > > early 2000' I've used both Anakia derived XML rendering and DSVL. > > The major characteristics are: > * Anakia uses JDOM which has more Java-like syntax (node children are just > plain collections). Anakia was also built as an ANT task, but can be used > alone as the documentation shows. > * DSVL can be used in an XSLT-like declarative form, internally it uses > XML4J which has build in XPATH support > > I liked DSVL more since it allows both declarative processing and explicit > modes. It has been on the back of my mind to implement an upgrade of DSVL > using standard DOM and JXPath to profit from the standards and also to use > the XSL-style processing on Java objects. But I never had the project nor > the time to do this... > > The speed of DSVL was a bit dissapointing, but XSLT was not much better. > For one-time conversion tasks this should be no issue. > > Another option apart from using Anakia and DSVL, is to just place your DOM > into the context along with some XPATH tool and do your processing from > there. I currently use such an approach with a custom cmdline tool (that > understands XML and CSV - see attachment, plus some old-examples). Again, in > the back of my mind I want to move this to use the ToolboxManager to be more > configurable and flexible. > > The idea of using velocity for XML rendering into HTML is much neater than > XSL since the syntaxes do not collide and are optically easy to kept apart. > > Just mu 2c! > :) Christoph > > > Alessandro Bologna wrote: > > Thanks Rob! > > > > Any other suggestions from the list? > > Alessandro > > > > > > > > On 9/12/07, Robert Koberg <[EMAIL PROTECTED]> wrote: > >> On Wed, 2007-09-12 at 13:25 -0400, Alessandro Bologna wrote: > >> > >>> In any case, what I am really interested is what are the best > practices > >>> using Velocity to render complex, quite unstructured, namespace > >>> qualified XML contents. > >> Your going to run into problems with DVSL/Anakia if your content is > >> unstructured > >> > >>> What was your approach? > >> XSL is the tool for the job. > >> > >> best, > >> -Rob > >> > >>> Thanks in advance for your responses. > >>> > >>> Alessandro > >>> > >>> > >>> > >>> > >>> > >>> > >>> > >>> > >>> On 9/11/07, Alessandro Bologna <[EMAIL PROTECTED]> wrote: > >>>> Hi, > >>>> > >>>> my apologies in advance if this is an FAQ, but I couldn't find an > >> answer > >>>> in the documentation, so I decided to write to the list. > >>>> > >>>> In the CMS project I am working on, we are considering using velocity > >> to > >>>> generate "pre-cooked" template based web pages, using XML as data > >> source. > >>>> In other words, the data to be published is essentially XML, with > >> elements > >>>> such as <article>, <headline>, <deck>, <body> etc, with some elements > >>>> containing quite unstructured XHTML (i.e variable number of <p/>, > >> <div/> > >>>> etc), and other containing refences to other elements via id/refid. > >>>> > >>>> This data has to be processed to generate static HMTL files that are > >> then > >>>> pushed to Apache for serving them. > >>>> > >>>> Question #1 > >>>> It seems that there are two main options: using XMLEasyBean or/and > >> DVSL. > >>>> Are there any other alternatives? > >>>> > >>>> Question #2 > >>>> In both cases, it seems that XML namespaces are not supported (I am > >>>> getting an empty output if my source contains namespace qualified XML > >>>> elements), am I doing something wrong? > >>>> > >>>> Question #3 > >>>> Any idea of performances, compared to say, XSLT? > >>>> > >>>> Thanks > >>>> Alessandro Bologna > >>>> > >>>> > >> > >> --------------------------------------------------------------------- > >> To unsubscribe, e-mail: [EMAIL PROTECTED] > >> For additional commands, e-mail: [EMAIL PROTECTED] > >> > >> > > > > /* > * Licensed to the Apache Software Foundation (ASF) under one > * or more contributor license agreements. See the NOTICE file > * distributed with this work for additional information > * regarding copyright ownership. The ASF licenses this file > * to you under the Apache License, Version 2.0 (the > * "License"); you may not use this file except in compliance > * with the License. You may obtain a copy of the License at > * > * http://www.apache.org/licenses/LICENSE-2.0 > * > * Unless required by applicable law or agreed to in writing, > * software distributed under the License is distributed on an > * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY > * KIND, either express or implied. See the License for the > * specific language governing permissions and limitations > * under the License. > */ > > package de.dlr.dfd.dims.tools.transformer; > > import java.io.BufferedWriter; > import java.io.File; > import java.io.OutputStream; > import java.io.OutputStreamWriter; > import java.io.Writer; > import java.util.Hashtable; > import java.util.Map; > import java.util.StringTokenizer; > import java.util.Vector; > > import org.apache.velocity.Template; > import org.apache.velocity.VelocityContext; > import org.apache.velocity.anakia.AnakiaJDOMFactory; > import org.apache.velocity.anakia.Escape; > import org.apache.velocity.anakia.OutputWrapper; > import org.apache.velocity.app.VelocityEngine; > import org.apache.velocity.runtime.RuntimeConstants; > import org.apache.velocity.util.StringUtils; > > import org.jdom.Document; > import org.jdom.JDOMException; > import org.jdom.input.SAXBuilder; > > import org.xml.sax.SAXParseException; > > import de.dlr.dfd.dims.tools.xmlTransformer.ClassTool; > import de.dlr.dfd.dims.tools.xmlTransformer.ContextTool; > import de.dlr.dfd.dims.tools.csvParser.CSVParser; > > > > /** > * The purpose of this class is to allow you to use Velocity as an XML > * transformation tool like XSLT is. So, instead of using XSLT, you will > * be able to use this class instead to do your transformations.<p> > * > * You can find more documentation about used classes on the Velocity <a > * href="http://jakarta.apache.org/velocity/anakia.html">Website</a> . > * > * Addition (28.01.2005) : You can also use this class to transform a > csv-file. > * The old name of this file was xmlTransformer in the same package. (Sven > Kroeger) > * > * @created November 13, 2001 > * @author Jon S. Stevens, Attila Szegedi, Christoph Reck, Sven Kroeger > */ > public class Transformer > { > static final String CLASS_ID = "@(#) $Id: Transformer.java,v 1.22005/02/01 > 13:46:39 reck Exp $"; > > private static String XML = "xml"; > private static String CSV = "csv"; > > /** The VelocityEngine instance to use. **/ > private VelocityEngine velocity; > > /** The <code>[EMAIL PROTECTED] SAXBuilder}</code> instance to use. **/ > private SAXBuilder builder; > > /** The encoding used for the output **/ > protected String encoding = "ISO-8859-1"; > > /** > * Create the transformer instance, then use > * <code>process(fileIn, templateIn)</code>. > */ > public Transformer(String templatePath, String loggerClass, String > kindOfSource) > throws Exception > { > // create the VelocityEngine instance to use > velocity = new VelocityEngine(); > > if ( kindOfSource.equals( XML ) ) // kroeger : add if-clause > { > // create the AnakiaElement factory > builder = new SAXBuilder(); > builder.setFactory( new AnakiaJDOMFactory() ); > } > > // either use velocity.properties from the template path or defaults > File templateDir = new File(templatePath); > File velocityPropertiesFile = new File(templateDir, " > velocity.properties"); > if( velocityPropertiesFile.exists() ) > { > velocity.init( velocityPropertiesFile.getAbsolutePath() ); > } > else > { > templatePath = new File(templatePath).getCanonicalPath(); > velocity.setProperty( RuntimeConstants.FILE_RESOURCE_LOADER_PATH, > templatePath ); > velocity.setProperty( RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS, > loggerClass ); > velocity.setProperty( RuntimeConstants.VM_PERM_ALLOW_INLINE, "true"); > velocity.setProperty( > RuntimeConstants.VM_PERM_ALLOW_INLINE_REPLACE_GLOBAL, "true"); > velocity.init(); > } > > // get the property TEMPLATE_ENCODING, we know it's a string... > String encoding = (String) velocity.getProperty( > RuntimeConstants.OUTPUT_ENCODING); > if( (encoding == null) || (encoding.length() == 0) || > encoding.equals("8859-1") || encoding.equals("8859_1") ) > { > encoding = "ISO-8859-1"; > } > } > > /** > * Process an XML file using Velocity. > */ > private void processXML( Map rootContext, > String xmlFile, > String transformTemplate, > OutputStream outStream ) > { > Writer writer = null; > try > { > //-- command line status > velocity.info( "Transformer input: " + xmlFile ); > > // Build the JDOM Document > Document document = builder.build( xmlFile ); > > // Shove things into the Context > VelocityContext context = new VelocityContext(rootContext); > > OutputWrapper ow = new OutputWrapper(); > ow.setEncoding( encoding ); > > context.put( "document", document ); > context.put( "xmlout", ow ); > context.put( "relativePath", getRelativePath( xmlFile ) ); > context.put( "escape", new Escape() ); > context.put( "Context", new ContextTool(context) ); > context.put( "date", new java.util.Date() ); > > /* > * Make the context instance available in the templates. > * TODO: provide a pluggable directive that makes this. > * Note: the per-request context initializer template can > * remove it to hide it from the application templates. > */ > context.put( "context", context ); > > // Process the VSL template with the context and write out > // the result as the outFile. > writer = new BufferedWriter( new OutputStreamWriter( outStream ) ); > // get the template to process > Template template = velocity.getTemplate( transformTemplate ); > template.merge( context, writer ); > > velocity.info( "Transformer done." ); > } > catch( JDOMException e ) > { > if( e.getCause() != null ) > { > Throwable rootCause = e.getCause(); > if( rootCause instanceof SAXParseException ) > { > System.err.println( "" ); > System.err.println( "Error: " + rootCause.getMessage() ); > System.err.println( > " Line: " + > ( ( SAXParseException ) rootCause ).getLineNumber() + > " Column: " + > ( ( SAXParseException ) rootCause ).getColumnNumber() ); > System.err.println( "" ); > } > else > { > rootCause.printStackTrace(); > } > } > else > { > e.printStackTrace(); > } > velocity.error( "Transformer failed to process " + xmlFile ); > } > catch( Throwable e ) > { > velocity.error( "Transformer failed to process " + xmlFile ); > e.printStackTrace(); > } > finally > { > if( writer != null ) > { > try > { > writer.flush(); > writer.close(); > } > catch( Exception e ) > { > } > } > } > } > > /** > * Process an CSV file using Velocity. > */ > private void processCSV( Map rootContext, > String csvFile, > String transformTemplate, > OutputStream outStream ) > { > Writer writer = null; > try > { > //-- command line status > velocity.info( "Transformer input: " + csvFile ); > > // Shove things into the Context > VelocityContext context = new VelocityContext(rootContext); > > OutputWrapper ow = new OutputWrapper(); > ow.setEncoding( encoding ); > > context.put( "inFile", csvFile ); > context.put( "csvParser", new CSVParser() ); > > context.put( "csvout", ow ); > context.put( "relativePath", getRelativePath( csvFile ) ); > context.put( "escape", new Escape() ); > context.put( "Context", new ContextTool(context) ); > context.put( "date", new java.util.Date() ); > > /* > * Make the context instance available in the templates. > * TODO: provide a pluggable directive that makes this. > * Note: the per-request context initializer template can > * remove it to hide it from the application templates. > */ > context.put( "context", context ); > > // Process the VSL template with the context and write out > // the result as the outFile. > writer = new BufferedWriter( new OutputStreamWriter( outStream ) > ); > // get the template to process > Template template = velocity.getTemplate( transformTemplate ); > template.merge( context, writer ); > > velocity.info( "Transformer done with CSV file." ); > } > catch( Throwable e ) > { > velocity.error( "Transformer failed to process " + csvFile ); > e.printStackTrace(); > } > finally > { > if( writer != null ) > { > try > { > writer.flush(); > writer.close(); > } > catch( Exception e ) > { > } > } > } > } > > /** > * Process a controller template using Velocity. > */ > private void process( Map rootContext, > String transformTemplate, > OutputStream outStream ) > { > Writer writer = null; > try > { > // Shove things into the Context > VelocityContext context = new VelocityContext(rootContext); > > context.put( "relativePath", getRelativePath( transformTemplate ) ); > context.put( "escape", new Escape() ); > context.put( "Context", new ContextTool(context) ); > context.put( "date", new java.util.Date() ); > > /* > * Make the context instance available in the templates. > * TODO: provide a pluggable directive that makes this. > * Note: the per-request context initializer template can > * remove it to hide it from the application templates. > */ > context.put( "context", context ); > > // Process the VSL template with the context and write out > // the result as the outFile. > writer = new BufferedWriter( new OutputStreamWriter( outStream ) ); > // get the template to process > Template template = velocity.getTemplate( transformTemplate ); > template.merge( context, writer ); > > velocity.info( "Transformer done." ); > } > catch( Throwable e ) > { > velocity.error( "Transformer failed to process " + transformTemplate > ); > e.printStackTrace(); > } > finally > { > if( writer != null ) > { > try > { > writer.flush(); > writer.close(); > } > catch( Exception e ) > { > } > } > } > } > > /** > * Hacky method to figure out the relative path that we are currently in. > This > * is good for getting the relative path for images and anchor's. > * > * @param file > * @return The <code>relativePath</code> value. > */ > private String getRelativePath( String file ) > { > if( file == null || file.length() == 0 ) > { > return ""; > } > StringTokenizer st = new StringTokenizer( file, "/\\" ); > // needs to be -1 cause ST returns 1 even if there are no matches. huh? > int slashCount = st.countTokens() - 1; > StringBuffer sb = new StringBuffer(); > for( int i = 0; i < slashCount; i++ ) > { > sb.append( "../" ); > } > > if( sb.toString().length() > 0 ) > { > return StringUtils.chop( sb.toString(), 1 ); > } > else > { > return "."; > } > } > > /** > * Transformation invocation over command line arguments. > */ > public static void main(String[] args) > { > // A switch for the kind of transforming; > String kindOfSource = ""; > // The classname of the default logger to be used > String logger = "org.apache.velocity.runtime.log.NullLogSystem"; > > Vector vargs = new Vector(); > for( int i = 0; i < args.length; ++i ) > { > if( args[i].equals("-quiet") ) > logger = "org.apache.velocity.runtime.log.NullLogSystem"; > else if( args[i].equals("-verbose") ) > logger = "de.dlr.dfd.dims.tools.xmlTransformer.StderrLogSystem"; > else if ( args[i].equalsIgnoreCase("-xml") ) > { > kindOfSource = XML; > } > else if ( args[i].equalsIgnoreCase("-csv") ) > { > kindOfSource = CSV; > } > else > vargs.add( args[i] ); > } > if( vargs.size() >= 1 ) > { > try > { > Transformer t = new Transformer(".", logger, kindOfSource); > Hashtable rootContext = new Hashtable(); > // convenience to allow more complex actions within > templates > rootContext.put( "Class", new ClassTool() ); > rootContext.put( "args", args ); > String template, inFile; > if( vargs.size() == 1 ) > { > inFile = ""; > template = (String) vargs.elementAt(0); > } > else > { > inFile = (String) vargs.elementAt(0); > template = (String) vargs.elementAt(1); > } > > if ( kindOfSource.equals( CSV ) ) > { > // run a CSV-Transformation > t.processCSV( rootContext, inFile, template, System.out); > } > else if ( kindOfSource.equals( XML ) ) > { > // run a XML-Transformation > t.processXML( rootContext, inFile, template, System.out); > } > else > { > t.process( rootContext, template, System.out ); > } > } > catch ( Exception ex ) > { > System.err.println("ERROR: failed running transformation"); > ex.printStackTrace(); > Runtime.getRuntime().exit(2); > } > } > else > { > System.err.println("ERROR: invalid command line parameters"); > System.err.println(""); > System.err.println("USAGE: Transformer [-xml file.xml | -csv file.csv] > transformTemplate.vsl"); > System.err.println(""); > Runtime.getRuntime().exit(1); > } > } > > } // end of XmlTransformer > > ## > ------------------------------------------------------------------------ > ## Function to read in a CVS file into an array of maps. > ## The first item in the array contains the header line > ## > ------------------------------------------------------------------------ > #set( $LF = $Context.formDecode("%0A") ) > #macro( parseCSV $filename $lines ) > Parsing file="$filename" > #set( $text = "#include($filename)" ) > #set( $tokenizer = $Class.newInstance("java.util.StringTokenizer", $text, > ";") ) > ## > ## loop over all items in text > #set( $header = true ) > #set( $headers = [] ) > #foreach( $field in $tokenizer ) > ## > ## possibly split last $item in a line from $next > #set( $index = $field.indexOf($LF) ) > #if( $index > 0 ) > #set( $item = $field.substring(0, $index) ) > #set( $index = $index + 1 ) > #set( $next = $field.substring($index) ) > #else > #set( $item = $field ) > #end > ## > ## process item > #if( $header ) > #call( $headers.add($item) ) > #else > ## process line > #set( $column = $column + 1 ) > #call( $map.put( $headers.get($column), $item ) ) > #end > ## > ## process new line > #if( $index > 0 ) > #if( $header ) > #set( $header = false ) > #call( $lines.add($headers) ) > #else > #call( $lines.add($map) ) > #end > #set( $column = 0 ) > #set( $map = $Context.newHashtable( $headers.size() ) ) > #call( $map.put( $headers.get($column), $next ) ) > #end > #end > #end## end of macro parseCSV.vm > > ## > ------------------------------------------------------------------------ > ## Macro to write a text to a file. > ## > ------------------------------------------------------------------------ > #macro( fileWrite $filename $text ) > #set( $out = $Class.newInstance("java.io.FileOutputStream", $filename) ) > #set( $data = $text.getBytes() ) > #call( $out.write($data) ) > #call( $out.close() ) > #end > > ## > ------------------------------------------------------------------------ > ## Macro to convert a CVS-map to an HTML table. > ## > ------------------------------------------------------------------------ > #macro( convertToCsvTable $lines ) > <table> > <tr> > #foreach( $header in $lines.get(0) ) > <th>$header</th> > #end > </tr> > #set( $rows = $lines.size() - 1 ) > #foreach( $row in [1..$rows] ) > <tr> > #set( $map = $lines.get($row) ) > #foreach( $header in $lines.get(0) ) > <td id="$header">$map.get($header)</td> > #end > </tr> > #end > </table> > #end > > ## transform file to 2-dimensional array > #set( $csvFilename = "test.csv" ) > #set( $outFilename = "test.xml" ) > #set( $lines = [] ) > #set( $dummy = "#parseCSV($csvFilename $lines)" ) > > #if( $lines.size() == 0 ) > Failed reading CSV file "$csvFilename" > ## debug code > #### #parse("dump.vm") > #else > ## output the array > #set( $text = "#convertToCsvTable( $lines )" ) > $text > ## write to file > #fileWrite( $outFilename $text ) > #end > > ## > ------------------------------------------------------------------------ > ## File: templates/control/explain.vm > ## > ## Description: Controller to show details on an attribute. > ## > ## Input: QueryData: attributeId and attributeValue > ## Loads the 'gipValids' using a #parse( (possibly ) from > cache) > ## > ## Output: Attribute help screen. > ## > ## Date: 2000-11-08 > ## Author: [EMAIL PROTECTED] > ## Copyright: (c) 2000 Deutsches Zentrum fuer Luft und Raumfahrt > ## > ------------------------------------------------------------------------ > ## > #set( $title = "GIP Attribute Descriptor" ) > ## > ## -------- import attribute valids (cached) -------- > #parse( "control/include/gipValids.vm" ) > ## > #set( $l_attributeValue = $parameters.getString("AttributeValue", "") ) > #if( $l_attributeValue == "" ) > #error( "No attributeValue defined; nothing to lookup for help." ) > #### #stop() > #end > #set( $l_attributeId = $parameters.getString("AttributeId", "") ) > #if( $l_attributeId == "" ) > #set( $l_attributeId = '*AID' ) > #end > ## > #set( $l_xpathSpec = > "AttributeValueDescriptor[AttributeId='$l_attributeId' and > AttributeValue='$l_attributeValue']/*[name()!='DocumentReference']" ) > #set( $l_xmlList = $Xml.applyXPath($gipValids, $l_xpathSpec) ) > #if( $l_xmlList.isEmpty() ) > #error( "No descriptors found for AttributeId=$l_attributeId and > AttributeValue=$l_attributeValue" ) > #### #stop() > #end > > <table bgcolor="$COLORS.BG_TABLE" border="0" cellspacing="1" > cellpadding="2"> > <tr bgcolor="$COLORS.BG_HEAD"> > <td><font color="$COLORS.FG_HEAD">Name</font></td> > <td><font color="$COLORS.FG_HEAD">Value</font></td> > </tr> > #foreach( $l_field in $l_xmlList ) > #set( $l_name = $l_field.getName() ) > #set( $l_text = $l_field.getText() ) > <tr> > <td style="vertical-align:top">$l_name</td> > <td> > <tt> > #if( $l_text == "" ) > <font color="red">empty</font> > #elseif( $l_name == "AttributeId" ) > ## make AttributeId a backward link > <a href="$link.clone().addQueryData('AttributeValue',$l_text)" > >$l_attributeId</a> > #elseif( $l_name == "Abstract" ) > ## format in wrapping fixed-font, but preserving spaces > #set( $NL = $Context.formDecode('%0A') ) > #set( $l_separator = '' ) > #foreach( $l_line in $Context.tokenize($l_text, $NL) ) > $Regexp.substitute('s/ / /g', $l_line)$l_separator > #set( $l_separator = '<br>' ) > #end > #else > $l_text > #end > </tt> > </td> > </tr> > #end > ## list of DocumentReferences > <tr> > <td style="vertical-align:top">DocumentReference</td> > <td> > </tt> > #set( $l_xmlList = > $l_xmlList.get(0).Parent.getChildren("DocumentReference") ) > #if( $l_xmlList.isEmpty() ) > <em>none</em> > #else > #foreach( $l_field in $l_xmlList ) > #if( $velocityCount != 1 ) > <br> > #end > #if( $l_field.getAttribute("DocumentPointer") ) > <a href="$l_field.getAttributeValue("DocumentPointer")"> > #if( $l_field.getAttribute("DocumentDescription") ) > $l_field.getAttributeValue("DocumentDescription") > #else > $l_field.getAttributeValue("DocumentPointer") > #end > </a> > #else > <font color="red">empty</font> > #end > #end > #end > </td> > </tr> > ## list of valids > <tr> > <td colspan="2"></td> > </tr> > <tr> > <td style="vertical-align:top" align="left">Valids</td> > <td> > #set( $l_xpathSpec = > "AttributeValueDescriptor[AttributeId='$l_attributeValue']" ) > #set( $l_xmlList = $Xml.applyXPath($gipValids, $l_xpathSpec) ) > #if( $l_xmlList.isEmpty() ) > <em>none</em> > #else > #foreach( $l_field in $l_xmlList ) > #if( $velocityCount != 1 ) > <br> > #end > #set( $l_attributeId = $l_field.getChildText("AttributeId") ) > #set( $l_attributeValue = $l_field.getChildText("AttributeValue") > ) > #set( $l_shortName = $l_field.getChildText("ShortName") ) > #if ( $l_field.getChildText("LongName") ) ## avoid log messages > #set( $l_longName = $l_field.getChildText("LongName") ) > #else > #set( $l_longName = false ) > #end > #set( $l_url = $link.clone() ) > #call( $l_url.addQueryData('AttributeId',$l_attributeId) ) > #call( $l_url.addQueryData('AttributeValue',$l_attributeValue) ) > <tt><a href="$l_url" >$l_shortName</a></tt> > #if( $l_longName && ($l_shortName != $l_longName) ) > <font size="-1">$l_longName</font> > #end > #end > #end > </td> > </tr> > </table> > > /* > * $Header: $ > * $Revision: 1.0 $ > * $Date: 2001/06/13 $ > * > * ==================================================================== > * > * The Apache Software License, Version 1.1 > * > * Copyright (c) 1999-2001 The Apache Software Foundation. All rights > * reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions > * are met: > * > * 1. Redistributions of source code must retain the above copyright > * notice, this list of conditions and the following disclaimer. > * > * 2. Redistributions in binary form must reproduce the above copyright > * notice, this list of conditions and the following disclaimer in > * the documentation and/or other materials provided with the > * distribution. > * > * 3. The end-user documentation included with the redistribution, if > * any, must include the following acknowlegement: > * "This product includes software developed by the > * Apache Software Foundation (http://www.apache.org/)." > * Alternately, this acknowlegement may appear in the software itself, > * if and wherever such third-party acknowlegements normally appear. > * > * 4. The names "The Jakarta Project", "Commons", and "Apache Software > * Foundation" must not be used to endorse or promote products derived > * from this software without prior written permission. For written > * permission, please contact [EMAIL PROTECTED] > * > * 5. Products derived from this software may not be called "Apache" > * nor may "Apache" appear in their names without prior written > * permission of the Apache Group. > * > * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED > * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES > * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE > * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR > * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, > * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT > * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF > * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND > * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, > * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT > * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF > * SUCH DAMAGE. > * ==================================================================== > * > * This software consists of voluntary contributions made by many > * individuals on behalf of the Apache Software Foundation. For more > * information on the Apache Software Foundation, please see > * <http://www.apache.org/>. > * > */ > package org.apache.commons.tools; > > import java.io.InputStream; > import java.io.FileInputStream; > import java.io.CharArrayReader; > import java.net.URL; > import java.util.ArrayList; > import java.util.List; > import java.util.ListIterator; > > import org.jdom.Document; > import org.jdom.Element; > import org.jdom.Attribute; > import org.jdom.input.SAXBuilder; > import org.jdom.output.XMLOutputter; > import com.werken.xpath.XPath; > > import org.jdom.input.DOMBuilder; // ### for JAXP security workaround > import java.io.ByteArrayInputStream; > > // to emit error messagesd to the log > import org.apache.velocity.runtime.Runtime; > > /** > * This is a class to provide convenient access and control > * over XML files via <a href="http://www.jdom.org">JDOM</a>. > * > * @company Deutsches Zentrum fuer Luft- und Raumfahrt<p> > * @author [EMAIL PROTECTED] > */ > public class XmlTool > { > /** > * Empty constructor. > */ > public XmlTool() > { > // nothing to do > } > > /** > * Load a JDOM document. > * > * @param fileName The name of the file to load. > * @return The JDOM document root element. > */ > public static Element load(String fileName) > { > InputStream in = null; > try > { > try > { > URL url = new URL(fileName); > in = url.openStream(); > } > catch( Exception ignore ) > { > in = new FileInputStream(fileName); > } > SAXBuilder builder = > new SAXBuilder("org.apache.crimson.parser.XMLReaderImpl"); > Document doc = builder.build(in); > return doc.getRootElement(); > } > catch (Exception ex) > { > ex.printStackTrace(); > } > > return null; > } > > /** > * Create a JDOM tree from a string. > * > * @param xmlString The name of the file to load. > * @return The JDOM document root element. > */ > public static Element fromString(String xmlString) > { > try > { > CharArrayReader in = new CharArrayReader(xmlString.toCharArray > ()); > SAXBuilder builder = > new SAXBuilder("org.apache.crimson.parser.XMLReaderImpl"); > Document doc = builder.build(in); > return doc.getRootElement(); > } > catch (Exception ex) > { > ex.printStackTrace(); > } > > return null; > } > > /** > * Pretty print a JDOM tree. > * > * @param jdom XML document. > * @param indent The indentation string (e.g. spaces or tabs) > * @param initalIndent The initialIndent level. > * @return The formatted string (an empty string upon failure). > */ > public static String format(Document jdom, String indent, int > initalIndent) > { > try > { > XMLOutputter serializer = new XMLOutputter(); > serializer.setIndent(indent); > serializer.setIndentLevel(initalIndent); > return serializer.outputString(jdom); > } > catch (Exception ex) > { > ex.printStackTrace(); > } > > return ""; > } > > /** > * Pretty print a JDOM tree. > * > * @param jdom JDOM document root element. > * @param indent The indentation string (e.g. spaces or tabs) > * @param initalIndent The initialIndent level. > * @return The formatted string (an empty string upon failure). > */ > public static String format(Element jdom, String indent, int > initalIndent) > { > try > { > XMLOutputter serializer = new XMLOutputter(); > serializer.setIndent(indent); > serializer.setIndentLevel(initalIndent); > return serializer.outputString(jdom); > } > catch (Exception ex) > { > ex.printStackTrace(); > } > > return ""; > } > > /** > * Retrieve a list of attributes specified via an XPath statement. > * > * @param jdom JDOM document root element. > * @param xpathSpec The XPath specification to the desired attributes. > * @return An <code>ArrayList</code> with the attribute values. > */ > public static ArrayList getAttributeList(Element jdom, String > xpathSpec) > { > List attributes = applyXPath(jdom, xpathSpec); > > ArrayList list = new ArrayList( attributes.size() ); > > ListIterator iter = attributes.listIterator(); > while( iter.hasNext() ) > { > Object item = iter.next(); > if (item instanceof Attribute) > list.add( ((Attribute) item).getValue() ); > } > > return list; > } > > /** > * Retrieve a list of text elements specified via an XPath statement. > * > * @param jdom JDOM document root element. > * @param xpathSpec The XPath specification to the elements/attributes. > * @return An <code>ArrayList</code> with the text of the elements. > */ > public static ArrayList getTextList(Element jdom, String xpathSpec) > { > List elements = applyXPath(jdom, xpathSpec); > > ArrayList list = new ArrayList( elements.size() ); > > ListIterator iter = elements.listIterator(); > while( iter.hasNext() ) > { > Object item = iter.next(); > if (item instanceof Element) > list.add( ((Element) item).getText() ); > else if (item instanceof Attribute) > list.add( ((Attribute) item).getValue() ); > } > > return list; > } > > /** > * Apply an XPath to a JDOM Document > * > * @param doc The JDOM Document. > * @param xpathSpec The XPath to apply. > * > * @return A list of selected nodes. > */ > public static List applyXPath(Document doc, String xpathSpec) > { > try > { > XPath xpath = new XPath(xpathSpec); > return xpath.applyTo(doc); > } > catch (Exception ex) > { > Runtime.error("Error while processing applyXPath(\"" + > xpathSpec + "\", " + doc.getRootElement().getName() + "): " + > ex.toString() ); > } > return null; > } > > /** > * Apply an XPath to a JDOM Element. > * > * @param elem The Element context. > * @param xpathSpec The XPath to apply. > * > * @return A list of selected nodes. > */ > public static List applyXPath(Element elem, String xpathSpec) > { > try > { > XPath xpath = new XPath(xpathSpec); > return xpath.applyTo(elem); > } > catch (Exception ex) > { > Runtime.error("Error while processing applyXPath(\"" + > xpathSpec + "\", " + elem.getName() + "): " + > ex.toString() ); > } > return null; > } > > /** > Apply an XPath to a nodeset. > > @param xpathSpec The XPath to apply. > @param doc The nodeset context. > > @return A list of selected nodes. > */ > public static List applyXPath(List nodeSet, String xpathSpec) > { > try > { > XPath xpath = new XPath(xpathSpec); > return xpath.applyTo(nodeSet); > } > catch (Exception ex) > { > Runtime.error("Error while processing applyXPath(\"" + > xpathSpec + "\", (List)): " + > ex.toString() ); > } > return null; > } > > } // end of XmlTool.java > > ## Tidy up DVSL template for the XmlConfigWriter output. > ## The root node must be called ROOT. > ## Usage: > ## dvsl -STYLE xmlConfig_cleanup.dvsl -IN <in> -OUT <out> > ## cat <out> | ~reck/ftp/www/tidy/tidy -xml -quiet -wrap 200 -indent > > <clean> > > ## Double quote for convenience > #set( $qq = '"' ) > > ## Macro to output argument if test evaluates to true > #macro( ifset $test $output ) > #if ( $test )$output#end > #end > > ## print the ID attribute only if it is referenced > #macro( ID $element )#* > *##if( $element.attrib('ID') )#* > *##set( $ID = $element.attrib('ID') )#* > *##if( ($ID == 'ROOT') || > ($element.selectNodes("//[EMAIL PROTECTED]'$ID']").size() > 1) )#* > *# ID="$ID"#* > *##end#* > *##end#* > *##end > #### disable IDs > #macro( ID $element )#**##end > > # possibly emit a NAME attribute > #macro( NAME $element )#* > *##if( $element.attrib('NAME') )#* > *# NAME="$element.attrib('NAME')"#* > *##end#* > *##end > > # possibly emit a CLASS attribute > #macro( CLASS $element )#* > *##if( $element.attrib('CLASS') )#* > *# CLASS="$element.attrib('CLASS')"#* > *##end#* > *##end > > #match( "CONFIGURATION" ) > <CONFIGURATION> > $context.applyTemplates("[EMAIL PROTECTED]'ROOT']") > </CONFIGURATION> > #end > > #match( "[EMAIL PROTECTED]'java.lang.String']" ) > #set( $value = $node.value() ) > #if( $value.trim() == "" ) > <STRING#NAME($node) VALUE="" /> > #else > <STRING#NAME($node)>$value</STRING> > #end > #end > > #match( "[EMAIL PROTECTED]" ) > #set( $ID = $node.attrib('REF') ) > #if( $node.selectNodes("//[EMAIL PROTECTED]'$ID']").size() == 1 ) > $context.applyTemplates( $node.selectSingleNode("//[EMAIL PROTECTED]'$ID']") ) > #else > <OBJECT#ID($node)#NAME($node) REF="$ID" /> > #end > #end > > #match( "OBJECT" ) > #if( $node.value().trim() != "" ) > <OBJECT#ID($node)#NAME($node)#CLASS($node)>$node.value()</OBJECT> > #else > <OBJECT#ID($node)#NAME($node)#CLASS($node)> > $context.applyTemplates("*") > </OBJECT> > #end > #end > > #match( "CONSTRUCTOR" ) > #if( $node.children().isEmpty() ) > <CONSTRUCTOR#ID($node) /> > #else > <CONSTRUCTOR#ID($node)> > $context.applyTemplates("*") > </CONSTRUCTOR> > #end > #end > > #match( "FIELD" ) > <FIELD#ID($node) NAME="$node.attrib('NAME')"#CLASS($node)> > $context.applyTemplates("*") > </FIELD> > #end > > #match( "METHOD" ) > <METHOD#ID($node) NAME="$node.attrib('NAME')"#CLASS($node)> > $context.applyTemplates("*") > </METHOD> > #end > > #match( "ARRAY" ) > <ARRAY#ID($node)#NAME($node)#CLASS($node)> > $context.applyTemplates("*") > </ARRAY> > #end > > #match( "HASH" ) > <HASH#ID($node)#NAME($node)> > $context.applyTemplates("*") > </HASH> > #end > > > #match("*") > $node.copy() > #end > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, e-mail: [EMAIL PROTECTED] >
