📄 xmlparser.java
字号:
// ========================================================================// Copyright 2004-2005 Mort Bay Consulting Pty. Ltd.// ------------------------------------------------------------------------// Licensed 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 org.mortbay.xml;import java.io.File;import java.io.IOException;import java.io.InputStream;import java.net.URL;import java.util.AbstractList;import java.util.ArrayList;import java.util.HashMap;import java.util.Iterator;import java.util.Map;import java.util.NoSuchElementException;import java.util.Stack;import java.util.StringTokenizer;import javax.xml.parsers.SAXParser;import javax.xml.parsers.SAXParserFactory;import org.mortbay.log.Log;import org.mortbay.util.LazyList;import org.xml.sax.Attributes;import org.xml.sax.ContentHandler;import org.xml.sax.InputSource;import org.xml.sax.SAXException;import org.xml.sax.SAXParseException;import org.xml.sax.XMLReader;import org.xml.sax.helpers.DefaultHandler;/*--------------------------------------------------------------*//** * XML Parser wrapper. This class wraps any standard JAXP1.1 parser with convieniant error and * entity handlers and a mini dom-like document tree. * <P> * By default, the parser is created as a validating parser only if xerces is present. This can be * configured by setting the "org.mortbay.xml.XmlParser.Validating" system property. * * @author Greg Wilkins (gregw) */public class XmlParser{ private Map _redirectMap = new HashMap(); private SAXParser _parser; private Map _observerMap; private Stack _observers = new Stack(); private String _xpath; private Object _xpaths; private String _dtd; /* ------------------------------------------------------------ */ /** * Construct */ public XmlParser() { SAXParserFactory factory = SAXParserFactory.newInstance(); boolean validating_dft = factory.getClass().toString().startsWith("org.apache.xerces."); String validating_prop = System.getProperty("org.mortbay.xml.XmlParser.Validating", validating_dft ? "true" : "false"); boolean notValidating = Boolean.getBoolean("org.mortbay.xml.XmlParser.NotValidating"); // deprecated! boolean validating = !notValidating && Boolean.valueOf(validating_prop).booleanValue(); setValidating(validating); } /* ------------------------------------------------------------ */ /** * Constructor. */ public XmlParser(boolean validating) { setValidating(validating); } /* ------------------------------------------------------------ */ public void setValidating(boolean validating) { try { SAXParserFactory factory = SAXParserFactory.newInstance(); factory.setValidating(validating); _parser = factory.newSAXParser(); try { if (validating) _parser.getXMLReader().setFeature("http://apache.org/xml/features/validation/schema", validating); } catch (Exception e) { if (validating) Log.warn("Schema validation may not be supported: ", e); else Log.ignore(e); } _parser.getXMLReader().setFeature("http://xml.org/sax/features/validation", validating); _parser.getXMLReader().setFeature("http://xml.org/sax/features/namespaces", true); _parser.getXMLReader().setFeature("http://xml.org/sax/features/namespace-prefixes", false); } catch (Exception e) { Log.warn(Log.EXCEPTION, e); throw new Error(e.toString()); } } /* ------------------------------------------------------------ */ /** * @param name * @param entity */ public synchronized void redirectEntity(String name, URL entity) { if (entity != null) _redirectMap.put(name, entity); } /* ------------------------------------------------------------ */ /** * * @return Returns the xpath. */ public String getXpath() { return _xpath; } /* ------------------------------------------------------------ */ /** * Set an XPath A very simple subset of xpath is supported to select a partial tree. Currently * only path like "/node1/nodeA | /node1/nodeB" are supported. * * @param xpath The xpath to set. */ public void setXpath(String xpath) { _xpath = xpath; StringTokenizer tok = new StringTokenizer(xpath, "| "); while (tok.hasMoreTokens()) _xpaths = LazyList.add(_xpaths, tok.nextToken()); } /* ------------------------------------------------------------ */ public String getDTD() { return _dtd; } /* ------------------------------------------------------------ */ /** * Add a ContentHandler. Add an additional _content handler that is triggered on a tag name. SAX * events are passed to the ContentHandler provided from a matching start element to the * corresponding end element. Only a single _content handler can be registered against each tag. * * @param trigger Tag local or q name. * @param observer SAX ContentHandler */ public synchronized void addContentHandler(String trigger, ContentHandler observer) { if (_observerMap == null) _observerMap = new HashMap(); _observerMap.put(trigger, observer); } /* ------------------------------------------------------------ */ public synchronized Node parse(InputSource source) throws IOException, SAXException { _dtd=null; Handler handler = new Handler(); XMLReader reader = _parser.getXMLReader(); reader.setContentHandler(handler); reader.setErrorHandler(handler); reader.setEntityResolver(handler); if (Log.isDebugEnabled()) Log.debug("parsing: sid=" + source.getSystemId() + ",pid=" + source.getPublicId()); _parser.parse(source, handler); if (handler._error != null) throw handler._error; Node doc = (Node) handler._top.get(0); handler.clear(); return doc; } /* ------------------------------------------------------------ */ /** * Parse String URL. */ public synchronized Node parse(String url) throws IOException, SAXException { if (Log.isDebugEnabled()) Log.debug("parse: " + url); return parse(new InputSource(url)); } /* ------------------------------------------------------------ */ /** * Parse File. */ public synchronized Node parse(File file) throws IOException, SAXException { if (Log.isDebugEnabled()) Log.debug("parse: " + file); return parse(new InputSource(file.toURL().toString())); } /* ------------------------------------------------------------ */ /** * Parse InputStream. */ public synchronized Node parse(InputStream in) throws IOException, SAXException { _dtd=null; Handler handler = new Handler(); XMLReader reader = _parser.getXMLReader(); reader.setContentHandler(handler); reader.setErrorHandler(handler); reader.setEntityResolver(handler); _parser.parse(new InputSource(in), handler); if (handler._error != null) throw handler._error; Node doc = (Node) handler._top.get(0); handler.clear(); return doc; } /* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */ private class NoopHandler extends DefaultHandler { Handler _next; int _depth; NoopHandler(Handler next) { this._next = next; } /* ------------------------------------------------------------ */ public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException { _depth++; } /* ------------------------------------------------------------ */ public void endElement(String uri, String localName, String qName) throws SAXException { if (_depth == 0) _parser.getXMLReader().setContentHandler(_next); else _depth--; } } /* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */ private class Handler extends DefaultHandler { Node _top = new Node(null, null, null); SAXParseException _error; private Node _context = _top; private NoopHandler _noop; Handler() { _noop = new NoopHandler(this); } /* ------------------------------------------------------------ */ void clear() { _top = null; _error = null; _context = null; } /* ------------------------------------------------------------ */ public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException { String name = (uri == null || uri.equals("")) ? qName : localName; Node node = new Node(_context, name, attrs); // check if the node matches any xpaths set? if (_xpaths != null) { String path = node.getPath(); boolean match = false; for (int i = LazyList.size(_xpaths); !match && i-- > 0;) { String xpath = (String) LazyList.get(_xpaths, i); match = path.equals(xpath) || xpath.startsWith(path) && xpath.length() > path.length() && xpath.charAt(path.length()) == '/'; } if (match) { _context.add(node); _context = node; } else { _parser.getXMLReader().setContentHandler(_noop); } } else { _context.add(node); _context = node; } ContentHandler observer = null; if (_observerMap != null) observer = (ContentHandler) _observerMap.get(name); _observers.push(observer); for (int i = 0; i < _observers.size(); i++) if (_observers.get(i) != null) ((ContentHandler) _observers.get(i)).startElement(uri, localName, qName, attrs); } /* ------------------------------------------------------------ */ public void endElement(String uri, String localName, String qName) throws SAXException { _context = _context._parent; for (int i = 0; i < _observers.size(); i++) if (_observers.get(i) != null) ((ContentHandler) _observers.get(i)).endElement(uri, localName, qName); _observers.pop(); } /* ------------------------------------------------------------ */ public void ignorableWhitespace(char buf[], int offset, int len) throws SAXException { for (int i = 0; i < _observers.size(); i++) if (_observers.get(i) != null) ((ContentHandler) _observers.get(i)).ignorableWhitespace(buf, offset, len); } /* ------------------------------------------------------------ */ public void characters(char buf[], int offset, int len) throws SAXException { _context.add(new String(buf, offset, len)); for (int i = 0; i < _observers.size(); i++) if (_observers.get(i) != null) ((ContentHandler) _observers.get(i)).characters(buf, offset, len); } /* ------------------------------------------------------------ */ public void warning(SAXParseException ex) { Log.debug(Log.EXCEPTION, ex); Log.warn("WARNING@" + getLocationString(ex) + " : " + ex.toString()); } /* ------------------------------------------------------------ */ public void error(SAXParseException ex) throws SAXException { // Save error and continue to report other errors if (_error == null) _error = ex; Log.debug(Log.EXCEPTION, ex); Log.warn("ERROR@" + getLocationString(ex) + " : " + ex.toString()); } /* ------------------------------------------------------------ */ public void fatalError(SAXParseException ex) throws SAXException { _error = ex; Log.debug(Log.EXCEPTION, ex); Log.warn("FATAL@" + getLocationString(ex) + " : " + ex.toString()); throw ex; } /* ------------------------------------------------------------ */ private String getLocationString(SAXParseException ex) { return ex.getSystemId() + " line:" + ex.getLineNumber() + " col:" + ex.getColumnNumber(); } /* ------------------------------------------------------------ */ public InputSource resolveEntity(String pid, String sid) { if (Log.isDebugEnabled()) Log.debug("resolveEntity(" + pid + ", " + sid + ")"); if (sid!=null && sid.endsWith(".dtd")) _dtd=sid; URL entity = null;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -