C
Collin VanDyck
I've been using org.apache.xml.utils.DOMBuilder to build an
org.w3c.dom.Document object from a stream of SAX2 events in my application.
I encounter serious problems when I try and build the document using any
DOCTYPE preset.
My algorithm, should a DOCTYPE be needed in the final Document, is to
1. Create a DocumentBuilder from a DocumentFactory
2. Get the DOMImplementation from the DocumentBuilder
3. Ask the DOMImplementation to create a DocumentType object with some
presets.
4. Use that DocumentType to help create a new Document using the
DOMImplementation
5. Create a DOMBuilder on that Document, using the root Node of the
Document as the current Node so that any further events are built from
that node.
The problem I'm getting is that the DOMBuilder seems to think that I am
appending multiple elements to the root of the Document instead of the
root Node.
To illustrate this, I'm inserting some source that should be runnable
using standard J2SE 1.4.2 runtime libraries. This example will
illustrate my frustration.
Also, John Bollinger, I read your posts on DOCTYPEs, which helped to get
me to this point -- thanks.
The output from my program I get is:
Starting body element failed: Can't have more than one root on a DOM!
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html><head /></html>
But I believe it should be:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html><head /><body/></html>
Any ideas on this, anyone?
thanks,
Collin
----------starting source code-------------------------------
package run;
import java.io.BufferedWriter;
import java.io.StringWriter;
import java.io.Writer;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.apache.xalan.templates.OutputProperties;
import org.apache.xml.utils.DOMBuilder;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;
import org.xml.sax.helpers.AttributesImpl;
/**
* Test of the DOMBuilder
*
* @author Collin VanDyck
*/
public class DOMBuilderTest {
public static void main(String[] args)
{
try
{
////////////////////////
// set up the dombuilder
////////////////////////
final DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();
factory.setValidating(false);
factory.setNamespaceAware(false);
factory.setExpandEntityReferences(false);
factory.setIgnoringComments(false);
factory.setIgnoringElementContentWhitespace(false);
final DocumentBuilder builder = factory.newDocumentBuilder();
final DOMImplementation domImplementation =
builder.getDOMImplementation();
final DocumentType documentType =
domImplementation.createDocumentType(
"html",
"-//W3C//DTD XHTML 1.0 Strict//EN",
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd");
// this document is created with a root node already in place.
final Document document = domImplementation.createDocument(
"",
documentType.getName(),
documentType);
final Element documentElement = document.getDocumentElement();
// create the DOMBuilder with the current node to be the
document element.
final DOMBuilder domBuilder = new DOMBuilder(document,
documentElement);
////////////////////////
// add elements to my document
////////////////////////
// this works
domBuilder.startElement("","head","head",new AttributesImpl());
domBuilder.endElement("","head","head");
// this fails -- why, when we are not appending this
element to the document root but
// instead the root node of the document?
try
{
domBuilder.startElement("","body","body",new
AttributesImpl());
domBuilder.endElement("","body","body");
}
catch (Exception e)
{
System.err.println("Starting body element failed: " +
e.getMessage());
}
////////////////////////
// print it out
////////////////////////
printDocument(document);
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
/**
* Prints a Document.
*
* @param document
* @throws Exception
*/
private static void printDocument(Document document) throws Exception
{
final DOMSource domSource = new DOMSource(document);
final Writer stringWriter = new StringWriter();
final Result result = new StreamResult(new
BufferedWriter(stringWriter));
final TransformerFactory factory =
TransformerFactory.newInstance();
// produce an identity transform to copy from the source to the
result.
final Transformer transformer = factory.newTransformer();
transformer.setOutputProperties(OutputProperties.getDefaultMethodProperties("xml"));
final DocumentType doctype = document.getDoctype();
if (doctype != null)
{
transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC,
doctype.getPublicId());
transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM,
doctype.getSystemId());
}
// let her rip
transformer.transform(domSource, result);
final String output = stringWriter.toString();
System.out.println(output);
}
}
org.w3c.dom.Document object from a stream of SAX2 events in my application.
I encounter serious problems when I try and build the document using any
DOCTYPE preset.
My algorithm, should a DOCTYPE be needed in the final Document, is to
1. Create a DocumentBuilder from a DocumentFactory
2. Get the DOMImplementation from the DocumentBuilder
3. Ask the DOMImplementation to create a DocumentType object with some
presets.
4. Use that DocumentType to help create a new Document using the
DOMImplementation
5. Create a DOMBuilder on that Document, using the root Node of the
Document as the current Node so that any further events are built from
that node.
The problem I'm getting is that the DOMBuilder seems to think that I am
appending multiple elements to the root of the Document instead of the
root Node.
To illustrate this, I'm inserting some source that should be runnable
using standard J2SE 1.4.2 runtime libraries. This example will
illustrate my frustration.
Also, John Bollinger, I read your posts on DOCTYPEs, which helped to get
me to this point -- thanks.
The output from my program I get is:
Starting body element failed: Can't have more than one root on a DOM!
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html><head /></html>
But I believe it should be:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html><head /><body/></html>
Any ideas on this, anyone?
thanks,
Collin
----------starting source code-------------------------------
package run;
import java.io.BufferedWriter;
import java.io.StringWriter;
import java.io.Writer;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.apache.xalan.templates.OutputProperties;
import org.apache.xml.utils.DOMBuilder;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;
import org.xml.sax.helpers.AttributesImpl;
/**
* Test of the DOMBuilder
*
* @author Collin VanDyck
*/
public class DOMBuilderTest {
public static void main(String[] args)
{
try
{
////////////////////////
// set up the dombuilder
////////////////////////
final DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();
factory.setValidating(false);
factory.setNamespaceAware(false);
factory.setExpandEntityReferences(false);
factory.setIgnoringComments(false);
factory.setIgnoringElementContentWhitespace(false);
final DocumentBuilder builder = factory.newDocumentBuilder();
final DOMImplementation domImplementation =
builder.getDOMImplementation();
final DocumentType documentType =
domImplementation.createDocumentType(
"html",
"-//W3C//DTD XHTML 1.0 Strict//EN",
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd");
// this document is created with a root node already in place.
final Document document = domImplementation.createDocument(
"",
documentType.getName(),
documentType);
final Element documentElement = document.getDocumentElement();
// create the DOMBuilder with the current node to be the
document element.
final DOMBuilder domBuilder = new DOMBuilder(document,
documentElement);
////////////////////////
// add elements to my document
////////////////////////
// this works
domBuilder.startElement("","head","head",new AttributesImpl());
domBuilder.endElement("","head","head");
// this fails -- why, when we are not appending this
element to the document root but
// instead the root node of the document?
try
{
domBuilder.startElement("","body","body",new
AttributesImpl());
domBuilder.endElement("","body","body");
}
catch (Exception e)
{
System.err.println("Starting body element failed: " +
e.getMessage());
}
////////////////////////
// print it out
////////////////////////
printDocument(document);
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
/**
* Prints a Document.
*
* @param document
* @throws Exception
*/
private static void printDocument(Document document) throws Exception
{
final DOMSource domSource = new DOMSource(document);
final Writer stringWriter = new StringWriter();
final Result result = new StreamResult(new
BufferedWriter(stringWriter));
final TransformerFactory factory =
TransformerFactory.newInstance();
// produce an identity transform to copy from the source to the
result.
final Transformer transformer = factory.newTransformer();
transformer.setOutputProperties(OutputProperties.getDefaultMethodProperties("xml"));
final DocumentType doctype = document.getDoctype();
if (doctype != null)
{
transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC,
doctype.getPublicId());
transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM,
doctype.getSystemId());
}
// let her rip
transformer.transform(domSource, result);
final String output = stringWriter.toString();
System.out.println(output);
}
}