dombuilder.java

来自「RESIN 3.2 最新源码」· Java 代码 · 共 612 行

JAVA
612
字号
/* * Copyright (c) 1998-2008 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.xml2;import com.caucho.log.Log;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 javax.xml.namespace.QName;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 {  static final Logger log = Log.open(DOMBuilder.class);  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<QName> _prefixNames = new ArrayList<QName>();  private ArrayList<String> _prefixValues = new ArrayList<String>();  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.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)  {    if (_extLocator != null)      return new XmlParseException(_extLocator.getFilename() + ":" +                                   _extLocator.getLineNumber() + ": " + text);    else if (_locator != null)      return new XmlParseException(_locator.getSystemId() + ":" +                                   _locator.getLineNumber() + ": " + text);    else      return new XmlParseException(text);  }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?