/* See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * Esri Inc. licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.esri.gpt.framework.xml; import com.esri.gpt.framework.util.Val; import java.io.IOException; import java.util.ArrayList; import javax.xml.parsers.ParserConfigurationException; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; /** * Handles core SAX events during the parsing of an XML document. */ public class BaseSaxHandler extends DefaultHandler { // class variables ============================================================= // instance variables ========================================================== private StringBuffer _characters = new StringBuffer(); private ArrayList<String> _localNameStack = new ArrayList<String>(); private String _localPath = ""; // constructors ================================================================ /** Default constructor. */ public BaseSaxHandler() { super(); } // properties ================================================================== // methods ===================================================================== /** * Sets text node characters for a SAX element. * <br/>This is a core method for a SAX DefaultHandler. * @param ch the array of characters * @param start the starting position within the array * @param length the number of characters to read from the array * @throws SAXException if the exception occurs */ @Override public final void characters(char ch[], int start, int length) throws SAXException { if ((ch != null) && (length > 0)) { _characters.append(ch,start,length); } } /** * Ends the SAX document. * <br/>This is a core method for a SAX DefaultHandler. * @throws SAXException if a SAXException occurs */ @Override public void endDocument() throws SAXException { resetCharacters(); resetLocalNameStack(); } /** * Ends a SAX element. * <br/>This is a core method for a SAX DefaultHandler. * <br/>An onEndSaxElement event is triggered. * @param uri the uri namespace for the element * @param localName the local name for the element * @param qName the qualified name for the element * @throws SAXException if a SAXException occurs */ @Override public final void endElement(String uri, String localName, String qName) throws SAXException { try { onEndSaxElement(uri,localName,qName,_localPath,_characters.toString()); } finally { resetCharacters(); popLocalName(); } } /** * Triggered when an element is ended during the * parsing of an XML document. * <br/>There is no default implementation. * @param uri the uri namespace for the element * @param localName the local name for the element * @param qName the qualified name for the element * @param localPath the local path for the element * @param textNodeValue the text node value for the element * @throws SAXException if a SAXException occurs */ protected void onEndSaxElement(String uri, String localName, String qName, String localPath, String textNodeValue) throws SAXException { // no default implementation //System.err.println("onEnd: "+localPath+" = "+textNodeValue); } /** * Triggered when an element is started during the * parsing of an XML document. * <br/>There is no default implementation. * @param uri the uri namespace for the element * @param localName the local name for the element * @param qName the qualified name for the element * @param localPath the local path for the element * @param attributes the attributes for the element * @throws SAXException if a SAXException occurs */ protected void onStartSaxElement(String uri, String localName, String qName, String localPath, Attributes attributes) throws SAXException { // no default implementation //System.err.println("onStart: "+localPath); } /** * Starts a SAX parser on an XML string. * @param xml the XML string to parse * @param namespaceAware flag indication if the parser should be namespace aware * @throws ParserConfigurationException if the exception occurs * @throws SAXException if the exception occurs * @throws IOException if the exception occurs */ public void parse(String xml, boolean namespaceAware) throws ParserConfigurationException, SAXException, IOException { SaxUtil.parse(this,xml,namespaceAware); } /** * Pops a local element name from the stack and resets the local path * <br/>The name is removed from the stack. */ private void popLocalName() { int nSize = _localNameStack.size(); if (nSize > 0) { _localNameStack.remove(nSize - 1); } resetLocalPath(); } /** * Pushes a local element name onto the stack and resets the local path. * @param uri the uri namespace for the element * @param localName the local name for the element * @param qName the qualified name for the element */ private void pushLocalName(String uri, String localName, String qName) { String sName = Val.chkStr(qName); if (sName.length() == 0) { sName = Val.chkStr(localName); if (sName.length() == 0) { sName = "unknownElementName"; } } _localNameStack.add(sName); resetLocalPath(); } /** * Resets the text node characters for the current SAX element. */ private void resetCharacters() { _characters = new StringBuffer(); } /** * Resets the local element name stack. */ private void resetLocalNameStack() { _localNameStack = new ArrayList<String>(); resetLocalPath(); } /** * Resets the local path for the active element. * <br/>The local path is derived from the local name stack. */ private void resetLocalPath() { StringBuffer sbPath = new StringBuffer(); int n = _localNameStack.size(); for (int i=0;i<n;i++) { if (i > 0) { sbPath.append("/"); } String sName = (String)_localNameStack.get(i); sbPath.append(sName); } _localPath = sbPath.toString(); } /** * Starts the SAX document. * <br/>This is a core method for a SAX DefaultHandler. * @throws SAXException if a SAXException occurs */ @Override public void startDocument() throws SAXException { resetCharacters(); resetLocalNameStack(); } /** * Starts a SAX element. * <br/>This is a core method for a SAX DefaultHandler. * <br/>An onStartSaxElement event is triggered. * @param uri the uri namespace for the element * @param localName the local name for the element * @param qName the qualified name for the element * @param attributes the attributes for the element * @throws SAXException if a SAXException occurs */ @Override public final void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { resetCharacters(); pushLocalName(uri,localName,qName); onStartSaxElement(uri,localName,qName,_localPath,attributes); } }