nsfilter.java

来自「kaffe Java 解释器语言,源码,Java的子集系统,开放源代码」· Java 代码 · 共 330 行

JAVA
330
字号
/* * 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.Enumeration;import java.util.Stack;import org.xml.sax.*;import org.xml.sax.ext.*;import org.xml.sax.helpers.AttributesImpl;import org.xml.sax.helpers.NamespaceSupport;/** * This filter ensures that element and attribute names are properly prefixed, * and that such prefixes are declared.  Such data is critical for operations * like writing XML text, and validating against DTDs:  names or their prefixes * may have been discarded, although they are essential to the exchange of * information using XML.  There are various common ways that such data * gets discarded: <ul> * *	<li> By default, SAX2 parsers must discard the "xmlns*" *	attributes, and may also choose not to report properly prefixed *	names for elements or attributes.  (Some parsers may support *	changing the <em>namespace-prefixes</em> value from the default *	to <em>true</em>, effectively eliminating the need to use this *	filter on their output.) * *	<li> When event streams are generated from a DOM tree, they may *	have never have had prefixes or declarations for namespaces; or *	the existing prefixes or declarations may have been invalidated *	by structural modifications to that DOM tree. * *	<li> Other software writing SAX event streams won't necessarily *	be worrying about prefix management, and so they will need to *	have a transparent solution for managing them. * *	</ul> * * <p> This filter uses a heuristic to choose the prefix to assign to any * particular name which wasn't already corectly prefixed.  The associated * namespace will be correct, and the prefix will be declared.  Original * structures facilitating text editing, such as conventions about use of * mnemonic prefix names or the scoping of prefixes, can't always be * reconstructed after they are discarded, as strongly encouraged by the * current SAX2 defaults. * * <p> Note that this can't possibly know whether values inside attribute * value or document content involve prefixed names.  If your application * requires using prefixed names in such locations you'll need to add some * appropriate logic (perhaps adding additional heuristics in a subclass). * * @author David Brownell */public class NSFilter extends EventFilter{    private NamespaceSupport	nsStack = new NamespaceSupport ();    private Stack		elementStack = new Stack ();    private boolean		pushedContext;    private String		nsTemp [] = new String [3];    private AttributesImpl	attributes = new AttributesImpl ();    private boolean		usedDefault;    // gensymmed prefixes use this root name    private static final String	prefixRoot = "prefix-";        /**     * Passes events through to the specified consumer, after first     * processing them.     *     * @param next the next event consumer to receive events.     */	// constructor used by PipelineFactory    public NSFilter (EventConsumer next)    {	super (next);	setContentHandler (this);    }    private void fatalError (String message)    throws SAXException    {	SAXParseException	e;	ErrorHandler		handler = getErrorHandler ();	Locator			locator = getDocumentLocator ();	if (locator == null)	    e = new SAXParseException (message, null, null, -1, -1);	else	    e = new SAXParseException (message, locator);	if (handler != null)	    handler.fatalError (e);	throw e;    }    public void startDocument () throws SAXException    {	elementStack.removeAllElements ();	nsStack.reset ();	pushedContext = false;	super.startDocument ();    }    /**     * This call is not passed to the next consumer in the chain.     * Prefix declarations and scopes are only exposed in the form     * of attributes; this callback just records a declaration that     * will be exposed as an attribute.     */    public void startPrefixMapping (String prefix, String uri)    throws SAXException    {	if (pushedContext == false) {	    nsStack.pushContext ();	    pushedContext = true;	}	// this check is awkward, but the paranoia prevents big trouble	for (Enumeration e = nsStack.getDeclaredPrefixes ();		e.hasMoreElements ();		/* NOP */ ) {	    String	declared = (String) e.nextElement ();	    if (!declared.equals (prefix))		continue;	    if (uri.equals (nsStack.getURI (prefix)))		return;	    fatalError ("inconsistent binding for prefix '" + prefix		+ "' ... " + uri + " (was " + nsStack.getURI (prefix) + ")");	}	if (!nsStack.declarePrefix (prefix, uri))	    fatalError ("illegal prefix declared: " + prefix);    }    private String fixName (String ns, String l, String name, boolean isAttr)    throws SAXException    {	if ("".equals (name) || name == null) {	    name = l;	    if ("".equals (name) || name == null)		fatalError ("empty/null name");	}	// can we correctly process the name as-is?	// handles "element scope" attribute names here.	if (nsStack.processName (name, nsTemp, isAttr) != null		&& nsTemp [0].equals (ns)		) {	    return nsTemp [2];	}	// nope, gotta modify the name or declare a default mapping	int	temp;	// get rid of any current prefix	if ((temp = name.indexOf (':')) >= 0) {	    name = name.substring (temp + 1);	    // ... maybe that's enough (use/prefer default namespace) ...	    if (!isAttr && nsStack.processName (name, nsTemp, false) != null		    && nsTemp [0].equals (ns)		    ) {		return nsTemp [2];	    }	}	// must we define and use the default/undefined prefix?	if ("".equals (ns)) {	    if (isAttr)		fatalError ("processName bug");	    if (attributes.getIndex ("xmlns") != -1)		fatalError ("need to undefine default NS, but it's bound: "			+ attributes.getValue ("xmlns"));	    	    nsStack.declarePrefix ("", "");	    attributes.addAttribute ("", "", "xmlns", "CDATA", "");	    return name;	}	// is there at least one non-null prefix we can use?	for (Enumeration e = nsStack.getDeclaredPrefixes ();		e.hasMoreElements ();		/* NOP */) {	    String prefix = (String) e.nextElement ();	    String uri = nsStack.getURI (prefix);	    if (uri == null || !uri.equals (ns))		continue;	    return prefix + ":" + name;	}	// no such luck.  create a prefix name, declare it, use it.	for (temp = 0; temp >= 0; temp++) {	    String	prefix = prefixRoot + temp;	    if (nsStack.getURI (prefix) == null) {		nsStack.declarePrefix (prefix, ns);		attributes.addAttribute ("", "", "xmlns:" + prefix,			"CDATA", ns);		return prefix + ":" + name;	    }	}	fatalError ("too many prefixes genned");	// NOTREACHED	return null;    }    public void startElement (	String uri, String localName,	String qName, Attributes atts    ) throws SAXException    {	if (!pushedContext)	    nsStack.pushContext ();	pushedContext = false;	// make sure we have all NS declarations handy before we start	int	length = atts.getLength ();	for (int i = 0; i < length; i++) {	    String	aName = atts.getQName (i);	    if (!aName.startsWith ("xmlns"))		continue;	    String	prefix;	    if ("xmlns".equals (aName))		prefix = "";	    else if (aName.indexOf (':') == 5)		prefix = aName.substring (6);	    else	// "xmlnsfoo" etc.		continue;	    startPrefixMapping (prefix, atts.getValue (i));	}	// put namespace decls at the start of our regenned attlist	attributes.clear ();	for (Enumeration e = nsStack.getDeclaredPrefixes ();		e.hasMoreElements ();		/* NOP */) {	    String prefix = (String) e.nextElement ();	    attributes.addAttribute ("", "",		    ("".equals (prefix)			? "xmlns"			: "xmlns:" + prefix),		    "CDATA",		    nsStack.getURI (prefix));	}	// name fixups:  element, then attributes.	// fixName may declare a new prefix or, for the element,	// redeclare the default (if element name needs it).	qName = fixName (uri, localName, qName, false);	for (int i = 0; i < length; i++) {	    String	aName = atts.getQName (i);	    String	aNS = atts.getURI (i);	    String	aLocal = atts.getLocalName (i);	    String	aType = atts.getType (i);	    String	aValue = atts.getValue (i);	    if (aName.startsWith ("xmlns"))		continue;	    aName = fixName (aNS, aLocal, aName, true);	    attributes.addAttribute (aNS, aLocal, aName, aType, aValue);	}	elementStack.push (qName);	// pass event along, with cleaned-up names and decls.	super.startElement (uri, localName, qName, attributes);    }    public void endElement (String uri, String localName, String qName)    throws SAXException    {	nsStack.popContext ();	qName = (String) elementStack.pop ();	super.endElement (uri, localName, qName);    }    /**     * This call is not passed to the next consumer in the chain.     * Prefix declarations and scopes are only exposed in their     * attribute form.     */    public void endPrefixMapping (String prefix)    throws SAXException	{ }    public void endDocument () throws SAXException    {	elementStack.removeAllElements ();	nsStack.reset ();	super.endDocument ();    }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?