com.caucho.xml.DOMBuilder Maven / Gradle / Ivy
/*
* Copyright (c) 1998-2018 Caucho Technology -- all rights reserved
*
* This file is part of Resin(R) Open Source
*
* Each copy or derived work must preserve the copyright notice and this
* notice unmodified.
*
* Resin Open Source is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Resin Open Source is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
* of NON-INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with Resin Open Source; if not, write to the
* Free SoftwareFoundation, Inc.
* 59 Temple Place, Suite 330
* Boston, MA 02111-1307 USA
*
* @author Scott Ferguson
*/
package com.caucho.xml;
import com.caucho.util.CharBuffer;
import com.caucho.util.L10N;
import org.w3c.dom.*;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.ErrorHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* XMLWriter to create a DOM document.
*/
public class DOMBuilder implements XMLWriter, ContentHandler, ErrorHandler {
private static final Logger log = Logger.getLogger(DOMBuilder.class.getName());
private static final L10N L = new L10N(DOMBuilder.class);
static final String XMLNS = XmlParser.XMLNS;
private QDocument _doc;
private Node _top;
private Node _node;
private String _singleText;
private CharBuffer _text = new CharBuffer();
private boolean _escapeText;
private boolean _strictXml;
// If true, text and cdata sections should be combined.
private boolean _isCoalescing = true;
// If true, ignorable whitespace is skipped
private boolean _skipWhitespace = false;
private ArrayList _prefixNames = new ArrayList();
private ArrayList _prefixValues = new ArrayList();
private Locator _locator;
private ExtendedLocator _extLocator;
private String _systemId;
public DOMBuilder()
{
}
public void init(Node top)
{
if (top instanceof QDocument)
_doc = (QDocument) top;
else
_doc = (QDocument) top.getOwnerDocument();
_top = top;
_node = top;
_singleText = null;
_prefixNames.clear();
_prefixValues.clear();
}
public void setSystemId(String systemId)
{
_systemId = systemId;
if (systemId != null && _top instanceof Document) {
Document tdoc = (Document) _top;
DocumentType dtd = tdoc.getDoctype();
if (tdoc instanceof QDocument && dtd == null) {
dtd = new QDocumentType(null);
((QDocument) tdoc).setDoctype(dtd);
}
if (dtd instanceof QDocumentType && dtd.getSystemId() == null)
((QDocumentType) dtd).setSystemId(systemId);
}
if (_doc != null)
_doc.setSystemId(systemId);
}
public String getSystemId()
{
return _systemId;
}
public void setFilename(String filename)
{
if (filename != null && _top instanceof QDocument) {
_doc.setRootFilename(filename);
}
}
/**
* Set true if we're only handling strict xml.
*/
public void setStrictXML(boolean isStrictXml)
{
_strictXml = isStrictXml;
}
/**
* Set true if text and cdata nodes should be combined.
*/
public void setCoalescing(boolean isCoalescing)
{
_isCoalescing = isCoalescing;
}
/**
* Set true if ignorable whitespace should be skipped.
*/
public void setSkipWhitespace(boolean skipWhitespace)
{
_skipWhitespace = skipWhitespace;
}
public void setDocumentLocator(Locator loc)
{
if (_doc == null) {
_doc = new QDocument();
_node = _doc;
_top = _doc;
}
_locator = loc;
if (loc instanceof ExtendedLocator)
_extLocator = (ExtendedLocator) loc;
if (_extLocator != null && _doc.getSystemId() == null)
_doc.setLocation(_extLocator.getSystemId(),
_extLocator.getFilename(),
_extLocator.getLineNumber(),
_extLocator.getColumnNumber());
}
public void startPrefixMapping(String prefix, String url)
{
if (_node == null || _node == _top)
_doc.addNamespace(prefix, url);
if (prefix == null || prefix.equals("")) {
_prefixNames.add(new QName(null, "xmlns", XmlParser.XMLNS));
_prefixValues.add(url);
}
else {
_prefixNames.add(new QName("xmlns", prefix, XmlParser.XMLNS));
_prefixValues.add(url);
}
}
public void endPrefixMapping(String prefix)
{
}
public Node getNode()
{
return _top;
}
public void startDocument()
{
if (_doc == null) {
_doc = new QDocument();
_node = _doc;
_top = _doc;
}
}
public void endDocument()
throws SAXException
{
popText();
}
public void setLocation(String filename, int line, int column)
{
}
public void startElement(String uri, String localName, String qName)
throws IOException
{
popText();
Element elt;
if (uri != null && ! uri.equals(""))
elt = _doc.createElementNS(uri, qName);
else if (! qName.equals(""))
elt = _doc.createElement(qName);
else
elt = _doc.createElement(localName);
if (_node == _doc) {
if (_doc.getDocumentElement() == null)
((QDocument) _doc).setDocumentElement(elt);
}
_node.appendChild(elt);
_node = elt;
if (_extLocator != null && elt instanceof QElement) {
((QElement) elt).setLocation(_extLocator.getSystemId(),
_extLocator.getFilename(),
_extLocator.getLineNumber(),
_extLocator.getColumnNumber());
}
}
public void startElement(QName name, QAttributes attributes)
throws SAXException
{
popText();
QElement elt = (QElement) _doc.createElementByName(name);
_node.appendChild(elt);
_node = elt;
if (_node == _doc) {
if (_doc.getDocumentElement() == null)
((QDocument) _doc).setDocumentElement(elt);
}
for (int i = 0; i < _prefixNames.size(); i++) {
QName attrName = _prefixNames.get(i);
String value = _prefixValues.get(i);
elt.setAttribute(attrName, value);
}
_prefixNames.clear();
_prefixValues.clear();
int length = attributes.getLength();
for (int i = 0; i < length; i++) {
QName attrName = attributes.getName(i);
String value = attributes.getValue(i);
elt.setAttribute(attrName, value);
}
if (_extLocator != null) {
elt.setLocation(_extLocator.getSystemId(),
_extLocator.getFilename(),
_extLocator.getLineNumber(),
_extLocator.getColumnNumber());
}
QDocumentType dtd = (QDocumentType) _doc.getDoctype();
if (dtd != null)
dtd.fillDefaults(elt);
}
public void startElement(String uri, String localName, String qName,
Attributes attributes)
throws SAXException
{
popText();
Element elt;
if (uri != null && ! uri.equals(""))
elt = _doc.createElementNS(uri, qName);
else if (! qName.equals(""))
elt = _doc.createElement(qName);
else
elt = _doc.createElement(localName);
if (_node == _doc) {
if (_doc.getDocumentElement() == null)
((QDocument) _doc).setDocumentElement(elt);
else if (_strictXml)
throw error(L.l("expected a single top-level element at `{0}'", qName));
}
_node.appendChild(elt);
_node = elt;
int length = attributes.getLength();
for (int i = 0; i < length; i++) {
String attrUri = attributes.getURI(i);
String attrQname = attributes.getQName(i);
String value = attributes.getValue(i);
Attr attr;
if (attrUri != null && ! attrUri.equals(""))
attr = _doc.createAttributeNS(attrUri, attrQname);
else if (! attrQname.equals(""))
attr = _doc.createAttribute(attrQname);
else
attr = _doc.createAttribute(attributes.getLocalName(i));
attr.setNodeValue(value);
((Element) _node).setAttributeNode(attr);
}
if (_extLocator != null)
((QElement) elt).setLocation(_extLocator.getSystemId(),
_extLocator.getFilename(),
_extLocator.getLineNumber(),
_extLocator.getColumnNumber());
QDocumentType dtd = (QDocumentType) _doc.getDoctype();
if (dtd != null) {
dtd.fillDefaults((QElement) elt);
}
}
public void dtd(QDocumentType dtd)
{
((QDocument) _doc).setDoctype(dtd);
((QDocument) _doc).appendChild(dtd);
}
public void attribute(String uri, String localName, String qName,
String value)
throws IOException
{
if (_node instanceof Element) {
Attr attr = _doc.createAttributeNS(uri, qName);
attr.setNodeValue(value);
((Element) _node).setAttributeNode(attr);
}
else
((QDocument) _node).setAttribute(qName, value);
}
public void endElement(String uri, String localName, String qName)
{
popText();
if (_node != null) // XXX:
_node = _node.getParentNode();
if (_node == null)
_node = _doc;
}
public void processingInstruction(String name, String data)
{
popText();
ProcessingInstruction pi = _doc.createProcessingInstruction(name, data);
_node.appendChild(pi);
}
/**
* Handles the callback for a comment.
*
* @param data the content of the comment.
*/
public void comment(char []buf, int offset, int length)
throws SAXException
{
try {
comment(new String(buf, offset, length));
} catch (IOException e) {
throw new SAXException(e);
}
}
/**
* Handles the callback for a comment.
*
* @param data the content of the comment.
*/
public void comment(String data)
throws IOException
{
popText();
Comment comment = _doc.createComment(data);
_node.appendChild(comment);
}
public boolean getEscapeText()
{
return _escapeText;
}
public void setEscapeText(boolean isEscaped)
{
_escapeText = isEscaped;
}
public void text(String text)
throws IOException
{
if (_singleText == null && _text.length() == 0) {
if (! text.equals(""))
_singleText = text;
}
else if (_singleText != null) {
_text.append(_singleText);
_text.append(text);
}
else
_text.append(text);
if (! _isCoalescing)
popText();
}
public void text(char []buffer, int offset, int length)
throws IOException
{
if (length == 0)
return;
if (_singleText != null) {
_singleText = null;
_text.append(_singleText);
}
_text.append(buffer, offset, length);
if (! _isCoalescing)
popText();
}
/**
* Adds text characters to the current document.
*/
public void characters(char []buffer, int offset, int length)
throws SAXException
{
if (length == 0)
return;
if (_strictXml && _node == _doc) {
if (_doc.getDocumentElement() == null) {
while (length > 0 && XmlChar.isWhitespace(buffer[offset])) {
offset++;
length--;
}
for (int i = 0; i < length; i++) {
if (buffer[offset + i] == '\n' || buffer[offset + i] == '\r') {
length = i;
break;
}
}
if (length > 16)
length = 16;
if (length > 0)
throw error(L.l("expected top element at `{0}'",
new String(buffer, offset, length)));
}
}
_text.append(buffer, offset, length);
/*
if (! isCoalescing)
popText();
*/
}
/**
* Handles the callback for ignorable whitespace.
*
* @param buffer the character buffer containing the whitespace.
* @param offset starting offset into the character buffer.
* @param length number of characters in the buffer.
*/
public void ignorableWhitespace(char []buffer, int offset, int length)
throws SAXException
{
if (! _skipWhitespace)
characters(buffer, offset, length);
}
public void entityReference(String name)
{
popText();
QEntityReference er = new QEntityReference(name);
er._owner = (QDocument) _doc;
_node.appendChild(er);
}
public void skippedEntity(String s)
{
_text.append(s);
}
public void cdata(String text)
throws IOException
{
popText();
_node.appendChild(_doc.createCDATASection(text));
}
public void cdata(char []buffer, int offset, int length)
throws IOException
{
cdata(new String(buffer, offset, length));
}
private void popText()
{
if (_singleText != null) {
Node text = _doc.createTextNode(_singleText);
_node.appendChild(text);
_singleText = null;
return;
}
if (_text.length() == 0)
return;
Node text = _doc.createTextNode(_text.toString());
_text.clear();
_node.appendChild(text);
}
public void fatalError(SAXParseException e)
throws SAXException
{
log.log(Level.FINE, e.toString(), e);
throw error(e.getMessage());
}
public void error(SAXParseException e)
throws SAXException
{
log.log(Level.FINER, e.toString(), e);
throw error(e.getMessage());
}
public void warning(SAXParseException e)
throws SAXException
{
log.log(Level.FINER, e.toString(), e);
}
/**
* Throws an appropriate error.
*/
public SAXException createError(Exception e)
{
if (e instanceof SAXException)
return (SAXException) e;
else
return new SAXException(e);
}
/**
* Returns a new parse exception with filename and line if available.
*/
XmlParseException error(String text)
{
String loc = "";
if (_extLocator != null) {
return new XmlParseException(_extLocator.getFilename(),
_extLocator.getLineNumber(),
text);
}
else if (_locator != null) {
return new XmlParseException(_locator.getSystemId(),
_locator.getLineNumber(),
text);
}
return new XmlParseException(text);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy