📄 saxcontenthandler.java
字号:
/* * Copyright 2001 (C) MetaStuff, Ltd. All Rights Reserved. * * This software is open source. * See the bottom of this file for the licence. * * $Id: SAXContentHandler.java,v 1.5 2003/11/02 18:04:59 per_nyfelt Exp $ */package org.dom4j.io;import org.dom4j.*;import org.dom4j.dtd.AttributeDecl;import org.dom4j.dtd.ElementDecl;import org.dom4j.dtd.ExternalEntityDecl;import org.dom4j.dtd.InternalEntityDecl;import org.dom4j.tree.AbstractElement;import org.dom4j.tree.AbstractNamespace;import org.dom4j.tree.NamespaceStack;import org.xml.sax.*;import org.xml.sax.ext.DeclHandler;import org.xml.sax.ext.LexicalHandler;import org.xml.sax.helpers.DefaultHandler;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;/** <p><code>SAXContentHandler</code> builds a dom4j tree via SAX events.</p> * * @author <a href="mailto:jstrachan@apache.org">James Strachan</a> * @version $Revision: 1.5 $ */public class SAXContentHandler extends DefaultHandler implements LexicalHandler, DeclHandler, DTDHandler { /** The factory used to create new <code>Document</code> instances */ private NodeFactory nodeFactory; /** The document that is being built */ private Document document; /** stack of <code>Element</code> objects */ private ElementStack elementStack; /** stack of <code>AbstractNamespace</code> and <code>QName</code> objects */ private NamespaceStack namespaceStack; /** the <code>ElementHandler</code> called as the elements are complete */ private ElementHandler elementHandler; /** The name of the current entity */ private String entity; /** Flag used to indicate that we are inside a DTD section */ private boolean insideDTDSection; /** Flag used to indicate that we are inside a CDATA section */ private boolean insideCDATASection; /** namespaces that are available for use */ private Map availableNamespaceMap = new HashMap(); /** declared namespaces that are not yet available for use */ private List declaredNamespaceList = new ArrayList(); /** internal DTD declarations */ private List internalDTDDeclarations; /** external DTD declarations */ private List externalDTDDeclarations; /** The number of namespaces that are declared in the current scope */ private int declaredNamespaceIndex; /** The entity resolver */ private EntityResolver entityResolver; private InputSource inputSource; /** The current element we are on */ private Element currentElement; /** Should internal DTD declarations be expanded into a List in the DTD */ private boolean includeInternalDTDDeclarations = false; /** Should external DTD declarations be expanded into a List in the DTD */ private boolean includeExternalDTDDeclarations = false; /** The number of levels deep we are inside a startEntity / endEntity call */ private int entityLevel; /** Are we in an internal DTD subset? */ private boolean internalDTDsubset = false; /** Whether adjacent text nodes should be merged */ private boolean mergeAdjacentText = false; /** Have we added text to the buffer */ private boolean textInTextBuffer = false; /** Should we ignore comments */ private boolean ignoreComments = false; /** Buffer used to concatenate text together */ private StringBuffer textBuffer; /** Holds value of property stripWhitespaceText. */ private boolean stripWhitespaceText = false; public SAXContentHandler() { this( (NodeFactory) DocumentFactory.getInstance() ); } /** * @deprecated Use SAXContentHandler(NodeFactory) instead */ public SAXContentHandler(DocumentFactory documentFactory) { this.nodeFactory = documentFactory; this.namespaceStack = new NamespaceStack(nodeFactory); } public SAXContentHandler(NodeFactory nodeFactory) { this.nodeFactory = nodeFactory; this.namespaceStack = new NamespaceStack(nodeFactory); } /** * @deprecated Use SAXContentHandler(NodeFactory, ElementHandler) instead. */ public SAXContentHandler(DocumentFactory documentFactory, ElementHandler elementHandler) { this.nodeFactory = documentFactory; this.elementHandler = elementHandler; this.namespaceStack = new NamespaceStack(nodeFactory); } public SAXContentHandler(NodeFactory nodeFactory, ElementHandler elementHandler) { this.nodeFactory = nodeFactory; this.elementHandler = elementHandler; this.namespaceStack = new NamespaceStack(nodeFactory); } /** * @deprecated Use SAXContentHandler(NodeFactory, ElementHandler, ElementStack) instead. */ public SAXContentHandler(DocumentFactory documentFactory, ElementHandler elementHandler, ElementStack elementStack) { this.nodeFactory = documentFactory; this.elementHandler = elementHandler; this.elementStack = elementStack; this.namespaceStack = new NamespaceStack(nodeFactory); } public SAXContentHandler(NodeFactory nodeFactory, ElementHandler elementHandler, ElementStack elementStack) { this.nodeFactory = nodeFactory; this.elementHandler = elementHandler; this.elementStack = elementStack; this.namespaceStack = new NamespaceStack(nodeFactory); } /** @return the document that has been or is being built */ public Document getDocument() { if ( document == null ) { document = createDocument(); } return document; } // ContentHandler interface //------------------------------------------------------------------------- public void processingInstruction(String target, String data) throws SAXException { if ( mergeAdjacentText && textInTextBuffer ) { completeCurrentTextNode(); } if ( currentElement != null ) { currentElement.addProcessingInstruction(target, data); } else { document.addProcessingInstruction(target, data); } } public void startPrefixMapping(String prefix, String uri) throws SAXException { namespaceStack.push( prefix, uri ); } public void endPrefixMapping(String prefix) throws SAXException { namespaceStack.pop( prefix ); declaredNamespaceIndex = namespaceStack.size(); } public void startDocument() throws SAXException { document = createDocument(); currentElement = null; if ( elementStack == null ) { elementStack = createElementStack(); } else { elementStack.clear(); } if ( (elementHandler != null) && (elementHandler instanceof DispatchHandler) ) { elementStack.setDispatchHandler((DispatchHandler)elementHandler); } namespaceStack.clear(); declaredNamespaceIndex = 0; if ( mergeAdjacentText && textBuffer == null ) { textBuffer = new StringBuffer(); } textInTextBuffer = false; } public void endDocument() throws SAXException { namespaceStack.clear(); elementStack.clear(); currentElement = null; textBuffer = null; } public void startElement(String namespaceURI, String localName, String qualifiedName, Attributes attributes) throws SAXException { if ( mergeAdjacentText && textInTextBuffer ) { completeCurrentTextNode(); } QName qName = namespaceStack.getQName( namespaceURI, localName, qualifiedName ); Branch branch = currentElement; if ( branch == null ) { branch = document; } Element element = branch.addElement(qName); // add all declared namespaces addDeclaredNamespaces(element); // now lets add all attribute values addAttributes( element, attributes ); elementStack.pushElement(element); currentElement = element; if ( elementHandler != null ) { elementHandler.onStart(elementStack); } } public void endElement(String namespaceURI, String localName, String qName) { if ( mergeAdjacentText && textInTextBuffer ) { completeCurrentTextNode(); } if ( elementHandler != null && currentElement != null ) { elementHandler.onEnd(elementStack); } elementStack.popElement(); currentElement = elementStack.peekElement(); } public void characters(char[] ch, int start, int end) throws SAXException { if ( end == 0 ) { return; } if ( currentElement != null ) { if (entity != null) { if ( mergeAdjacentText && textInTextBuffer ) { completeCurrentTextNode(); } currentElement.addEntity(entity, new String(ch, start, end)); entity = null; } else if (insideCDATASection) { if ( mergeAdjacentText && textInTextBuffer ) { completeCurrentTextNode(); } currentElement.addCDATA(new String(ch, start, end)); } else { if ( mergeAdjacentText ) { textBuffer.append(ch, start, end); textInTextBuffer = true; } else { currentElement.addText(new String(ch, start, end)); } } } } // ErrorHandler interface //------------------------------------------------------------------------- /** This method is called when a warning occurs during the parsing * of the document. * This method does nothing. */ public void warning(SAXParseException exception) throws SAXException { // ignore warnings by default } /** This method is called when an error is detected during parsing * such as a validation error. * This method rethrows the exception */ public void error(SAXParseException exception) throws SAXException { throw exception; } /** This method is called when a fatal error occurs during parsing. * This method rethrows the exception */ public void fatalError(SAXParseException exception) throws SAXException { throw exception; } // LexicalHandler interface //------------------------------------------------------------------------- public void startDTD(String name, String publicId, String systemId) throws SAXException { if (document != null) { document.addDocType(name, publicId, systemId); } insideDTDSection = true; internalDTDsubset = true; } public void endDTD() throws SAXException { insideDTDSection = false; if ( document != null ) { DocumentType docType = document.getDocType(); if ( docType != null ) { if ( internalDTDDeclarations != null ) { docType.setInternalDeclarations( internalDTDDeclarations ); } if ( externalDTDDeclarations != null ) { docType.setExternalDeclarations( externalDTDDeclarations ); } } } internalDTDDeclarations = null; externalDTDDeclarations = null; } public void startEntity(String name) throws SAXException { ++entityLevel; // Ignore DTD references entity = null; if (! insideDTDSection ) { if ( ! isIgnorableEntity(name) ) { entity = name; } } // internal DTD subsets can only appear outside of a // startEntity/endEntity block // see the startDTD method in // http://dom4j.org/javadoc/org/xml/sax/ext/LexicalHandler.html // or here:- // http://dom4j.org/javadoc/org/xml/sax/ext/LexicalHandler.html#startDTD(java.lang.String, java.lang.String, java.lang.String) internalDTDsubset = false; } public void endEntity(String name) throws SAXException { --entityLevel; entity = null; if ( entityLevel == 0 ) { internalDTDsubset = true; } } public void startCDATA() throws SAXException { insideCDATASection = true; } public void endCDATA() throws SAXException { insideCDATASection = false; } public void comment(char[] ch, int start, int end) throws SAXException { if (!ignoreComments) { if ( mergeAdjacentText && textInTextBuffer ) { completeCurrentTextNode(); } String text = new String(ch, start, end); if (!insideDTDSection && text.length() > 0) { if ( currentElement != null ) { currentElement.addComment(text); } else { document.addComment(text); } } } } // DeclHandler interface //------------------------------------------------------------------------- /** * Report an element type declaration. * * <p>The content model will consist of the string "EMPTY", the * string "ANY", or a parenthesised group, optionally followed * by an occurrence indicator. The model will be normalized so * that all parameter entities are fully resolved and all whitespace * is removed,and will include the enclosing parentheses. Other * normalization (such as removing redundant parentheses or * simplifying occurrence indicators) is at the discretion of the * parser.</p> * * @param name The element type name. * @param model The content model as a normalized string. * @exception SAXException The application may raise an exception. */ public void elementDecl(String name, String model) throws SAXException { if ( internalDTDsubset ) { if ( includeInternalDTDDeclarations ) { addDTDDeclaration( new ElementDecl( name, model ) ); } } else { if ( includeExternalDTDDeclarations ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -