jstrachan 2002/09/30 01:05:45
Modified: jelly/src/test/org/apache/commons/jelly/xml
transformExampleAllInLine.jelly
transformExampleSAXOutput.jelly TestXMLTags.java
transformExample.jelly
jelly/src/java/org/apache/commons/jelly/tags/xml
XMLTagLibrary.java ParseTag.java TransformTag.java
jelly/src/test/org/apache/commons/jelly/xml/schematron
transformSchematronExample.jelly
jelly project.xml
Added: jelly/src/test/org/apache/commons/jelly/xml
transformParamExample.xml transformParamExample.xsl
transformExampleXmlVar.jelly
transformParamExample2.jelly
transformExampleXmlVar.xml
transformExampleSAXOutputNestedTransforms.jelly
transformExample5.xsl transformParamExample.jelly
transformExample4.xsl transformExample3.xsl
transformExample2.xsl transformExample1.xsl
jelly/src/java/org/apache/commons/jelly/tags/xml
ParamTag.java
Log:
Applied Robert Leftwich's patches to support efficent SAX based XSLT pipelines via
nested <x:transform> tags. Groovy stuff!
This turns Jelly into a flexible, fast XSLT pipeline engine! Nice work Robert!
There's still a couple of issue to work out but this is looking really neat
Revision Changes Path
1.2 +3 -3
jakarta-commons-sandbox/jelly/src/test/org/apache/commons/jelly/xml/transformExampleAllInLine.jelly
Index: transformExampleAllInLine.jelly
===================================================================
RCS file:
/home/cvs/jakarta-commons-sandbox/jelly/src/test/org/apache/commons/jelly/xml/transformExampleAllInLine.jelly,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- transformExampleAllInLine.jelly 25 Sep 2002 08:37:50 -0000 1.1
+++ transformExampleAllInLine.jelly 30 Sep 2002 08:05:44 -0000 1.2
@@ -2,7 +2,7 @@
<j:jelly xmlns:j="jelly:core" xmlns:x="jelly:xml">
<x:parse var="xsl_doc">
- <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
+ <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="document">
<html>
@@ -16,9 +16,9 @@
</xsl:template>
</xsl:stylesheet>
- </x:parse>
+ </x:parse>
- <x:transform xsl="${xsl_doc}" var="doc" >
+ <x:transform xslt="${xsl_doc}" var="doc" >
<document>
<chapter>It works!</chapter>
</document>
1.2 +14 -14
jakarta-commons-sandbox/jelly/src/test/org/apache/commons/jelly/xml/transformExampleSAXOutput.jelly
Index: transformExampleSAXOutput.jelly
===================================================================
RCS file:
/home/cvs/jakarta-commons-sandbox/jelly/src/test/org/apache/commons/jelly/xml/transformExampleSAXOutput.jelly,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- transformExampleSAXOutput.jelly 26 Sep 2002 12:28:21 -0000 1.1
+++ transformExampleSAXOutput.jelly 30 Sep 2002 08:05:44 -0000 1.2
@@ -2,7 +2,7 @@
<j:jelly xmlns:j="jelly:core" xmlns:x="jelly:xml">
<x:parse var="xsl_doc">
- <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
+ <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="document">
<html>
@@ -16,20 +16,20 @@
</xsl:template>
</xsl:stylesheet>
- </x:parse>
+ </x:parse>
- <!-- here we're testing if the output of the XSLT comes out as SAX events
- || that the <x:parse> tag can then parse.
- || We're using the <x:parse> around the <x:transform> purely to test
- || that the <x:transform> is capable of outputting SAX events -->
- <x:parse var="doc">
- <x:transform xsl="${xsl_doc}">
- <document>
- <chapter>It works!</chapter>
- </document>
- </x:transform>
- </x:parse>
-
+ <!-- here we're testing if the output of the XSLT comes out as SAX events
+ || that the <x:parse> tag can then parse.
+ || We're using the <x:parse> around the <x:transform> purely to test
+ || that the <x:transform> is capable of outputting SAX events -->
+ <x:parse var="doc">
+ <x:transform xslt="${xsl_doc}">
+ <document>
+ <chapter>It works!</chapter>
+ </document>
+ </x:transform>
+ </x:parse>
+
<x:expr select="$doc/html/title"/>
</j:jelly>
1.7 +34 -5
jakarta-commons-sandbox/jelly/src/test/org/apache/commons/jelly/xml/TestXMLTags.java
Index: TestXMLTags.java
===================================================================
RCS file:
/home/cvs/jakarta-commons-sandbox/jelly/src/test/org/apache/commons/jelly/xml/TestXMLTags.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- TestXMLTags.java 26 Sep 2002 12:28:21 -0000 1.6
+++ TestXMLTags.java 30 Sep 2002 08:05:44 -0000 1.7
@@ -139,7 +139,7 @@
);
assertEquals("Produces the correct output", "It works!", text);
}
-
+
public void testTransformAllInLine() throws Exception {
String text = evaluteScriptAsText(
"src/test/org/apache/commons/jelly/xml/transformExampleAllInLine.jelly"
@@ -147,6 +147,21 @@
assertEquals("Produces the correct output", "It works!", text);
}
+ public void testTransformParams() throws Exception {
+ String text = evaluteScriptAsText(
+ "src/test/org/apache/commons/jelly/xml/transformParamExample.jelly"
+ );
+ assertEquals("Produces the correct output", "It works!", text);
+ }
+
+ public void testTransformParamsInLine() throws Exception {
+
+ String text = evaluteScriptAsText(
+ "src/test/org/apache/commons/jelly/xml/transformParamExample2.jelly"
+ );
+ assertEquals("Produces the correct output", "It works!", text);
+ }
+
public void testTransformSAXOutput() throws Exception {
String text = evaluteScriptAsText(
"src/test/org/apache/commons/jelly/xml/transformExampleSAXOutput.jelly"
@@ -154,6 +169,13 @@
assertEquals("Produces the correct output", "It works!", text);
}
+ public void testTransformSAXOutputNestedTransforms() throws Exception {
+ String text = evaluteScriptAsText(
+
"src/test/org/apache/commons/jelly/xml/transformExampleSAXOutputNestedTransforms.jelly"
+ );
+ assertEquals("Produces the correct output", "It works!", text);
+ }
+
public void testTransformSchematron() throws Exception {
String text = evaluteScriptAsText(
"src/test/org/apache/commons/jelly/xml/schematron/transformSchematronExample.jelly"
@@ -161,6 +183,13 @@
assertEquals("Produces the correct output", "Report count=1:assert
count=2", text);
}
+ public void testTransformXmlVar() throws Exception {
+ String text = evaluteScriptAsText(
+ "src/test/org/apache/commons/jelly/xml/transformExampleXmlVar.jelly"
+ );
+ assertEquals("Produces the correct output", "It works!", text);
+ }
+
public void runUnitTest(String name) throws Exception {
Document document = parseUnitTest(name);
@@ -192,20 +221,20 @@
}
/**
- * Evaluates the script by the given file name and
+ * Evaluates the script by the given file name and
* returns the whitespace trimmed output as text
*/
protected String evaluteScriptAsText(String fileName) throws Exception {
JellyContext context = new JellyContext();
-
+
// allow scripts to refer to any resource inside this project
// using an absolute URI like /src/test/org/apache/foo.xml
context.setRootURL(new File(".").toURL());
-
+
// cature the output
StringWriter buffer = new StringWriter();
XMLOutput output = XMLOutput.createXMLOutput(buffer);
-
+
context.runScript( new File(fileName), output );
String text = buffer.toString().trim();
if (log.isDebugEnabled()) {
1.2 +1 -1
jakarta-commons-sandbox/jelly/src/test/org/apache/commons/jelly/xml/transformExample.jelly
Index: transformExample.jelly
===================================================================
RCS file:
/home/cvs/jakarta-commons-sandbox/jelly/src/test/org/apache/commons/jelly/xml/transformExample.jelly,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- transformExample.jelly 25 Sep 2002 08:37:50 -0000 1.1
+++ transformExample.jelly 30 Sep 2002 08:05:44 -0000 1.2
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<j:jelly xmlns:j="jelly:core" xmlns:x="jelly:xml">
- <x:transform xsl="transformExample.xsl" var="doc" >
+ <x:transform xslt="transformExample.xsl" var="doc" >
<document>
<chapter>It works!</chapter>
</document>
1.1
jakarta-commons-sandbox/jelly/src/test/org/apache/commons/jelly/xml/transformParamExample.xml
Index: transformParamExample.xml
===================================================================
<?xml version="1.0"?>
<doc>Hello</doc>
1.1
jakarta-commons-sandbox/jelly/src/test/org/apache/commons/jelly/xml/transformParamExample.xsl
Index: transformParamExample.xsl
===================================================================
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:param name="param1" select="'default value'"/>
<xsl:template match="doc">
<out><xsl:value-of select="$param1"/></out>
</xsl:template>
</xsl:stylesheet>
1.1
jakarta-commons-sandbox/jelly/src/test/org/apache/commons/jelly/xml/transformExampleXmlVar.jelly
Index: transformExampleXmlVar.jelly
===================================================================
<?xml version="1.0"?>
<j:jelly xmlns:j="jelly:core" xmlns:x="jelly:xml">
<x:transform xslt="transformExample.xsl" xml="transformExampleXmlVar.xml"
var="doc"/>
<x:expr select="$doc/html/title"/>
</j:jelly>
1.1
jakarta-commons-sandbox/jelly/src/test/org/apache/commons/jelly/xml/transformParamExample2.jelly
Index: transformParamExample2.jelly
===================================================================
<?xml version="1.0"?>
<j:jelly xmlns:j="jelly:core" xmlns:x="jelly:xml">
<x:parse var="xsl_doc">
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:param name="param1" select="'default value 1'"/>
<xsl:param name="param2" select="'default value 2'"/>
<xsl:template match="doc">
<out><xsl:value-of select="$param1"/><xsl:value-of
select="$param2"/></out>
</xsl:template>
</xsl:stylesheet>
</x:parse>
<x:transform xslt="${xsl_doc}" var="doc">
<doc>Hello</doc>
<x:param name="param1" value="It "/>
<x:param name="param2">works!</x:param>
</x:transform>
<x:expr select="$doc/out"/>
</j:jelly>
1.1
jakarta-commons-sandbox/jelly/src/test/org/apache/commons/jelly/xml/transformExampleXmlVar.xml
Index: transformExampleXmlVar.xml
===================================================================
<?xml version="1.0"?>
<document>
<chapter>It works!</chapter>
</document>
1.1
jakarta-commons-sandbox/jelly/src/test/org/apache/commons/jelly/xml/transformExampleSAXOutputNestedTransforms.jelly
Index: transformExampleSAXOutputNestedTransforms.jelly
===================================================================
<?xml version="1.0"?>
<j:jelly xmlns:j="jelly:core" xmlns:x="jelly:xml" xmlns:log="jelly:log">
<x:transform xslt="transformExample5.xsl" var="doc">
<x:transform xslt="transformExample4.xsl">
<x:transform xslt="transformExample3.xsl">
<x:transform xslt="transformExample2.xsl">
<x:transform xslt="transformExample1.xsl">
<document>
<chapter>It works!</chapter>
</document>
</x:transform>
</x:transform>
</x:transform>
</x:transform>
</x:transform>
<x:expr select="$doc/data5/data5_title"/>
</j:jelly>
1.1
jakarta-commons-sandbox/jelly/src/test/org/apache/commons/jelly/xml/transformExample5.xsl
Index: transformExample5.xsl
===================================================================
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="data4">
<data5>
<xsl:apply-templates/>
<data5_body></data5_body>
</data5>
</xsl:template>
<xsl:template match="data4_title">
<data5_title><xsl:apply-templates/></data5_title>
</xsl:template>
</xsl:stylesheet>
1.1
jakarta-commons-sandbox/jelly/src/test/org/apache/commons/jelly/xml/transformParamExample.jelly
Index: transformParamExample.jelly
===================================================================
<?xml version="1.0"?>
<j:jelly xmlns:j="jelly:core" xmlns:x="jelly:xml">
<x:transform xslt="transformParamExample.xsl" var="doc"
xml="transformParamExample.xml">
<x:param name="param1" value="It works!"/>
</x:transform>
<x:expr select="$doc/out"/>
</j:jelly>
1.1
jakarta-commons-sandbox/jelly/src/test/org/apache/commons/jelly/xml/transformExample4.xsl
Index: transformExample4.xsl
===================================================================
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="data3">
<data4>
<xsl:apply-templates/>
<data4_body></data4_body>
</data4>
</xsl:template>
<xsl:template match="data3_title">
<data4_title><xsl:apply-templates/></data4_title>
</xsl:template>
</xsl:stylesheet>
1.1
jakarta-commons-sandbox/jelly/src/test/org/apache/commons/jelly/xml/transformExample3.xsl
Index: transformExample3.xsl
===================================================================
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="data2">
<data3>
<xsl:apply-templates/>
<data3_body></data3_body>
</data3>
</xsl:template>
<xsl:template match="data2_title">
<data3_title><xsl:apply-templates/></data3_title>
</xsl:template>
</xsl:stylesheet>
1.1
jakarta-commons-sandbox/jelly/src/test/org/apache/commons/jelly/xml/transformExample2.xsl
Index: transformExample2.xsl
===================================================================
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="data1">
<data2>
<xsl:apply-templates/>
<data2_body></data2_body>
</data2>
</xsl:template>
<xsl:template match="data1_title">
<data2_title><xsl:apply-templates/></data2_title>
</xsl:template>
</xsl:stylesheet>
1.1
jakarta-commons-sandbox/jelly/src/test/org/apache/commons/jelly/xml/transformExample1.xsl
Index: transformExample1.xsl
===================================================================
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="document">
<data1>
<xsl:apply-templates/>
<data1_body></data1_body>
</data1>
</xsl:template>
<xsl:template match="chapter">
<data1_title><xsl:apply-templates/></data1_title>
</xsl:template>
</xsl:stylesheet>
1.12 +15 -14
jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/xml/XMLTagLibrary.java
Index: XMLTagLibrary.java
===================================================================
RCS file:
/home/cvs/jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/xml/XMLTagLibrary.java,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- XMLTagLibrary.java 25 Sep 2002 08:37:50 -0000 1.11
+++ XMLTagLibrary.java 30 Sep 2002 08:05:45 -0000 1.12
@@ -56,7 +56,7 @@
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
- *
+ *
* $Id$
*/
package org.apache.commons.jelly.tags.xml;
@@ -82,7 +82,7 @@
/** The Log to which logging calls will be made. */
private Log log = LogFactory.getLog(XMLTagLibrary.class);
-
+
public XMLTagLibrary() {
registerTag("out", ExprTag.class);
registerTag("if", IfTag.class);
@@ -90,7 +90,8 @@
registerTag("parse", ParseTag.class);
registerTag("set", SetTag.class);
registerTag("transform", TransformTag.class);
-
+ registerTag("param", ParamTag.class);
+
// extensions to JSTL
registerTag("expr", ExprTag.class);
registerTag("element", ElementTag.class);
@@ -106,21 +107,21 @@
String attributeValue) throws Exception {
// #### may need to include some namespace URI information in the XPath
instance?
-
- if (attributeName.equals("select")) {
+
+ if (attributeName.equals("select")) {
if ( log.isDebugEnabled() ) {
log.debug( "Parsing XPath expression: " + attributeValue );
}
-
+
try {
XPath xpath = new Dom4jXPath(attributeValue);
return new XPathExpression(xpath);
}
catch (JaxenException e) {
- throw new JellyException( "Could not parse XPath expression: \"" +
attributeValue + "\" reason: " + e, e );
- }
+ throw new JellyException( "Could not parse XPath expression: \"" +
attributeValue + "\" reason: " + e, e );
+ }
}
-
+
// will use the default expression instead
return super.createExpression(factory, tagName, attributeName,
attributeValue);
}
1.12 +20 -14
jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/xml/ParseTag.java
Index: ParseTag.java
===================================================================
RCS file:
/home/cvs/jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/xml/ParseTag.java,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- ParseTag.java 25 Sep 2002 08:37:50 -0000 1.11
+++ ParseTag.java 30 Sep 2002 08:05:45 -0000 1.12
@@ -56,7 +56,7 @@
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
- *
+ *
* $Id$
*/
package org.apache.commons.jelly.tags.xml;
@@ -92,7 +92,7 @@
}
// Tag interface
- //-------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
public void doTag(XMLOutput output) throws Exception {
if (getVar() == null) {
throw new IllegalArgumentException("The var attribute cannot be null");
@@ -100,9 +100,14 @@
Document document = getXmlDocument(output);
context.setVariable(getVar(), document);
}
-
+
// Properties
- //-------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
+ /** Gets the source of the XML which is either a String URI, Reader or
InputStream */
+ public Object getXml() {
+ return this.xml;
+ }
+
/** Sets the source of the XML which is either a String URI, Reader or
InputStream */
public void setXml(Object xml) {
this.xml = xml;
@@ -120,22 +125,23 @@
// Implementation methods
- //-------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
/**
* Factory method to create a new SAXReader
- */
+ */
protected SAXReader createSAXReader() throws Exception {
return new SAXReader(validate);
}
-
+
protected Document getXmlDocument(XMLOutput output) throws Exception {
Document document = null;
- if (xml == null) {
+ Object xmlObj = this.getXml();
+ if (xmlObj == null) {
document = parseBody(output);
}
else {
- document = parse(xml);
+ document = parse(xmlObj);
}
return document;
}
1.3 +528 -50
jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/xml/TransformTag.java
Index: TransformTag.java
===================================================================
RCS file:
/home/cvs/jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/xml/TransformTag.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- TransformTag.java 26 Sep 2002 12:28:21 -0000 1.2
+++ TransformTag.java 30 Sep 2002 08:05:45 -0000 1.3
@@ -61,24 +61,48 @@
*/
package org.apache.commons.jelly.tags.xml;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.net.URL;
+import java.util.Iterator;
+import java.util.List;
+
import javax.xml.transform.Result;
import javax.xml.transform.Source;
-import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.URIResolver;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.sax.SAXSource;
+import javax.xml.transform.sax.SAXTransformerFactory;
+import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamSource;
+import org.apache.commons.jelly.Script;
+import org.apache.commons.jelly.Tag;
import org.apache.commons.jelly.XMLOutput;
-
+import org.apache.commons.jelly.impl.ScriptBlock;
+import org.apache.commons.jelly.impl.StaticTagScript;
+import org.apache.commons.jelly.impl.BeanTagScript;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-
import org.dom4j.Document;
import org.dom4j.io.DocumentResult;
import org.dom4j.io.DocumentSource;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.DTDHandler;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.ext.LexicalHandler;
+import org.xml.sax.helpers.XMLReaderFactory;
/** A tag which parses some XML, applies an xslt transform to it
* and defines a variable with the transformed Document.
@@ -86,9 +110,9 @@
* xml property which can be a Reader, InputStream, URL or String URI.
*
* The XSL can be passed in via the
- * xsl property which can be a Reader, InputStream, URL or String URI.
+ * xslt property which can be a Reader, InputStream, URL or String URI.
*
- * @author <a href="mailto:[EMAIL PROTECTED]">Robert Leftwich</a>
+ * @author Robert Leftwich
* @version $Revision$
*/
public class TransformTag extends ParseTag {
@@ -96,18 +120,25 @@
/** The Log to which logging calls will be made. */
private static final Log log = LogFactory.getLog(TransformTag.class);
- /** The xsl to parse, either a String URI, a Reader or InputStream */
- private Object xsl;
+ /** Propert name for lexical handler */
+ private static final String LEXICAL_HANDLER_PROPERTY =
+ "http://xml.org/sax/properties/lexical-handler";
+
+ /** The xslt to parse, either a String URI, a Reader or InputStream */
+ private Object xslt;
/** The xsl transformer factory */
- private TransformerFactory tf;
+ private SAXTransformerFactory tf;
+
+ /** the transformer handler, doing the real work */
+ private TransformerHandler transformerHandler;
/**
* Constructor for TransformTag.
*/
public TransformTag() {
super();
- tf = TransformerFactory.newInstance();
+ this.tf = (SAXTransformerFactory) TransformerFactory.newInstance();
}
// Tag interface
@@ -120,29 +151,41 @@
* @throws Exception - when required attributes are missing
*/
public void doTag(XMLOutput output) throws Exception {
- Document xmlDocument = this.getXmlDocument(output);
- Document xslDocument = this.parse(this.xsl);
-
- tf.setURIResolver(createURIResolver());
- Transformer transformer = tf.newTransformer(new
DocumentSource(xslDocument));
- DocumentSource xmlDocSource = new DocumentSource(xmlDocument);
+ if (null == this.getXslt()) {
+ throw new IllegalArgumentException("The xslt attribute cannot be null");
+ }
- String var = getVar();
- if (var == null) {
+ // set a resolver to locate uri
+ this.tf.setURIResolver(createURIResolver());
+ this.transformerHandler =
+ this.tf.newTransformerHandler(this.getObjAsSAXSource(this.getXslt()));
+
+ // run any nested param tags
+ this.doNestedParamTag(output);
+
+ // get a reader to provide SAX events to transformer
+ XMLReader xmlReader = this.createXMLReader();
+ xmlReader.setContentHandler(this.transformerHandler);
+ xmlReader.setProperty(LEXICAL_HANDLER_PROPERTY, this.transformerHandler);
+
+ // handle result differently, depending on if var is specified
+ String varName = this.getVar();
+ if (null == varName) {
// pass the result of the transform out as SAX events
- Result result = createSAXResult(output);
- transformer.transform(xmlDocSource, result);
+ this.transformerHandler.setResult(this.createSAXResult(output));
+ xmlReader.parse(this.getXMLInputSource());
}
else {
+ // pass the result of the transform out as a document
DocumentResult result = new DocumentResult();
- transformer.transform(xmlDocSource, result);
+ this.transformerHandler.setResult(result);
+ xmlReader.parse(this.getXMLInputSource());
// output the result as a variable
Document transformedDoc = result.getDocument();
- context.setVariable(var, transformedDoc);
+ this.context.setVariable(varName, transformedDoc);
}
-
}
@@ -150,32 +193,37 @@
//-------------------------------------------------------------------------
/**
- * Sets the source of the XSL which is either a String URI, Reader or
InputStream
+ * Gets the source of the XSL which is either a String URI, Reader or
+ * InputStream
*
- * @param xsl The source of the xsl
+ * @returns xslt The source of the xslt
*/
- public void setXsl(Object xsl) {
- this.xsl = xsl;
+ public Object getXslt() {
+ return this.xslt;
}
- // Implementation methods
- //-------------------------------------------------------------------------
-
/**
- * Parses the given source
- * @see org.apache.commons.jelly.tags.xml.ParseTagSupport#parse(Object)
+ * Sets the source of the XSL which is either a String URI, Reader or
+ * InputStream
+ *
+ * @param xslt The source of the xslt
*/
- protected Document parse(Object source) throws Exception {
- if (source instanceof Document) {
- return (Document) source;
- } else {
- return super.parse(source);
- }
+ public void setXslt(Object xslt) {
+ this.xslt = xslt;
+ }
+
+ public void setParameterValue(String name, Object value) {
+ this.transformerHandler.getTransformer().setParameter(name, value);
}
+ // Implementation methods
+ //-------------------------------------------------------------------------
+
/**
- * Creates a new URI Resolver so that URIs inside the XSLT document can be
resolved using
- * the JellyContext
+ * Creates a new URI Resolver so that URIs inside the XSLT document can be
+ * resolved using the JellyContext
+ *
+ * @return a URI Resolver for the JellyContext
*/
protected URIResolver createURIResolver() {
return new URIResolver() {
@@ -183,31 +231,461 @@
throws TransformerException {
if (log.isDebugEnabled() ) {
- log.info( "base: " + base + " href: " + href );
+ log.debug( "base: " + base + " href: " + href );
}
-
+
// pass if we don't have a systemId
- if (href == null)
+ if (null == href)
return null;
- // @todo
+ // @todo
// #### this is a pretty simplistic implementation.
// #### we should really handle this better such that if
- // #### base is specified as an absolute URL
+ // #### base is specified as an absolute URL
// #### we trim the end off it and append href
return new StreamSource(context.getResourceAsStream(href));
}
};
}
-
+
/**
* Factory method to create a new SAXResult for the given
* XMLOutput so that the output of an XSLT transform will go
* directly into the XMLOutput that we are given.
+ *
+ * @param output The destination of the transform output
+ * @return A SAXResult for the transfrom output
*/
protected Result createSAXResult(XMLOutput output) {
SAXResult result = new SAXResult(output);
result.setLexicalHandler(output);
return result;
}
+
+ /**
+ * Factory method to create a new XMLReader for this tag
+ * so that the input of the XSLT transform comes from
+ * either the xml var, the nested tag or the tag body.
+ *
+ * @return XMLReader for the transform input
+ * @throws SAXException
+ * If the value of the "org.xml.sax.driver" system property
+ * is null, or if the class cannot be loaded and instantiated.
+ */
+ protected XMLReader createXMLReader() throws SAXException {
+ XMLReader xmlReader = null;
+ Object xmlReaderSourceObj = this.getXml();
+ // if no xml source specified then get from body
+ // otherwise convert it to a SAX source
+ if (null == xmlReaderSourceObj) {
+ xmlReader = new TagBodyXMLReader(this);
+ }
+ else {
+ xmlReader = XMLReaderFactory.createXMLReader();
+ }
+
+ return xmlReader;
+ }
+
+ /**
+ * Helper method to get the appropriate xml input source
+ * so that the input of the XSLT transform comes from
+ * either the xml var, the nested tag or the tag body.
+ *
+ * @return InputSource for the transform input
+ */
+ protected InputSource getXMLInputSource() {
+ InputSource xmlInputSource = null;
+ Object xmlInputSourceObj = this.getXml();
+ // if no xml source specified then get from tag body
+ // otherwise convert it to an input source
+ if (null == xmlInputSourceObj) {
+ xmlInputSource = new TagBodyInputSource();
+ } else {
+ xmlInputSource = this.getInputSourceFromObj(xmlInputSourceObj);
+ }
+ return xmlInputSource;
+ }
+
+ /**
+ * Helper method to convert the specified object to a SAX source
+ *
+ * @return SAXSource from the source object or null
+ */
+ protected SAXSource getObjAsSAXSource(Object saxSourceObj)
+ throws Exception {
+ SAXSource saxSource = null;
+ if (null != saxSourceObj) {
+ if (saxSourceObj instanceof Document) {
+ saxSource = new DocumentSource((Document) saxSourceObj);
+ } else {
+ InputSource xmlInputSource =
+ this.getInputSourceFromObj(saxSourceObj);
+ saxSource = new SAXSource(xmlInputSource);
+ }
+ }
+
+ return saxSource;
+ }
+
+ /**
+ * Helper method to get an xml input source for the supplied object
+ *
+ * @return InputSource for the object or null
+ */
+ protected InputSource getInputSourceFromObj(Object sourceObj ) {
+ InputSource xmlInputSource = null;
+ if (sourceObj instanceof Document) {
+ SAXSource saxSource = new DocumentSource((Document) sourceObj);
+ xmlInputSource = saxSource.getInputSource();
+ } else {
+ if (sourceObj instanceof String) {
+ String uri = (String) sourceObj;
+ xmlInputSource = new InputSource(context.getResourceAsStream(uri));
+ }
+ else if (sourceObj instanceof Reader) {
+ xmlInputSource = new InputSource((Reader) sourceObj);
+ }
+ else if (sourceObj instanceof InputStream) {
+ xmlInputSource = new InputSource((InputStream) sourceObj);
+ }
+ else if (sourceObj instanceof URL) {
+ String uri = ((URL) sourceObj).toString();
+ xmlInputSource = new InputSource(context.getResourceAsStream(uri));
+ }
+ else {
+ throw new IllegalArgumentException(
+ "Invalid source argument. Must be a String, Reader, InputStream
or URL."
+ + " Was type; "
+ + sourceObj.getClass().getName()
+ + " with value: "
+ + sourceObj);
+ }
+ }
+
+ return xmlInputSource;
+ }
+
+ /**
+ * Helper method to run any nested param tags
+ *
+ * @param output The destination for any SAX output (not actually used)
+ */
+ private void doNestedParamTag(XMLOutput output) throws Exception {
+ // find any nested param tags and run them
+ Script bodyScript = this.getBody();
+ if (bodyScript instanceof ScriptBlock) {
+ ScriptBlock scriptBlock = (ScriptBlock) bodyScript;
+ List scriptList = scriptBlock.getScriptList();
+ for (Iterator iter = scriptList.iterator(); iter.hasNext(); ) {
+ Script script = (Script) iter.next();
+ if (script instanceof BeanTagScript) {
+ Tag tag = ((BeanTagScript) script).getTag();
+ if (tag instanceof ParamTag) {
+ script.run(context, output);
+ }
+
+ }
+ }
+ }
+ }
+
+ /** A helper class that converts a transform tag body to an XMLReader
+ * to hide the details of where the input for the transform is obtained
+ *
+ * @author <a href="mailto:[EMAIL PROTECTED]">Robert Leftwich</a>
+ * @version $Revision$
+ */
+ private class TagBodyXMLReader implements XMLReader {
+
+ /** The tag whose body is to be read. */
+ private Tag tag;
+
+ /** The destination for the sax events generated by the reader. */
+ private XMLOutput xmlOutput;
+
+ /** Storage for a DTDHandler if set by the user of the reader. */
+ private DTDHandler dtdHandler;
+
+ /** Storage for a ErrorHandler if set by the user of the reader. */
+ private ErrorHandler errorHandler;
+
+ /** Storage for a EntityResolver if set by the user of the reader. */
+ private EntityResolver entityResolver;
+
+ /**
+ * Construct an XMLReader for the specified Tag
+ *
+ * @param tag The Tag to convert to an XMLReader
+ */
+ public TagBodyXMLReader(Tag tag)
+ {
+ this.tag = tag;
+ this.xmlOutput = new XMLOutput();
+ }
+
+ // Methods
+ //-------------------------------------------------------------------------
+
+ /**
+ * Parse an XML source.
+ *
+ * @param input The source of the xml
+ * @throws SAXException -
+ * Any SAX exception, possibly wrapping another exception.
+ * @throws IOException -
+ * An IO exception from the parser, possibly from a byte
+ stream or character stream supplied by the application.
+ */
+ public void parse(InputSource input)
+ throws IOException, SAXException
+ {
+ // safety check that we are being used correctly
+ if (input instanceof TagBodyInputSource) {
+ this.doInvokeBody();
+ } else {
+ throw new SAXException("Invalid input source");
+ }
+ }
+
+ /**
+ * Parse an XML source specified by a system id
+ *
+ * @param input The system identifier (URI)
+ * @throws SAXException -
+ * Any SAX exception, possibly wrapping another exception.
+ * @throws IOException -
+ * An IO exception from the parser, possibly from a byte
+ stream or character stream supplied by the application.
+ */
+ public void parse(String systemId)
+ throws IOException, SAXException
+ {
+ this.doInvokeBody();
+ }
+
+ // Helper methods
+ //-------------------------------------------------------------------------
+
+ /**
+ * Actually invoke the tag body to generate the SAX events
+ *
+ * @throws SAXException -
+ * Any SAX exception, possibly wrapping another exception.
+ */
+ private void doInvokeBody() throws SAXException {
+ try {
+ if (this.shouldParseBody()) {
+ XMLReader anXMLReader = XMLReaderFactory.createXMLReader();
+ anXMLReader.setContentHandler(this.xmlOutput);
+
anXMLReader.setProperty(LEXICAL_HANDLER_PROPERTY,this.xmlOutput);
+ StringWriter writer = new StringWriter();
+ this.tag.invokeBody(XMLOutput.createXMLOutput(writer));
+ Reader reader = new StringReader(writer.toString());
+ anXMLReader.parse(new InputSource(reader));
+ } else {
+ this.tag.invokeBody(this.xmlOutput);
+ }
+ } catch (Exception ex) {
+ throw new SAXException(ex);
+ }
+ }
+
+ /**
+ * Helper method to determin if nested body needs to be parsed by (an
+ * xml parser, i.e. its only text) to generate SAX events or not
+ *
+ * @return True if tag body should be parsed or false if invoked only
+ */
+ private boolean shouldParseBody() {
+ boolean result = false;
+ // check to see if we need to parse the body or just invoke it
+ Script bodyScript = this.tag.getBody();
+ if (bodyScript instanceof ScriptBlock) {
+ ScriptBlock scriptBlock = (ScriptBlock) bodyScript;
+ List scriptList = scriptBlock.getScriptList();
+ for (Iterator iter = scriptList.iterator(); iter.hasNext(); ) {
+ Script script = (Script) iter.next();
+ if (script instanceof StaticTagScript) {
+ result = true;
+ break;
+ }
+ }
+ }
+ return result;
+ }
+
+ // Properties
+ //-------------------------------------------------------------------------
+
+ /**
+ * Gets the SAX ContentHandler to feed SAX events into
+ *
+ * @return the SAX ContentHandler to use to feed SAX events into
+ */
+ public ContentHandler getContentHandler() {
+ return this.xmlOutput.getContentHandler();
+ }
+
+ /**
+ * Sets the SAX ContentHandler to feed SAX events into
+ *
+ * @param contentHandler is the ContentHandler to use.
+ * This value cannot be null.
+ */
+ public void setContentHandler(ContentHandler contentHandler) {
+ this.xmlOutput.setContentHandler(contentHandler);
+ // often classes will implement LexicalHandler as well
+ if (contentHandler instanceof LexicalHandler) {
+ this.xmlOutput.setLexicalHandler((LexicalHandler) contentHandler);
+ }
+ }
+
+ /**
+ * Gets the DTD Handler to feed SAX events into
+ *
+ * @return the DTD Handler to use to feed SAX events into
+ */
+ public DTDHandler getDTDHandler() {
+ return this.dtdHandler;
+ }
+
+ /**
+ * Sets the DTD Handler to feed SAX events into
+ *
+ * @param the DTD Handler to use to feed SAX events into
+ */
+ public void setDTDHandler(DTDHandler dtdHandler) {
+ this.dtdHandler = dtdHandler;
+ }
+
+ /**
+ * Gets the Error Handler to feed SAX events into
+ *
+ * @return the Error Handler to use to feed SAX events into
+ */
+ public ErrorHandler getErrorHandler() {
+ return this.errorHandler;
+ }
+
+ /**
+ * Sets the Error Handler to feed SAX events into
+ *
+ * @param the Error Handler to use to feed SAX events into
+ */
+ public void setErrorHandler(ErrorHandler errorHandler) {
+ // save the error handler
+ this.errorHandler = errorHandler;
+ }
+
+ /**
+ * Gets the Entity Resolver to feed SAX events into
+ *
+ * @return the Entity Resolver to use to feed SAX events into
+ */
+ public EntityResolver getEntityResolver() {
+ return this.entityResolver;
+ }
+
+ /**
+ * Sets the Entity Resolver to feed SAX events into
+ *
+ * @param the Entity Resolver to use to feed SAX events into
+ */
+ public void setEntityResolver(EntityResolver entityResolver) {
+ this.entityResolver = entityResolver;
+ }
+
+ /**
+ * Lookup the value of a property
+ *
+ * @param name - The property name, which is a fully-qualified URI.
+ * @return - The current value of the property.
+ * @throws SAXNotRecognizedException -
+ * When the XMLReader does not recognize the property name.
+ * @throws SAXNotSupportedException -
+ * When the XMLReader recognizes the property name but
+ * cannot determine its value at this time.
+ */
+ public Object getProperty(String name)
+ throws SAXNotRecognizedException, SAXNotSupportedException
+ {
+ // respond to the lexical handler request
+ if (name.equalsIgnoreCase(LEXICAL_HANDLER_PROPERTY)) {
+ return this.xmlOutput.getLexicalHandler();
+ } else {
+ // do nothing
+ return null;
+ }
+ }
+
+ /**
+ * Set the value of a property
+ *
+ * @param name - The property name, which is a fully-qualified URI.
+ * @param value - The property value
+ * @throws SAXNotRecognizedException -
+ * When the XMLReader does not recognize the property name.
+ * @throws SAXNotSupportedException -
+ * When the XMLReader recognizes the property name but
+ * cannot determine its value at this time.
+ */
+ public void setProperty(String name, Object value)
+ throws SAXNotRecognizedException, SAXNotSupportedException
+ {
+ // respond to the lexical handler setting
+ if (name.equalsIgnoreCase(LEXICAL_HANDLER_PROPERTY)) {
+ this.xmlOutput.setLexicalHandler((LexicalHandler) value);
+ }
+ }
+
+ /**
+ * Lookup the value of a feature
+ *
+ * @param name - The feature name, which is a fully-qualified URI.
+ * @return - The current state of the feature (true or false)
+ * @throws SAXNotRecognizedException -
+ * When the XMLReader does not recognize the feature name.
+ * @throws SAXNotSupportedException -
+ * When the XMLReader recognizes the feature name but
+ * cannot determine its value at this time.
+ */
+ public boolean getFeature(String name)
+ throws SAXNotRecognizedException, SAXNotSupportedException
+ {
+ // do nothing
+ return false;
+ }
+
+ /**
+ * Set the value of a feature
+ *
+ * @param name - The feature name, which is a fully-qualified URI.
+ * @param value - The current state of the feature (true or false)
+ * @throws SAXNotRecognizedException -
+ * When the XMLReader does not recognize the feature name.
+ * @throws SAXNotSupportedException -
+ * When the XMLReader recognizes the feature name but
+ * cannot determine its value at this time.
+ */
+ public void setFeature(String name, boolean value)
+ throws SAXNotRecognizedException, SAXNotSupportedException
+ {
+ // do nothing
+ }
+ }
+
+ /** A marker class used by the TagBodyXMLReader as a sanity check
+ * (i.e. The source is not actually used)
+ *
+ */
+ private class TagBodyInputSource extends InputSource {
+
+ /**
+ * Construct an instance of this marker class
+ */
+ public TagBodyInputSource() {
+ }
+ }
+
}
1.1
jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/xml/ParamTag.java
Index: ParamTag.java
===================================================================
/*
* $Header$
* $Revision$
* $Date$
*
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999-2002 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/>.
*
* $Id$
*/
package org.apache.commons.jelly.tags.xml;
import org.apache.commons.jelly.JellyContext;
import org.apache.commons.jelly.JellyException;
import org.apache.commons.jelly.TagSupport;
import org.apache.commons.jelly.XMLOutput;
/** Sets a parameter in the parent transform tag
*
* @author Robert Leftwich
* @version $Revision$
*/
public class ParamTag extends TagSupport {
/** the name of the attribute. */
private String name;
/** the value of the attribute. */
private Object value;
public ParamTag() {
}
// Tag interface
//-------------------------------------------------------------------------
public void doTag(XMLOutput output) throws Exception {
TransformTag tag = (TransformTag) this.findAncestorWithClass(
TransformTag.class );
if ( tag == null ) {
throw new JellyException( "<param> tag must be enclosed inside a
<transform> tag" );
}
Object value = this.getValue();
tag.setParameterValue( this.getName(),
(null == value ? this.getBodyText(): value));
}
// Properties
//-------------------------------------------------------------------------
/**
* @return the name of the attribute.
*/
public String getName() {
return name;
}
/**
* Sets the name of the attribute
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the value of the attribute.
*/
public Object getValue() {
return value;
}
/**
* Sets the value of the attribute
*/
public void setValue(Object value) {
this.value = value;
}
}
1.2 +5 -5
jakarta-commons-sandbox/jelly/src/test/org/apache/commons/jelly/xml/schematron/transformSchematronExample.jelly
Index: transformSchematronExample.jelly
===================================================================
RCS file:
/home/cvs/jakarta-commons-sandbox/jelly/src/test/org/apache/commons/jelly/xml/schematron/transformSchematronExample.jelly,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- transformSchematronExample.jelly 25 Sep 2002 08:37:50 -0000 1.1
+++ transformSchematronExample.jelly 30 Sep 2002 08:05:45 -0000 1.2
@@ -1,17 +1,17 @@
<?xml version="1.0"?>
<j:jelly xmlns:j="jelly:core" xmlns:x="jelly:xml">
- <x:transform
+ <x:transform
xml="test-schematron.xml"
- xsl="schematron-wrapper.xsl"
+ xslt="schematron-wrapper.xsl"
var="test_schematron"/>
- <x:transform
+ <x:transform
xml="source.xml"
- xsl="${test_schematron}" var="doc"/>
+ xslt="${test_schematron}" var="doc"/>
Report count=<x:expr select="count($doc//report)"/>:assert count=<x:expr
select="count($doc//assert)"/>
-
+
</j:jelly>
1.75 +1 -1 jakarta-commons-sandbox/jelly/project.xml
Index: project.xml
===================================================================
RCS file: /home/cvs/jakarta-commons-sandbox/jelly/project.xml,v
retrieving revision 1.74
retrieving revision 1.75
diff -u -r1.74 -r1.75
--- project.xml 27 Sep 2002 02:12:31 -0000 1.74
+++ project.xml 30 Sep 2002 08:05:45 -0000 1.75
@@ -138,7 +138,7 @@
</contributor>
<contributor>
<name>Robert Leftwich</name>
- <email>[EMAIL PROTECTED]</email>
+ <email>[EMAIL PROTECTED]</email>
<roles>
<role>Developer</role>
</roles>
--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>