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 + -
显示快捷键?