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 "SORENS,MICHAEL (HP-Boise,ex1)" <mi...@hp.com> on 2003/08/15 22:35:55 UTC

transform() fails for DOMSource but succeeds for StreamSource

I want to do a transform with a DOMSource input. If I do this from a file
(i.e. StreamSource), it works fine, but changing only the argument to
transform() to be a DOMSource, then the transformation fails with a
HIERARCHY_REQUEST_ERR. I boiled down a test for this to its simplest form,
containing 80 lines of code below. This code performs one of three
transforms (differing in type of argument) by invoking with "-A", "-B", or
"-C". It uses supplementary files test.xml and test.xsl following. 
Question 1: Why does transform() fail if I use a DOMSource argument??

I believe I am using Xalan 2.4.0 and Xerces 2.3.0.
Question 2: How does one query Xalan/Xerces to find the version number?

- - - - - - - - - - - - - - - - - - - - - - - - - - - -
[File: TransformTest.java]
package com.cleancode.xml;

import java.io.File;
import java.io.FileOutputStream;

import javax.xml.transform.TransformerFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.stream.StreamSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

import org.apache.xalan.serialize.Serializer;
import org.apache.xalan.serialize.SerializerFactory;
import org.apache.xalan.templates.OutputProperties;

public class TransformTest {

	private static void echoXml(Node node, String what) throws Exception
{
		System.out.println("Echoing "+what+":");
		Serializer serializer = SerializerFactory.getSerializer
	
(OutputProperties.getDefaultMethodProperties("xml"));
		serializer.setOutputStream(System.out);
		serializer.asDOMSerializer().serialize(node);
		System.out.println("");
		System.out.println("Echo "+what+" complete.");
	}

	public static void main( String[] args ) throws Exception {
		String inName = "test.xml";
		String outName = "test.out";
		String xslName = "test.xsl";
		boolean optA = (args.length > 0) && "-A".equals(args[0]);
		boolean optB = (args.length > 0) && "-B".equals(args[0]);
		boolean optC = (args.length > 0) && "-C".equals(args[0]);

		boolean ignoreWhitespace = false;
		boolean ignoreComments = false;
		boolean putCDATAIntoText = false;
		boolean createEntityRefs = false;
		DocumentBuilderFactory dbf =
DocumentBuilderFactory.newInstance();
		dbf.setNamespaceAware(true);
		dbf.setIgnoringComments(ignoreComments);
		dbf.setIgnoringElementContentWhitespace(ignoreWhitespace);
		dbf.setCoalescing(putCDATAIntoText);
		dbf.setExpandEntityReferences(!createEntityRefs);
		DocumentBuilder db = dbf.newDocumentBuilder();
		Element docRoot = db.parse(inName).getDocumentElement();
		echoXml(docRoot, "Input");

		File XslFile = new File(xslName);
		TransformerFactory tFactory =
TransformerFactory.newInstance();
		Transformer transformer =
			tFactory.newTransformer(new StreamSource(XslFile));
		DOMResult dr = new DOMResult();
		if (optA) {
			transformer.transform(new StreamSource(inName), dr);
			echoXml(dr.getNode(), "Output");
		}
		else if (optB) {
			try { transformer.transform(new DOMSource(docRoot),
dr); }
			catch (Exception e) {
				System.out.println("transform
[DOMSource=>DOMResult] failed:" + e);
			}
			echoXml(dr.getNode(), "Output");
		}
		else if (optC) {
			transformer.transform(new DOMSource(docRoot),
				new StreamResult(new
FileOutputStream(outName)));
			System.out.println("output stored in " + outName);
		}
		else {
			System.out.println("usage: TransformTest [ -A|-B|-C
]");
		}
	}
}

- - - - - - - - - - - - - - - - - - - - - - - - - - - -
[File: test.xsl]
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:cc="stuff.com"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >

<xsl:output method="xml" indent="yes" omit-xml-declaration="no" />

<xsl:template match="/files">
	<cc:myDoc>
	<xsl:for-each select="file">
		<cc:indexItem>
			<file><xsl:value-of select="."/></file>
		</cc:indexItem>
	</xsl:for-each>
	</cc:myDoc>
</xsl:template>

</xsl:stylesheet>

- - - - - - - - - - - - - - - - - - - - - - - - - - - -
[File: test.xml]
<?xml version="1.0" encoding="UTF-8"?>
<files>
	<file>motivation.xml</file>
	<file>history.xml</file>
</files>
- - - - - - - - - - - - - - - - - - - - - - - - - - - -


Re: transform() fails for DOMSource but succeeds for StreamSource

Posted by Stanimir Stamenkov <st...@myrealbox.com>.
/Ziv Ben-Eliahu/:

> Document parsedDoc = builder.parse(new File("apple.xml"));
>
> The stream-source gave the expected results.
> The parsed-dom-source (from the same file as the stream-source) gave bad 
> results - its like the Document was not recognized.
> The manually-built-dom-source gave the expected results.

Is your |builder| configured to produce a namespace aware DOM?  Is 
your "manually-built-dom" namespace aware?  If both DOM instances 
have different namespace awareness - this could be the reason, 
although I can't think of anything specific at the moment.

-- 
Stanimir

Re: transform() fails for DOMSource but succeeds for StreamSource

Posted by Mike Brown <mi...@skew.org>.
I'm guessing but I think the answer is the same as before - if you fail to set
a system ID that is a full URI, results will be unpredictable.

In your examples, you start using your DOMSource and your StreamSource 
objects without having set their system IDs.  I suggest creating the File 
objects separately so that you can use their .getAbsoluteFile().toURI() 
methods to obtain a proper URI that you can use as the system ID in your 
Source objects. Then set that ID in those objects either in the constructor or 
via a separate call to their .setSystemID() method.

Let us know if it works.

Ziv Ben-Eliahu wrote:
> Hi There.
> I have a similar problem - fails for DOMSource but succeeds for 
> StreamSource - but failure is not an error, it is a different output.
> 
> I have the following XML:
> <apple xmlns="http://purl.oclc.org/NET/JSX/0.3/Apple">
>      <shop type="happy-days">
>          <owner name="Jhon" type="big"/>
>      </shop>
>      <order name="GooGoo" type="org.goo" />
> </apple>
> 
> I have two parsers - an identity-transformer and a xsl-transformer :
>          Transformer tfCopy = javax.xml.transform.TransformerFactory
>                                .newInstance().newTransformer();
>          Transformer tf = javax.xml.transform.TransformerFactory
>                          .newInstance()newTransformer(
>                             new StreamSource(new File("Apple.xsl")));
> 
> I have three source type - by stream, builder-parsed, builder-created:
> Document parsedDoc = builder.parse(new File("apple.xml"));
> DOMSource parsedSource = new DOMSource(parsedDoc);
> StreamSource streamSource = new StreamSource(new File("apple.xml"));
> DOMSource builtSource = new DOMSource(build());  // build() is a manual 
> build of the parsed document
> 
> 
> When I use the identity-transformer the results are the same:
>          tfCopy.transform(streamSource, new StreamResult(new 
> File("d:/streamed.xml")));
>          tfCopy.transform(builtSource, new StreamResult(new 
> File("d:/built.xml")));
>          tfCopy.transform(parsedSource, new StreamResult(new 
> File("d:/parsed.xml")));
> 
> 
> 
> When I use the XSL-based-transformer, results are completely different.
>          tf.transform(builtSource, new StreamResult(new 
> File("d:/built.html")));
>          tf.transform(parsedSource, new StreamResult(new 
> File("d:/parsed.html")));
>          tf.transform(streamSource, new StreamResult(new 
> File("d:/streamed.html")));
> 
> 
> I won't include them since they are long, but to sum up:
> The stream-source gave the expected results.
> The parsed-dom-source (from the same file as the stream-source) gave bad 
> results - its like the Document was not recognized.
> The manually-built-dom-source gave the expected results.
> 
> 
> Question: how come identity-transformer worked fine with the parsed DOM 
> and a xsl-transformer did not?
> 
> 
> My current solution is:
> Use the identity-transformer to copy from the parsed-dom to a 
> result-dom. Then take the node from the result-dom. The XSL-transformer 
> works fine with that node.
> 
> Thank you for your help,
> Ziv.
> 
> 
> 
> SORENS,MICHAEL (HP-Boise,ex1) wrote:
> > I want to do a transform with a DOMSource input. If I do this from a file
> > (i.e. StreamSource), it works fine, but changing only the argument to
> > transform() to be a DOMSource, then the transformation fails with a
> > HIERARCHY_REQUEST_ERR. I boiled down a test for this to its simplest form,
> > containing 80 lines of code below. This code performs one of three
> > transforms (differing in type of argument) by invoking with "-A", "-B", or
> > "-C". It uses supplementary files test.xml and test.xsl following. 
> > Question 1: Why does transform() fail if I use a DOMSource argument??
> > 
> > I believe I am using Xalan 2.4.0 and Xerces 2.3.0.
> > Question 2: How does one query Xalan/Xerces to find the version number?
> 

Re: transform() fails for DOMSource but succeeds for StreamSource

Posted by Ziv Ben-Eliahu <zi...@wirexn.com>.
Hi There.
I have a similar problem - fails for DOMSource but succeeds for 
StreamSource - but failure is not an error, it is a different output.

I have the following XML:
<apple xmlns="http://purl.oclc.org/NET/JSX/0.3/Apple">
     <shop type="happy-days">
         <owner name="Jhon" type="big"/>
     </shop>
     <order name="GooGoo" type="org.goo" />
</apple>

I have two parsers - an identity-transformer and a xsl-transformer :
         Transformer tfCopy = javax.xml.transform.TransformerFactory
                               .newInstance().newTransformer();
         Transformer tf = javax.xml.transform.TransformerFactory
                         .newInstance()newTransformer(
                            new StreamSource(new File("Apple.xsl")));

I have three source type - by stream, builder-parsed, builder-created:
Document parsedDoc = builder.parse(new File("apple.xml"));
DOMSource parsedSource = new DOMSource(parsedDoc);
StreamSource streamSource = new StreamSource(new File("apple.xml"));
DOMSource builtSource = new DOMSource(build());  // build() is a manual 
build of the parsed document


When I use the identity-transformer the results are the same:
         tfCopy.transform(streamSource, new StreamResult(new 
File("d:/streamed.xml")));
         tfCopy.transform(builtSource, new StreamResult(new 
File("d:/built.xml")));
         tfCopy.transform(parsedSource, new StreamResult(new 
File("d:/parsed.xml")));



When I use the XSL-based-transformer, results are completely different.
         tf.transform(builtSource, new StreamResult(new 
File("d:/built.html")));
         tf.transform(parsedSource, new StreamResult(new 
File("d:/parsed.html")));
         tf.transform(streamSource, new StreamResult(new 
File("d:/streamed.html")));


I won't include them since they are long, but to sum up:
The stream-source gave the expected results.
The parsed-dom-source (from the same file as the stream-source) gave bad 
results - its like the Document was not recognized.
The manually-built-dom-source gave the expected results.


Question: how come identity-transformer worked fine with the parsed DOM 
and a xsl-transformer did not?


My current solution is:
Use the identity-transformer to copy from the parsed-dom to a 
result-dom. Then take the node from the result-dom. The XSL-transformer 
works fine with that node.

Thank you for your help,
Ziv.



SORENS,MICHAEL (HP-Boise,ex1) wrote:
> I want to do a transform with a DOMSource input. If I do this from a file
> (i.e. StreamSource), it works fine, but changing only the argument to
> transform() to be a DOMSource, then the transformation fails with a
> HIERARCHY_REQUEST_ERR. I boiled down a test for this to its simplest form,
> containing 80 lines of code below. This code performs one of three
> transforms (differing in type of argument) by invoking with "-A", "-B", or
> "-C". It uses supplementary files test.xml and test.xsl following. 
> Question 1: Why does transform() fail if I use a DOMSource argument??
> 
> I believe I am using Xalan 2.4.0 and Xerces 2.3.0.
> Question 2: How does one query Xalan/Xerces to find the version number?


Re: transform() fails for DOMSource but succeeds for StreamSource

Posted by Dave Flanagan <da...@trainingetc.com>.
Had originally sent the response shown below detailing the problem he was
having - but it did not make it to the userlist when I sent the response -
here it is again if any one was interested in what what happening

Dave Flanagan

Michael - making one of two changes should correct the problem you are
experiencing:
Solution #1:
    Instead of dealing with the Document Element of the source which you are
    obtaining with the following line:
        Element docRoot = db.parse(inName).getDocumentElement();
    change it to
        Document docRoot = db.parse(inName);
-------
Solution #2:
If no change to your java code is desired then
     in the stylesheet change
          <xsl:template match="/files">
     to
          <xsl:template match="files">

Dave Flanagan

----- Original Message ----- 
From: "Joseph Kesselman" <ke...@us.ibm.com>
To: <xa...@xml.apache.org>
Sent: Monday, August 18, 2003 10:16 AM
Subject: Re: transform() fails for DOMSource but succeeds for StreamSource


>
>
>
>
> I strongly suspect you've misdiagnosed the problem, and your glitch is
tied
> to the use of a DOMResult rather than a DOMSource.
>
> When outputting to a DOM Document, your generated document *must* meet the
> DOM's well-formedness requirements -- single root element, no text nodes
> outside that root element, etc.  If you violate those constraints, the DOM
> will throw a HIERARCHY_REQUEST_ERR.
>
> I haven't analysed your testcase in detail, but if my guess is right your
> options are:
>
> 1) Fix the stylesheet to produce a well-formed XML document.
>
> 2) Output to SAX rather than DOM, since SAX doesn't enforce as many of the
> well-formedness constraints.
>
> 3) If you really need DOM and really something other than a well-formed
> document, you could try wrapping the DOMResult around a DocumentFragment
> rather than a Document. That would permit multiple top-level elements and
> text at the top level; depending on exactly what the system is complaining
> about, that might be enough to get you over the hump.
>
> ______________________________________
> Joe Kesselman, IBM Next-Generation Web Technologies: XML, XSL and more.
> "The world changed profoundly and unpredictably the day Tim Berners Lee
> got bitten by a radioactive spider." -- Rafe Culpin, in r.m.filk
>
>



Re: transform() fails for DOMSource but succeeds for StreamSource

Posted by Joseph Kesselman <ke...@us.ibm.com>.



I strongly suspect you've misdiagnosed the problem, and your glitch is tied
to the use of a DOMResult rather than a DOMSource.

When outputting to a DOM Document, your generated document *must* meet the
DOM's well-formedness requirements -- single root element, no text nodes
outside that root element, etc.  If you violate those constraints, the DOM
will throw a HIERARCHY_REQUEST_ERR.

I haven't analysed your testcase in detail, but if my guess is right your
options are:

1) Fix the stylesheet to produce a well-formed XML document.

2) Output to SAX rather than DOM, since SAX doesn't enforce as many of the
well-formedness constraints.

3) If you really need DOM and really something other than a well-formed
document, you could try wrapping the DOMResult around a DocumentFragment
rather than a Document. That would permit multiple top-level elements and
text at the top level; depending on exactly what the system is complaining
about, that might be enough to get you over the hump.

______________________________________
Joe Kesselman, IBM Next-Generation Web Technologies: XML, XSL and more.
"The world changed profoundly and unpredictably the day Tim Berners Lee
got bitten by a radioactive spider." -- Rafe Culpin, in r.m.filk