wellformednessfilter.java
来自「kaffe Java 解释器语言,源码,Java的子集系统,开放源代码」· Java 代码 · 共 351 行
JAVA
351 行
/* * Copyright (C) 1999-2001 David Brownell * * This file is part of GNU JAXP, a library. * * GNU JAXP 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. * * GNU JAXP 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * As a special exception, if you link this library with other files to * produce an executable, this library does not by itself cause the * resulting executable to be covered by the GNU General Public License. * This exception does not however invalidate any other reasons why the * executable file might be covered by the GNU General Public License. */package gnu.xml.pipeline;import java.util.EmptyStackException;import java.util.Stack;import org.xml.sax.*;import org.xml.sax.ext.*;/** * This filter reports fatal exceptions in the case of event streams that * are not well formed. The rules currently tested include: <ul> * * <li>setDocumentLocator ... may be called only before startDocument * * <li>startDocument/endDocument ... must be paired, and all other * calls (except setDocumentLocator) must be nested within these. * * <li>startElement/endElement ... must be correctly paired, and * may never appear within CDATA sections. * * <li>comment ... can't contain "--" * * <li>character data ... can't contain "]]>" * * <li>whitespace ... can't contain CR * * <li>whitespace and character data must be within an element * * <li>processing instruction ... can't contain "?>" or CR * * <li>startCDATA/endCDATA ... must be correctly paired. * * </ul> * * <p> Other checks for event stream correctness may be provided in * the future. For example, insisting that * entity boundaries nest correctly, * namespace scopes nest correctly, * namespace values never contain relative URIs, * attributes don't have "<" characters; * and more. * * @author David Brownell */public final class WellFormednessFilter extends EventFilter{ private boolean startedDoc; private Stack elementStack = new Stack (); private boolean startedCDATA; private String dtdState = "before"; /** * Swallows all events after performing well formedness checks. */ // constructor used by PipelineFactory public WellFormednessFilter () { this (null); } /** * Passes events through to the specified consumer, after first * processing them. */ // constructor used by PipelineFactory public WellFormednessFilter (EventConsumer consumer) { super (consumer); setContentHandler (this); setDTDHandler (this); try { setProperty (LEXICAL_HANDLER, this); } catch (SAXException e) { /* can't happen */ } } /** * Resets state as if any preceding event stream was well formed. * Particularly useful if it ended through some sort of error, * and the endDocument call wasn't made. */ public void reset () { startedDoc = false; startedCDATA = false; elementStack.removeAllElements (); } private SAXParseException getException (String message) { SAXParseException e; Locator locator = getDocumentLocator (); if (locator == null) return new SAXParseException (message, null, null, -1, -1); else return new SAXParseException (message, locator); } private void fatalError (String message) throws SAXException { SAXParseException e = getException (message); ErrorHandler handler = getErrorHandler (); if (handler != null) handler.fatalError (e); throw e; } /** * Throws an exception when called after startDocument. * * @param locator the locator, to be used in error reporting or relative * URI resolution. * * @exception IllegalStateException when called after the document * has already been started */ public void setDocumentLocator (Locator locator) { if (startedDoc) throw new IllegalStateException ( "setDocumentLocator called after startDocument"); super.setDocumentLocator (locator); } public void startDocument () throws SAXException { if (startedDoc) fatalError ("startDocument called more than once"); startedDoc = true; startedCDATA = false; elementStack.removeAllElements (); super.startDocument (); } public void startElement ( String uri, String localName, String qName, Attributes atts ) throws SAXException { if (!startedDoc) fatalError ("callback outside of document?"); if ("inside".equals (dtdState)) fatalError ("element inside DTD?"); else dtdState = "after"; if (startedCDATA) fatalError ("element inside CDATA section"); if (qName == null || "".equals (qName)) fatalError ("startElement name missing"); elementStack.push (qName); super.startElement (uri, localName, qName, atts); } public void endElement (String uri, String localName, String qName) throws SAXException { if (!startedDoc) fatalError ("callback outside of document?"); if (startedCDATA) fatalError ("element inside CDATA section"); if (qName == null || "".equals (qName)) fatalError ("endElement name missing"); try { String top = (String) elementStack.pop (); if (!qName.equals (top)) fatalError ("<" + top + " ...>...</" + qName + ">"); // XXX could record/test namespace info } catch (EmptyStackException e) { fatalError ("endElement without startElement: </" + qName + ">"); } super.endElement (uri, localName, qName); } public void endDocument () throws SAXException { if (!startedDoc) fatalError ("callback outside of document?"); dtdState = "before"; startedDoc = false; super.endDocument (); } public void startDTD (String root, String publicId, String systemId) throws SAXException { if (!startedDoc) fatalError ("callback outside of document?"); if ("before" != dtdState) fatalError ("two DTDs?"); if (!elementStack.empty ()) fatalError ("DTD must precede root element"); dtdState = "inside"; super.startDTD (root, publicId, systemId); } public void notationDecl (String name, String publicId, String systemId) throws SAXException {// FIXME: not all parsers will report startDTD() ...// we'd rather insist we're "inside". if ("after" == dtdState) fatalError ("not inside DTD"); super.notationDecl (name, publicId, systemId); } public void unparsedEntityDecl (String name, String publicId, String systemId, String notationName) throws SAXException {// FIXME: not all parsers will report startDTD() ...// we'd rather insist we're "inside". if ("after" == dtdState) fatalError ("not inside DTD"); super.unparsedEntityDecl (name, publicId, systemId, notationName); } // FIXME: add the four DeclHandler calls too public void endDTD () throws SAXException { if (!startedDoc) fatalError ("callback outside of document?"); if ("inside" != dtdState) fatalError ("DTD ends without start?"); dtdState = "after"; super.endDTD (); } public void characters (char ch [], int start, int length) throws SAXException { int here = start, end = start + length; if (elementStack.empty ()) fatalError ("characters must be in an element"); while (here < end) { if (ch [here++] != ']') continue; if (here == end) // potential problem ... continue; if (ch [here++] != ']') continue; if (here == end) // potential problem ... continue; if (ch [here++] == '>') fatalError ("character data can't contain \"]]>\""); } super.characters (ch, start, length); } public void ignorableWhitespace (char ch [], int start, int length) throws SAXException { int here = start, end = start + length; if (elementStack.empty ()) fatalError ("characters must be in an element"); while (here < end) { if (ch [here++] == '\r') fatalError ("whitespace can't contain CR"); } super.ignorableWhitespace (ch, start, length); } public void processingInstruction (String target, String data) throws SAXException { if (data.indexOf ('\r') > 0) fatalError ("PIs can't contain CR"); if (data.indexOf ("?>") > 0) fatalError ("PIs can't contain \"?>\""); } public void comment (char ch [], int start, int length) throws SAXException { if (!startedDoc) fatalError ("callback outside of document?"); if (startedCDATA) fatalError ("comments can't nest in CDATA"); int here = start, end = start + length; while (here < end) { if (ch [here] == '\r') fatalError ("comments can't contain CR"); if (ch [here++] != '-') continue; if (here == end) fatalError ("comments can't end with \"--->\""); if (ch [here++] == '-') fatalError ("comments can't contain \"--\""); } super.comment (ch, start, length); } public void startCDATA () throws SAXException { if (!startedDoc) fatalError ("callback outside of document?"); if (startedCDATA) fatalError ("CDATA starts can't nest"); startedCDATA = true; super.startCDATA (); } public void endCDATA () throws SAXException { if (!startedDoc) fatalError ("callback outside of document?"); if (!startedCDATA) fatalError ("CDATA end without start?"); startedCDATA = false; super.endCDATA (); }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?