You are viewing a plain text version of this content. The canonical link for it is here.
Posted to j-users@xalan.apache.org by Mike Brown <mi...@skew.org> on 2007/02/22 18:41:15 UTC

Node-set to XML string via Java extensions in Xalan-J: possible?

I'm trying to serialize nodes to an XML string, using Java extensions. I'm
trying to avoid writing my own. I thought perhaps I could use the
DOMSerializer in Xalan-J.

However, I'm having trouble calling certain methods. They're documented as
existing, but Xalan-J is not finding them. For example, I can instantiate an
OutputPropertiesFactory, but I can't call its getDefaultMethodProperties()
method. And I can't instantiate a SerializerFactory at all.



Here is my XML:

<?xml version="1.0" encoding="utf-8"?>
<greetings>
  <greeting xml:lang="en">hello!</greeting>
  <greeting xml:lang="es">&#161;hola!</greeting>
  <greeting xml:lang="fr">bonjour!</greeting>
  <greeting xml:lang="ru">&#1047;&#1076;&#1088;&#1072;&#1074;&#1089;&#1090;&#1074;&#1091;&#1081;&#1090;&#1077;!</greeting>
  <greeting xml:lang="ja">&#20170;&#26085;&#12399;</greeting>
</greetings>


Here is my XSLT (the failure is when I try to create $formatprops):

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:java="http://xml.apache.org/xalan/java">

  <xsl:output method="text" indent="no"/>

  <xsl:template match="/">
    <xsl:variable name="nodeset" select="/greetings"/>
    <!--OutputPropertiesFactory opropsfactory = new OutputPropertiesFactory();-->
    <xsl:variable name="opropsfactory" select="java:org.apache.xml.serializer.OutputPropertiesFactory.new()"/>
    <!--String method = org.apache.xml.serializer.Method.XML;
        Properties formatprops = opropsfactory.getDefaultMethodProperties(method);-->
    <xsl:variable name="formatprops" select="java:getDefaultMethodProperties($opropsfactory, 'xml')"/>
    <!--SerializerFactory serializerfactory = new SerializerFactory();-->
    <xsl:variable name="serializerfactory" select="java:org.apache.xml.serializer.SerializerFactory.new()"/>
	<!--Serializer serializer = serializerfactory.getSerializer(formatprops);-->
	<xsl:variable name="serializer" select="java:getSerializer($serializerfactory, $formatprops)"/>
	<!--StringWriter buffer = new StringWriter();-->
	<xsl:variable name="buffer" select="java:java.io.StringWriter.new()"/>
	<!--serializer.setWriter(buffer);-->
	<xsl:variable name="void1" select="java:setWriter($serializer, $buffer)"/>
	<!--DOMSerializer domserializer = serializer.asDOMSerializer();-->
	<xsl:variable name="domserializer" select="java:asDOMSerializer($serializer)"/>
	<!--domserializer.serialize(node);-->
	<xsl:variable name="void2" select="java:serialize($domserializer, $nodeset)"/>
	<!--System.out.write(buffer.toString());-->
	<xsl:value-of select="java:toString($buffer)"/>
  </xsl:template>

</xsl:stylesheet>


Here is how I am invoking Xalan-J, and the error message:

C:\dev\test>java -Djava.endorsed.dirs=C:\dev\xalan-j_2_7_0 -cp C:\dev\xalan-j_2_7_0\xalan.jar;C:\dev\xalan-j_2_7_0\serializer.jar org.apache.xalan.xslt.Process -IN greetings.xml -XSL xalanserialize.xsl -EDUMP

; SystemID: file:///C:/dev/test/xalanserialize.xsl; Line#: 14; Column#: 103
javax.xml.transform.TransformerException: java.lang.NoSuchMethodException: For extension function, could not find method org.apache.xml.serializer.OutputPropertiesFactory.getDefaultMethodProperties([ExpressionContext,] #STRING).
        at org.apache.xalan.extensions.ExtensionHandlerJavaPackage.callFunction(ExtensionHandlerJavaPackage.java:420)
        at org.apache.xalan.extensions.ExtensionHandlerJavaPackage.callFunction(ExtensionHandlerJavaPackage.java:438)
        at org.apache.xalan.extensions.ExtensionsTable.extFunction(ExtensionsTable.java:220)
        at org.apache.xalan.transformer.TransformerImpl.extFunction(TransformerImpl.java:473)
        at org.apache.xpath.functions.FuncExtFunction.execute(FuncExtFunction.java:206)
        at org.apache.xpath.XPath.execute(XPath.java:335)
        at org.apache.xalan.templates.ElemVariable.getValue(ElemVariable.java:278)
        at org.apache.xalan.templates.ElemVariable.execute(ElemVariable.java:246)
        at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2411)
        at org.apache.xalan.transformer.TransformerImpl.applyTemplateToNode(TransformerImpl.java:2281)
        at org.apache.xalan.transformer.TransformerImpl.transformNode(TransformerImpl.java:1367)
        at org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:709)
        at org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:1284)
        at org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:1262)
        at org.apache.xalan.xslt.Process.main(Process.java:1046)
---------
java.lang.NoSuchMethodException: For extension function, could not find method org.apache.xml.serializer.OutputPropertiesFactory.getDefaultMethodProperties([ExpressionContext,] #STRING).
        at org.apache.xalan.extensions.MethodResolver.getMethod(MethodResolver.java:274)
        at org.apache.xalan.extensions.ExtensionHandlerJavaPackage.callFunction(ExtensionHandlerJavaPackage.java:381)
        at org.apache.xalan.extensions.ExtensionHandlerJavaPackage.callFunction(ExtensionHandlerJavaPackage.java:438)
        at org.apache.xalan.extensions.ExtensionsTable.extFunction(ExtensionsTable.java:220)
        at org.apache.xalan.transformer.TransformerImpl.extFunction(TransformerImpl.java:473)
        at org.apache.xpath.functions.FuncExtFunction.execute(FuncExtFunction.java:206)
        at org.apache.xpath.XPath.execute(XPath.java:335)
        at org.apache.xalan.templates.ElemVariable.getValue(ElemVariable.java:278)
        at org.apache.xalan.templates.ElemVariable.execute(ElemVariable.java:246)
        at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2411)
        at org.apache.xalan.transformer.TransformerImpl.applyTemplateToNode(TransformerImpl.java:2281)
        at org.apache.xalan.transformer.TransformerImpl.transformNode(TransformerImpl.java:1367)
        at org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:709)
        at org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:1284)
        at org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:1262)
        at org.apache.xalan.xslt.Process.main(Process.java:1046)
Exception in thread "main" java.lang.RuntimeException: java.lang.NoSuchMethodException: For extension function, could not find method org.apache.xml.serializer.OutputPropertiesFactory.getDefaultMethodProperties([ExpressionContext,] #STRING).
        at org.apache.xalan.xslt.Process.doExit(Process.java:1153)
        at org.apache.xalan.xslt.Process.main(Process.java:1126)


If I try to create the SerializerFactory first, I get a similar error about its constructor
not being found. Am I doing something wrong?

Thanks,
Mike

Re: Node-set to XML string via Java extensions in Xalan-J: possible?

Posted by Mike Brown <mi...@skew.org>.
Kevin Cormier wrote:
> The getDefaultMethodProperties(String method) method of the
> org.apache.xml.serializer.OutputPropertiesFactory class is static, so you
> can't call it on the instance that you've created.  You can call it like
> this:
> 
> <xsl:variable name="formatprops"
> select="java:org.apache.xml.serializer.OutputPropertiesFactory.getDefaultMethodProperties('xml')"/>
> 
> As for the SerializerFactory, its constructor is private, so it can't be
> instantiated directly.  You have to use the static getSerializer(Properties
> format) method to obtain an instance.

Ah! Thank you! That was exactly what I needed. I knew I must've overlooked 
something. Here's XSLT demonstrating both the pure-JAXP and DOMSerializer 
methods. I couldn't find a SAXSerializer in the Xalan 2.7.1 distribution.

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:java="http://xml.apache.org/xalan/java">

  <xsl:output method="text"/>

	<xsl:template match="/">
		<xsl:text>JAXP:&#10;=====&#10;</xsl:text>
		<xsl:call-template name="serialize-xml-via-JAXP"/>
		<xsl:text>&#10;&#10;org.apache.xml.serializer.DOMSerializer:&#10;========================================&#10;</xsl:text>
		<xsl:call-template name="serialize-xml-via-DOMSerializer"/>
	</xsl:template>

	<xsl:template name="serialize-xml-via-JAXP">
		<!--TransformerFactory tfactory = new TransformerFactory.newInstance();-->
		<xsl:variable name="tfactory" select="java:javax.xml.transform.TransformerFactory.newInstance()"/>
		<!--Transformer t = tfactory.newTransformer();-->
		<xsl:variable name="t" select="java:newTransformer($tfactory)"/>
		<!--DOMSource isrc = new DOMSource(nodeset);-->
		<xsl:variable name="isrc" select="java:javax.xml.transform.dom.DOMSource.new(.)"/>
		<!--StringWriter buffer = new StringWriter();-->
		<xsl:variable name="buffer" select="java:java.io.StringWriter.new()"/>
		<!--StreamResult result = new StreamResult(buffer);-->
		<xsl:variable name="result" select="java:javax.xml.transform.stream.StreamResult.new($buffer)"/>
		<!--t.transform(isrc, result)-->
		<xsl:variable name="void0" select="java:transform($t, $isrc, $result)"/>
		<!--System.out.write(buffer.toString());-->
		<!--Also clean up newlines-->
		<xsl:value-of select="translate(java:toString($buffer), '&#13;', '')"/>
	</xsl:template>

	<xsl:template name="serialize-xml-via-DOMSerializer">
		<!--String method = org.apache.xml.serializer.Method.XML;
		    Properties formatprops = OutputPropertiesFactory.getDefaultMethodProperties(method);-->
		<xsl:variable name="formatprops" select="java:org.apache.xml.serializer.OutputPropertiesFactory.getDefaultMethodProperties('xml')"/>
		<!--Serializer serializer = SerializerFactory.getSerializer(formatprops);-->
		<xsl:variable name="serializer" select="java:org.apache.xml.serializer.SerializerFactory.getSerializer($formatprops)"/>
		<!--StringWriter buffer = new StringWriter();-->
		<xsl:variable name="buffer" select="java:java.io.StringWriter.new()"/>
		<!--serializer.setWriter(buffer);-->
		<xsl:variable name="void1" select="java:setWriter($serializer, $buffer)"/>
		<!--DOMSerializer domserializer = serializer.asDOMSerializer();-->
		<xsl:variable name="domserializer" select="java:asDOMSerializer($serializer)"/>
		<!--domserializer.serialize(node);-->
		<xsl:variable name="void2" select="java:serialize($domserializer, .)"/>
		<!--System.out.write(buffer.toString());-->
		<xsl:value-of select="java:toString($buffer)"/>
	</xsl:template>

</xsl:stylesheet>

Re: Node-set to XML string via Java extensions in Xalan-J: possible?

Posted by Kevin Cormier <kc...@ca.ibm.com>.
Hi Mike,

The getDefaultMethodProperties(String method) method of the
org.apache.xml.serializer.OutputPropertiesFactory class is static, so you
can't call it on the instance that you've created.  You can call it like
this:

<xsl:variable name="formatprops"
select="java:org.apache.xml.serializer.OutputPropertiesFactory.getDefaultMethodProperties('xml')"/>

As for the SerializerFactory, its constructor is private, so it can't be
instantiated directly.  You have to use the static getSerializer(Properties
format) method to obtain an instance.

Hope this helps.

Kevin Cormier
Software Developer, XSLT Development
IBM Toronto Lab, D1-435
Phone: 905-413-5771
E-mail:  kcormier@ca.ibm.com


                                                                           
             Mike Brown                                                    
             <mi...@skew.org>                                               
                                                                        To 
             02/22/2007 12:41          xalan-j-users@xml.apache.org        
             PM                                                         cc 
                                                                           
                                                                   Subject 
                                       Node-set to XML string via Java     
                                       extensions in Xalan-J: possible?    
                                                                           
                                                                           
                                                                           
                                                                           
                                                                           
                                                                           




I'm trying to serialize nodes to an XML string, using Java extensions. I'm
trying to avoid writing my own. I thought perhaps I could use the
DOMSerializer in Xalan-J.

However, I'm having trouble calling certain methods. They're documented as
existing, but Xalan-J is not finding them. For example, I can instantiate
an
OutputPropertiesFactory, but I can't call its getDefaultMethodProperties()
method. And I can't instantiate a SerializerFactory at all.



Here is my XML:

<?xml version="1.0" encoding="utf-8"?>
<greetings>
  <greeting xml:lang="en">hello!</greeting>
  <greeting xml:lang="es">&#161;hola!</greeting>
  <greeting xml:lang="fr">bonjour!</greeting>
  <greeting
xml:lang="ru">&#1047;&#1076;&#1088;&#1072;&#1074;&#1089;&#1090;&#1074;&#1091;&#1081;&#1090;&#1077;!</greeting>

  <greeting xml:lang="ja">&#20170;&#26085;&#12399;</greeting>
</greetings>


Here is my XSLT (the failure is when I try to create $formatprops):

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:java="http://xml.apache.org/xalan/java">

  <xsl:output method="text" indent="no"/>

  <xsl:template match="/">
    <xsl:variable name="nodeset" select="/greetings"/>
    <!--OutputPropertiesFactory opropsfactory = new
OutputPropertiesFactory();-->
    <xsl:variable name="opropsfactory"
select="java:org.apache.xml.serializer.OutputPropertiesFactory.new()"/>
    <!--String method = org.apache.xml.serializer.Method.XML;
Properties formatprops =
opropsfactory.getDefaultMethodProperties(method);-->
    <xsl:variable name="formatprops"
select="java:getDefaultMethodProperties($opropsfactory, 'xml')"/>
    <!--SerializerFactory serializerfactory = new SerializerFactory();-->
    <xsl:variable name="serializerfactory"
select="java:org.apache.xml.serializer.SerializerFactory.new()"/>
             <!--Serializer serializer =
serializerfactory.getSerializer(formatprops);-->
             <xsl:variable name="serializer"
select="java:getSerializer($serializerfactory, $formatprops)"/>
             <!--StringWriter buffer = new StringWriter();-->
             <xsl:variable name="buffer"
select="java:java.io.StringWriter.new()"/>
             <!--serializer.setWriter(buffer);-->
             <xsl:variable name="void1" select="java:setWriter($serializer,
$buffer)"/>
             <!--DOMSerializer domserializer =
serializer.asDOMSerializer();-->
             <xsl:variable name="domserializer"
select="java:asDOMSerializer($serializer)"/>
             <!--domserializer.serialize(node);-->
             <xsl:variable name="void2"
select="java:serialize($domserializer, $nodeset)"/>
             <!--System.out.write(buffer.toString());-->
             <xsl:value-of select="java:toString($buffer)"/>
  </xsl:template>

</xsl:stylesheet>


Here is how I am invoking Xalan-J, and the error message:

C:\dev\test>java -Djava.endorsed.dirs=C:\dev\xalan-j_2_7_0 -cp
C:\dev\xalan-j_2_7_0\xalan.jar;C:\dev\xalan-j_2_7_0\serializer.jar
org.apache.xalan.xslt.Process -IN greetings.xml -XSL xalanserialize.xsl
-EDUMP

; SystemID: file:///C:/dev/test/xalanserialize.xsl; Line#: 14; Column#: 103
javax.xml.transform.TransformerException: java.lang.NoSuchMethodException:
For extension function, could not find method
org.apache.xml.serializer.OutputPropertiesFactory.getDefaultMethodProperties([ExpressionContext,]
 #STRING).
        at
org.apache.xalan.extensions.ExtensionHandlerJavaPackage.callFunction(ExtensionHandlerJavaPackage.java:420)

        at
org.apache.xalan.extensions.ExtensionHandlerJavaPackage.callFunction(ExtensionHandlerJavaPackage.java:438)

        at
org.apache.xalan.extensions.ExtensionsTable.extFunction(ExtensionsTable.java:220)

        at
org.apache.xalan.transformer.TransformerImpl.extFunction(TransformerImpl.java:473)

        at
org.apache.xpath.functions.FuncExtFunction.execute(FuncExtFunction.java:206)

        at org.apache.xpath.XPath.execute(XPath.java:335)
        at
org.apache.xalan.templates.ElemVariable.getValue(ElemVariable.java:278)
        at
org.apache.xalan.templates.ElemVariable.execute(ElemVariable.java:246)
        at
org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2411)

        at
org.apache.xalan.transformer.TransformerImpl.applyTemplateToNode(TransformerImpl.java:2281)

        at
org.apache.xalan.transformer.TransformerImpl.transformNode(TransformerImpl.java:1367)

        at
org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:709)

        at
org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:1284)

        at
org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:1262)

        at org.apache.xalan.xslt.Process.main(Process.java:1046)
---------
java.lang.NoSuchMethodException: For extension function, could not find
method
org.apache.xml.serializer.OutputPropertiesFactory.getDefaultMethodProperties([ExpressionContext,]
 #STRING).
        at
org.apache.xalan.extensions.MethodResolver.getMethod(MethodResolver.java:274)

        at
org.apache.xalan.extensions.ExtensionHandlerJavaPackage.callFunction(ExtensionHandlerJavaPackage.java:381)

        at
org.apache.xalan.extensions.ExtensionHandlerJavaPackage.callFunction(ExtensionHandlerJavaPackage.java:438)

        at
org.apache.xalan.extensions.ExtensionsTable.extFunction(ExtensionsTable.java:220)

        at
org.apache.xalan.transformer.TransformerImpl.extFunction(TransformerImpl.java:473)

        at
org.apache.xpath.functions.FuncExtFunction.execute(FuncExtFunction.java:206)

        at org.apache.xpath.XPath.execute(XPath.java:335)
        at
org.apache.xalan.templates.ElemVariable.getValue(ElemVariable.java:278)
        at
org.apache.xalan.templates.ElemVariable.execute(ElemVariable.java:246)
        at
org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2411)

        at
org.apache.xalan.transformer.TransformerImpl.applyTemplateToNode(TransformerImpl.java:2281)

        at
org.apache.xalan.transformer.TransformerImpl.transformNode(TransformerImpl.java:1367)

        at
org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:709)

        at
org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:1284)

        at
org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:1262)

        at org.apache.xalan.xslt.Process.main(Process.java:1046)
Exception in thread "main" java.lang.RuntimeException:
java.lang.NoSuchMethodException: For extension function, could not find
method
org.apache.xml.serializer.OutputPropertiesFactory.getDefaultMethodProperties([ExpressionContext,]
 #STRING).
        at org.apache.xalan.xslt.Process.doExit(Process.java:1153)
        at org.apache.xalan.xslt.Process.main(Process.java:1126)


If I try to create the SerializerFactory first, I get a similar error about
its constructor
not being found. Am I doing something wrong?

Thanks,
Mike



Re: Node-set to XML string via Java extensions in Xalan-J: possible?

Posted by Mike Brown <mi...@skew.org>.
keshlam@us.ibm.com wrote:
> Just guessing: Xalan's internal data model is not really a DOM, though we
> provide a DOM-subset access layer on top of it for the convenience of
> extensions. You might have better results calling a SAXSerializer instead,
> since generating SAX output is a more natural action for the Xalan code.

Ah, I might try that. Thanks.

> One question: What are you trying to accomplish that's forcing you toward
> this unnatural action? If you're really trying to generate XML syntax into
> the string content or comments of an XML document [...]

I'm not. I'm generating *HTML* (maybe I left xsl:output method="xml" in my
sample code by mistake) and am putting part or all of the source tree, as XML
text, into a textarea. Our QA folks run our web app through thousands of test
scenarios, each of which results in a different source XML document that
affects the HTML output, sometimes in undesirable ways. The textarea gives
them the ability to provide us developers with an extremely valuable tool for
debugging: they just copy-paste the content of the textarea into their bug
report. 90% of the time it allows us to quickly reproduce their results and/or
rule out certain parts of the app as being a problem.

Mike

Re: Node-set to XML string via Java extensions in Xalan-J: possible?

Posted by ke...@us.ibm.com.
Just guessing: Xalan's internal data model is not really a DOM, though we
provide a DOM-subset access layer on top of it for the convenience of
extensions. You might have better results calling a SAXSerializer instead,
since generating SAX output is a more natural action for the Xalan code.

One question: What are you trying to accomplish that's forcing you toward
this unnatural action? If you're really trying to generate XML syntax into
the string content or comments of an XML document, that's an *extremely*
bad design and you should seriously consider simply inserting the nodeset
as ordinary document structure, using namespaces if necessary to
distinguish it from the containing document.


______________________________________
"... Three things see no end: A loop with exit code done wrong,
A semaphore untested, And the change that comes along. ..."
  -- "Threes" Rev 1.1 - Duane Elms / Leslie Fish
(http://www.ovff.org/pegasus/songs/threes-rev-11.html)

Re: Node-set to XML string via Java extensions in Xalan-J: possible?

Posted by Mike Brown <mi...@skew.org>.
Mike Brown wrote:
> I'm trying to serialize nodes to an XML string, using Java extensions. I'm
> trying to avoid writing my own. I thought perhaps I could use the
> DOMSerializer in Xalan-J.

FWIW, using JAXP methods, as shown below, seems to work OK. I'd still like to
know what went wrong with the DOMSerializer, though.

  <xsl:template match="/">
    <!--Node node = (a node-set for which the 1st node in document order will be serialized)-->
    <xsl:variable name="node" select="/"/>
    <!--TransformerFactory tfactory = new TransformerFactory.newInstance();-->
    <xsl:variable name="tfactory" select="java:javax.xml.transform.TransformerFactory.newInstance()"/>
    <!--Transformer t = tfactory.newTransformer();-->
    <xsl:variable name="t" select="java:newTransformer($tfactory)"/>
    <!--DOMSource isrc = new DOMSource(nodeset);-->
    <xsl:variable name="isrc" select="java:javax.xml.transform.dom.DOMSource.new($node)"/>
	<!--StringWriter buffer = new StringWriter();-->
	<xsl:variable name="buffer" select="java:java.io.StringWriter.new()"/>
	<!--StreamResult result = new StreamResult(buffer);-->
	<xsl:variable name="result" select="java:javax.xml.transform.stream.StreamResult.new($buffer)"/>
	<!--t.transform(isrc, result)-->
	<xsl:variable name="void0" select="java:transform($t, $isrc, $result)"/>
	<!--System.out.write(buffer.toString());-->
	<!--Also clean up newlines-->
	<xsl:value-of select="translate(java:toString($buffer), '&#13;', '')"/>
  </xsl:template>

Mike