All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hfg.xml.parser.SaxyParser Maven / Gradle / Ivy

There is a newer version: 20240423
Show newest version
package com.hfg.xml.parser;

import java.util.Stack;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.EmptyStackException;
import java.io.InputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import javax.xml.parsers.SAXParser;

import org.xml.sax.*;
import org.xml.sax.ext.LexicalHandler;
import org.xml.sax.helpers.AttributesImpl;

import com.hfg.util.BooleanUtil;
import com.hfg.xml.Doctype;
import com.hfg.xml.XMLNamespace;

//------------------------------------------------------------------------------
/**
  SaxyParser is a lightweight SAX parser.
  
Important (for me) differences between SaxyParser and Xerces:
  • SaxyParser does NOT close InputSources upon the completion of parsing.
  • SaxyParser can handle the interleaving of content and subtags.
@author J. Alex Taylor, hairyfatguy.com */ //------------------------------------------------------------------------------ // com.hfg XML/HTML Coding Library // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library 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. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com // [email protected] //------------------------------------------------------------------------------ public class SaxyParser extends SAXParser implements XMLReader { //########################################################################### // PUBLIC FIELDS //########################################################################### /** Parser property to enable entity expansion.
    http://hairyfatguy.com/sax/properties/entity-expansion
    
False by default. */ public static final String ENTITY_EXPANSION_PROPERTY = "http://hairyfatguy.com/sax/properties/entity-expansion"; /** Parser property to enable strict parsing mode.
    http://hairyfatguy.com/sax/properties/strict
    
False by default. */ public static final String STRICT_PROPERTY = "http://hairyfatguy.com/sax/properties/strict"; //########################################################################### // PRIVATE FIELDS //########################################################################### private Doctype mDoctype; private ContentHandler mContentHandler; private LexicalHandler mLexicalHandler; private DTDHandler mDTDHandler; private ErrorHandler mErrHandler; private EntityResolver mEntityResolver; private boolean debug = false; private boolean mExpandEntities = false; private boolean mStrict = false; private BufferedReader mBufferedReader; private int mLineCount; private int mColumn; private boolean mEOL; private char[] mTempBuffer = new char[100]; private int mState; private Stack mTagStack; private Stack mStateStack; private int mDepth; private Map mNamespaceMap; private Stack mDefaultNamespaceStack; // Enumerated parser states private static final int INITIAL = 0; private static final int IN_START_OF_TAG = 1; private static final int IN_XML_DECLARATION = 2; private static final int IN_DOCTYPE = 3; private static final int IN_START_TAG = 4; private static final int IN_END_TAG = 5; private static final int IN_CONTENT = 6; private static final int IN_ENTITY = 7; private static final int IN_CDATA = 8; private static final int IN_COMMENT = 9; private static final int IN_EMPTY_TAG = 10; private static final int IN_MIDDLE_OF_START_TAG = 11; private static final int IN_ATT_NAME = 12; private static final int IN_ATT_VALUE = 13; private static final int DONE = 14; private static final int TAG_START = '<'; private static final int TAG_END = '>'; private static final int ENTITY_START = '&'; private static int MAX_ENTITY_LENGTH = 12; private static String XMLNS = "xmlns".intern(); private static final String LEXICAL_HANDLER_PROPERTY = "http://xml.org/sax/properties/lexical-handler"; //########################################################################### // CONSTRUCTORS //########################################################################### //--------------------------------------------------------------------------- public SaxyParser() { super(); } //########################################################################### // PUBLIC METHODS //########################################################################### //--------------------------------------------------------------------------- /** After parsing, the Doctype (if one was set) can be retrieved here. */ public Doctype getDoctype() { return mDoctype; } // METHODS REQUIRED TO EXTEND SaxParser //--------------------------------------------------------------------------- @SuppressWarnings("deprecation") public Parser getParser() throws SAXException { throw new SAXException("getParser() not supported. User getXMLReader()."); } //--------------------------------------------------------------------------- public XMLReader getXMLReader() { return this; } //--------------------------------------------------------------------------- public boolean isNamespaceAware() { return true; } //--------------------------------------------------------------------------- public boolean isValidating() { return false; } //--------------------------------------------------------------------------- public void setProperty(String inName, Object inValue) throws SAXNotRecognizedException { if (inName.equals(LEXICAL_HANDLER_PROPERTY)) { setLexicalHandler((LexicalHandler)inValue); } else if (inName.equals(ENTITY_EXPANSION_PROPERTY)) { mExpandEntities = BooleanUtil.valueOf(inValue); } else if (inName.equals(STRICT_PROPERTY)) { mStrict = BooleanUtil.valueOf(inValue); } else { throw new SAXNotRecognizedException("Property '" + inName + "' not supported."); } } //--------------------------------------------------------------------------- public Object getProperty(String inName) throws SAXNotRecognizedException { Object obj; if (inName.equals(LEXICAL_HANDLER_PROPERTY)) { obj = getLexicalHandler(); } else if (inName.equals(ENTITY_EXPANSION_PROPERTY)) { obj = new Boolean(mExpandEntities); } else if (inName.equals(STRICT_PROPERTY)) { obj = new Boolean(mStrict); } else { throw new SAXNotRecognizedException("Property '" + inName + "' not supported."); } return obj; } // METHODS REQUIRED BY THE XMLReader interface //--------------------------------------------------------------------------- public ContentHandler getContentHandler() { return mContentHandler; } //--------------------------------------------------------------------------- public void setContentHandler(ContentHandler handler) { mContentHandler = handler; } //--------------------------------------------------------------------------- public DTDHandler getDTDHandler() { return mDTDHandler; } //--------------------------------------------------------------------------- public void setDTDHandler(DTDHandler handler) { mDTDHandler = handler; } //--------------------------------------------------------------------------- public ErrorHandler getErrorHandler() { return mErrHandler; } //--------------------------------------------------------------------------- public void setErrorHandler(ErrorHandler handler) { mErrHandler = handler; } //--------------------------------------------------------------------------- public EntityResolver getEntityResolver() { return mEntityResolver; } //--------------------------------------------------------------------------- public void setEntityResolver(EntityResolver resolver) { mEntityResolver = resolver; } //--------------------------------------------------------------------------- public void setFeature(String inName, boolean inValue) throws SAXNotRecognizedException { if (inName.equals("http://xml.org/sax/features/namespaces")) { // Namespaces is always on. } else if (inName.equals("http://xml.org/sax/features/namespace-prefixes")) { // Always set to false. } else { throw new SAXNotRecognizedException("Feature '" + inName + "' not supported."); } } //--------------------------------------------------------------------------- public boolean getFeature(String inName) throws SAXNotRecognizedException { boolean outValue = false; if (inName.equals("http://xml.org/sax/features/namespaces")) { outValue = true; } else if (inName.equals("http://xml.org/sax/features/namespace-prefixes")) { outValue = false; } else { throw new SAXNotRecognizedException("Feature '" + inName + "' not supported."); } return outValue; } /* //--------------------------------------------------------------------------- public void setLocale(Locale locale) throws SAXException { throw new SAXException("setLocale() is not supported by this parser."); } */ //--------------------------------------------------------------------------- public LexicalHandler getLexicalHandler() { return mLexicalHandler; } //--------------------------------------------------------------------------- public void setLexicalHandler(LexicalHandler handler) { mLexicalHandler = handler; } //--------------------------------------------------------------------------- public void parse(String inSystemId) throws SAXException, IOException { parse(new InputSource(inSystemId)); } //--------------------------------------------------------------------------- public XMLNamespace getCurrentDefaultNamespace() { return (mDefaultNamespaceStack.size() > 0 ? XMLNamespace.getNamespace(mDefaultNamespaceStack.peek().getURI()) : null); } //--------------------------------------------------------------------------- private int nextChar() throws IOException { int c = mBufferedReader.read(); if (c == -1) throw new EOFException(); // Need to map \r, \r\n, and \n to \n // See XML spec section 2.11 if (c <= '\n') { if (c == '\n' && mEOL) { mEOL = false; c = nextChar(); } else if (mEOL) { mEOL = false; } else if (c == '\n') { mLineCount++; mColumn = 0; } else if (c == '\r') { mEOL = true; c = '\n'; mLineCount++; mColumn = 0; } else { mColumn++; } } else { mColumn++; } return c; } //--------------------------------------------------------------------------- private void skipEndTag(int c) throws SAXException, IOException { String openTag = null; try { openTag = (String) mTagStack.peek(); } catch (EmptyStackException e) { StringBuffer extraEndTag = new StringBuffer(c); while ((c = nextChar()) != TAG_END) { extraEndTag.append(c); } throw new SAXException("End tag '" + extraEndTag + "' didn't have a matching start tag!"); } mTempBuffer[0] = (char)c; int bytesToRead = openTag.length(); if (mBufferedReader.read(mTempBuffer, 1, bytesToRead) != bytesToRead) { throw new SAXException("Expected end tag '" + openTag + "' but reached the end of the file."); } mColumn+=bytesToRead; if (!openTag.equals(new String(mTempBuffer, 0, openTag.length()))) { throw new SAXException("Expected end tag '" + openTag + "' but found '" + (new String(mTempBuffer, 0, openTag.length())) + "' instead!" + " Line: " + mLineCount + " Col: " + mColumn); } if (mTempBuffer[bytesToRead] != TAG_END) { throw new SAXException("Problem with end tag '" + mTempBuffer[bytesToRead] + "'! Line: " + mLineCount + " Col: " + mColumn); } } //--------------------------------------------------------------------------- public void parse(InputSource source) throws SAXException, IOException { initNamespaceStructures(); mStateStack = new Stack(); mTagStack = new Stack(); mDepth = 0; XMLStringBuffer buffer = new XMLStringBuffer(); XMLStringBuffer entity = new XMLStringBuffer(); String tagName = null; String tagURI = null; String tagLocalName = null; AttributesImpl attributes = new AttributesImpl(); String attName = null; mLineCount = 1; mColumn = 0; mEOL = false; // int quoteChar = '"'; int quoteChar = -1; // I'm not sure of any other way that will work to even out the differences between character and binary sources. try { mBufferedReader = new BufferedReader(source.getCharacterStream(), 8192); } catch (NullPointerException e) { mBufferedReader = new BufferedReader(new InputStreamReader(source.getByteStream()), 8192); } mContentHandler.startDocument(); mState = INITIAL; pushState(); try { int c; while (mState != DONE) { c = nextChar(); switch (mState) { case IN_CONTENT: while (true) { // We are in tag content if (c == TAG_START) { pushState(); mState = IN_START_OF_TAG; if (buffer.length() > 0) { if (buffer.hasNonwhitespaceContent()) { mContentHandler.characters(buffer.getCharArray(), 0, buffer.length()); } buffer.clear(); } break; } else if (c == ENTITY_START) { pushState(); mState = IN_ENTITY; entity.clear(); break; } else { buffer.append((char) c); } c = nextChar(); } break; case INITIAL: while (true) { if (c == -1) { mState = DONE; break; } else if (c == TAG_START) { pushState(); mState = IN_START_OF_TAG; break; } else if (!Character.isWhitespace((char) c)) { throw new SAXException("Unexpected text outside of tags (" + (char) c + ")!" + " Line: " + mLineCount + " Col: " + mColumn); } c = nextChar(); } break; case IN_START_OF_TAG: // What type of tag does it look like we've wandered into? if (c == '/') { popState(); mState = IN_END_TAG; tagName = null; } else if (c == '?') { mState = IN_XML_DECLARATION; } else { mState = IN_START_TAG; tagName = null; attributes.clear(); buffer.append((char) c); } break; case IN_START_TAG: while (true) { if (Character.isWhitespace((char) c)) { tagName = buffer.toString(); pushDepth(tagName); buffer.clear(); mState = IN_MIDDLE_OF_START_TAG; break; } else if (c == TAG_END) { if (null == tagName) tagName = buffer.toString(); pushDepth(tagName); tagURI = getNamespaceURI(getNamespacePrefix(tagName)); tagLocalName = getLocalName(tagName); mContentHandler.startElement(tagURI, tagLocalName, tagName, attributes); mState = IN_CONTENT; buffer.clear(); break; } else if (c == '/') { if (null == tagName) tagName = buffer.toString(); pushDepth(tagName); mState = IN_EMPTY_TAG; break; } else if (c == '-' && buffer.toString().equals("!-")) { mState = IN_COMMENT; break; } else if (c == '[' && buffer.toString().equals("![CDATA")) { mState = IN_CDATA; buffer.clear(); break; } else if (c == 'E' && buffer.toString().equals("!DOCTYP")) { mState = IN_DOCTYPE; // buffer.clear(); buffer.prepend("<"); buffer.append((char) c); break; } else { buffer.append((char) c); } c = nextChar(); } break; case IN_MIDDLE_OF_START_TAG: while (true) { if (c == TAG_END) { tagURI = getNamespaceURI(getNamespacePrefix(tagName)); tagLocalName = getLocalName(tagName); mContentHandler.startElement(tagURI, tagLocalName, tagName, attributes); buffer.clear(); mState = IN_CONTENT; break; } else if (c == '/') { mState = IN_EMPTY_TAG; break; } else if (!Character.isWhitespace((char) c)) { mState = IN_ATT_NAME; attName = null; // buffer.clear(); buffer.append((char) c); break; } c = nextChar(); } break; case IN_ATT_NAME: while (true) { if (c == '=') { attName = buffer.toString(); mState = IN_ATT_VALUE; buffer.clear(); break; } else { buffer.append((char) c); } c = nextChar(); } break; case IN_ATT_VALUE: if (quoteChar == -1) { if (c == '"' || c == '\'') { quoteChar = c; c = nextChar(); } else { throw new SAXException("Improper attribute construction. Expected a quote character!"); } } while (true) { if (c == quoteChar) { String attValue = buffer.toString(); //debugMsg("attName: '" + attName + "'"); if (attName.startsWith("xmlns:") || attName.equals(XMLNS)) { extractNamespaceDeclaration(attName, attValue); } attributes.addAttribute("", attName, attName, "CDATA", attValue); buffer.clear(); quoteChar = -1; mState = IN_MIDDLE_OF_START_TAG; break; } else if (c == ENTITY_START) { pushState(); mState = IN_ENTITY; entity.clear(); break; } else if (" \r\n\u0009".indexOf(c) >= 0) { buffer.append(' '); } else { buffer.append((char) c); } c = nextChar(); } break; case IN_EMPTY_TAG: if (c != TAG_END) { throw new SAXException("Expected '>' for tag <" + tagName + "/>" + " Line: " + mLineCount + " Col: " + mColumn); } tagURI = getNamespaceURI(getNamespacePrefix(tagName)); tagLocalName = getLocalName(tagName); mContentHandler.startElement(tagURI, tagLocalName, tagName, attributes); mContentHandler.endElement(tagURI, tagLocalName, tagName); mTagStack.pop(); buffer.clear(); popDepth(); popState(); break; case IN_END_TAG: // XXXXXXXXXXXXX The ending tag better be the one currently open. // (Otherwise it's an error.) Try to take advantage of this precognition. //String openTag = (String) mTagStack.pop(); skipEndTag(c); tagName = (String) mTagStack.pop(); mContentHandler.endElement(tagURI, getLocalName(tagName), tagName); buffer.clear(); popDepth(); popState(); /* while (true) { // We are in an end tag if (c == TAG_END) { tagName = buffer.toString(); if (mDepth == 0) { throw new SAXException("Closing tag '' " + "had no opening tag!" + " Line: " + mLineCount + " Col: " + mColumn); } mContentHandler.endElement(tagURI, tagLocalName, tagName); buffer.clear(); popDepth(tagName); popState(); break; } else { buffer.append((char) c); } c = nextChar(); } */ break; case IN_ENTITY: boolean recoverFromInvalidEntity = false; while (true) { if (c == ';') { String expandedEntity = expandEntity(entity.toString()); buffer.append((expandedEntity != null ? expandedEntity : "&" + entity.toString() + ";")); entity.clear(); popState(); break; } else if (Character.isWhitespace((char) c)) { if (mStrict) { throw new SAXException("Character entity contains whitespace !?" + " Line: " + mLineCount + " Col: " + mColumn); } else { recoverFromInvalidEntity = true; break; } } else if (c == '"' || c == '\'' || c == '>') { if (mStrict) { throw new SAXException("Character entity contains illegal character !?" + " Line: " + mLineCount + " Col: " + mColumn); } else { recoverFromInvalidEntity = true; break; } } else if (entity.length() >= MAX_ENTITY_LENGTH) { // Either the entity was malformed or the ampersand should have been escaped. if (mStrict) { throw new SAXException("Max entity length (" + MAX_ENTITY_LENGTH + ") exceeded!?" + " Line: " + mLineCount + " Col: " + mColumn); } else { recoverFromInvalidEntity = true; break; } } else { entity.append((char) c); } c = nextChar(); } if (recoverFromInvalidEntity) { entity.append((char) c); buffer.append("&" + entity.toString()); entity.clear(); popState(); if (IN_ATT_VALUE == mState) { if (c == quoteChar) { String attValue = buffer.toString(); //debugMsg("attName: '" + attName + "'"); if (attName.startsWith("xmlns:") || attName.equals(XMLNS)) { extractNamespaceDeclaration(attName, attValue); } attributes.addAttribute("", attName, attName, "CDATA", attValue); buffer.clear(); quoteChar = -1; mState = IN_MIDDLE_OF_START_TAG; break; } } else if (IN_CONTENT == mState) { if (c == TAG_START) { pushState(); mState = IN_START_OF_TAG; if (buffer.length() > 0) { if (buffer.hasNonwhitespaceContent()) { mContentHandler.characters(buffer.getCharArray(), 0, buffer.length()); } buffer.clear(); } } } } break; case IN_CDATA: while (true) { if (c == TAG_END && buffer.toString().endsWith("]]")) { buffer.setLength(buffer.length() - 2); mContentHandler.characters(buffer.getCharArray(), 0, buffer.length()); popState(); buffer.clear(); break; } else { buffer.append((char) c); } c = nextChar(); } break; case IN_COMMENT: while (true) { // Inside a comment: if (c == TAG_END && buffer.toString().endsWith("--")) { if (mLexicalHandler != null) mLexicalHandler.comment(buffer.getCharArray(), 2, buffer.length() - 4); popState(); buffer.clear(); break; } else { buffer.append((char) c); } c = nextChar(); } break; case IN_XML_DECLARATION: while (true) { buffer.append((char) c); if (c == TAG_END) { popState(); if (mState == DONE) mState = INITIAL; buffer.clear(); break; } c = nextChar(); } break; case IN_DOCTYPE: while (true) { buffer.append((char) c); if (c == TAG_END) { popState(); if (mState == DONE) mState = INITIAL; mDoctype = Doctype.valueOf(buffer.toString()); buffer.clear(); break; } c = nextChar(); } break; } } } catch (EOFException e) { // Ignore. } if (mDepth != 0) { throw new SAXException("XML Document is not properly ended! " + "Remaining depth= " + mDepth); } else if (mState != INITIAL && mState != DONE) { throw new SAXException("Parser ended in bad state (" + mState + ")!"); } else { mContentHandler.endDocument(); } } //########################################################################### // PRIVATE METHODS //########################################################################### //--------------------------------------------------------------------------- private void debugMsg(String inMsg) { if (debug) { System.err.println(inMsg); } } //--------------------------------------------------------------------------- private String expandEntity(String inEntity) throws SAXException { String expandedEntity = null; if (mExpandEntities) { if (inEntity.startsWith("#")) { if (inEntity.charAt(1) == 'x') { // Hex expandedEntity = "" + (char) Integer.parseInt(inEntity.substring(2), 16); } else { // Decimal expandedEntity = "" + (char) Integer.parseInt(inEntity.substring(1)); } } else { // Try to resolve it with our battery of standard entity classes. expandedEntity = SpecialCharacterEntities.resolveEntity(inEntity); if (null == expandedEntity) { expandedEntity = Latin1Entities.getInstance().getNumericEntity(inEntity); } if (null == expandedEntity) { expandedEntity = SymbolEntities.getInstance().getNumericEntity(inEntity); } if (expandedEntity != null && expandedEntity.startsWith("#")) { expandedEntity = "" + (char) Integer.parseInt(expandedEntity.substring(1)); } } // Have we resolved it yet? If not, use the custom entity resolver if one // has been specified. if (null == expandedEntity) { if (mEntityResolver != null) { InputStream inStream = null; try { InputSource expandedEntitySource = mEntityResolver.resolveEntity(null, inEntity); if (expandedEntitySource != null) { inStream = expandedEntitySource.getByteStream(); StringBuffer entityBuffer = new StringBuffer(); int c = 0; while ((c = inStream.read()) != -1) { entityBuffer.append((char) c); } expandedEntity = entityBuffer.toString(); } else { throw new SAXException("'" + inEntity + "' is not a recognized entity."); } } catch (IOException e) { throw new SAXException(e); } finally { if (inStream != null) { try { inStream.close(); } catch (IOException e) { } } } } } } return expandedEntity; } //--------------------------------------------------------------------------- private Attributes generateAttributeList(HashMap inAttributes) { // NOTE: WE ARE NOT CURRENTLY SUPPORTING ATTRIBUTE TYPES XXXXXXXXXXXXXX // The attribute type is one of the strings "CDATA", "ID", "IDREF", "IDREFS", // "NMTOKEN", "NMTOKENS", "ENTITY", "ENTITIES", or "NOTATION" (always in upper case). // // If the parser has not read a declaration for the attribute, or if the parser // does not report attribute types, then it must return the value "CDATA" as // stated in the XML 1.0 Recommentation (clause 3.3.3, "Attribute-Value Normalization"). // // For an enumerated attribute that is not a notation, the parser will report // the type as "NMTOKEN". String attType = "CDATA"; AttributesImpl attList = new AttributesImpl(); if (inAttributes != null) { Iterator iter = inAttributes.entrySet().iterator(); while (iter.hasNext()) { Map.Entry att = (Map.Entry) iter.next(); attList.addAttribute("", (String) att.getKey(), (String) att.getKey(), attType, (String) att.getValue()); } } return attList; } //--------------------------------------------------------------------------- private void initNamespaceStructures() { mNamespaceMap = new HashMap(); mDefaultNamespaceStack = null; } //--------------------------------------------------------------------------- private void pushState() { mStateStack.push(new Integer(mState)); //debugMsg(mState + " pushed onto the StateStack"); } //--------------------------------------------------------------------------- private void popState() { mState = ((Integer) mStateStack.pop()).intValue(); //debugMsg(mState + " popped off the StateStack"); } //--------------------------------------------------------------------------- private void pushDepth(String inTagName) { mDepth++; //debugMsg("Depth pushed to " + mDepth); mTagStack.push(inTagName); } //--------------------------------------------------------------------------- private void popDepth() throws SAXException { //debugMsg("Depth popped to " + (mDepth - 1)); if (mNamespaceMap.size() > 0) { // Can't use an iterator because we might delete the map entry and that would // cause a ConcurrentModificaitonException. Object[] prefixes = mNamespaceMap.keySet().toArray(); for (int i = 0; i < prefixes.length; i++) { String prefix = (String) prefixes[i]; Stack namespaceStack = (Stack) mNamespaceMap.get(prefix); // There must be at least one value on the stack or we should have deleted // the map entry for the prefix. Namespace namespace = (Namespace) namespaceStack.peek(); if (namespace.getTagLevel() >= mDepth) { namespaceStack.pop(); if (namespaceStack.size() == 0) { mNamespaceMap.remove(prefix); } } } } // Adjust the default namespace stack if necessary. if (mDefaultNamespaceStack != null && mDefaultNamespaceStack.size() > 0) { Namespace namespace = (Namespace) mDefaultNamespaceStack.peek(); if (namespace.getTagLevel() >= mDepth) { mDefaultNamespaceStack.pop(); } } mDepth--; /* String openTag = (String) mTagStack.pop(); if (!inTagName.equals(openTag)) { throw new SAXException("Tag mismatch! Tag '" + openTag + "' was open " + "but the closing tag was '" + inTagName + "'!"); } */ if (mDepth == 0) popState(); } //--------------------------------------------------------------------------- private void extractNamespaceDeclaration(String inName, String inURI) { int index = inName.indexOf(":"); if (index > 0) { String prefix = inName.substring(index + 1); //debugMsg("Adding namespace '" + prefix + "': " + inURI); Stack namespaceStack = (Stack) mNamespaceMap.get(prefix); if (null == namespaceStack) { namespaceStack = new Stack(); mNamespaceMap.put(prefix, namespaceStack); } namespaceStack.push(new Namespace(inURI, mDepth)); XMLNamespace.getNamespace(prefix, inURI); // Register the namespace } else { //debugMsg("Setting default namespace: " + inURI); if (null == mDefaultNamespaceStack) { mDefaultNamespaceStack = new Stack(); } mDefaultNamespaceStack.push(new Namespace(inURI, mDepth)); XMLNamespace.getNamespace(inURI); // Register the namespace } } //--------------------------------------------------------------------------- private String getNamespaceURI(String inPrefix) { String uri = null; if (inPrefix != null) { Stack namespaceStack = (Stack) mNamespaceMap.get(inPrefix); if (namespaceStack != null) { uri = ((Namespace) namespaceStack.peek()).getURI(); } } if (null == uri && mDefaultNamespaceStack != null && mDefaultNamespaceStack.size() > 0) { uri = ((Namespace)mDefaultNamespaceStack.peek()).getURI(); } if (null == uri) uri = ""; return uri; } //--------------------------------------------------------------------------- private String getNamespacePrefix(String inValue) { String returnValue = null; int i = inValue.indexOf(":"); if (i > 0) { returnValue = inValue.substring(0, i); } return returnValue; } //--------------------------------------------------------------------------- private String getLocalName(String inValue) { String returnValue = inValue; int i = inValue.indexOf(":"); if (i > 0) { returnValue = inValue.substring(i + 1); } return returnValue; } //########################################################################### // INNER CLASSES //########################################################################### private class EOFException extends RuntimeException { } private class Namespace { private String mURI; private int mTagLevel; //------------------------------------------------------------------------ public Namespace(String inURI, int inTagLevel) { mURI = inURI; mTagLevel = inTagLevel; } //------------------------------------------------------------------------ public String getURI() { return mURI; } //------------------------------------------------------------------------ public int getTagLevel() { return mTagLevel; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy