001: /*
002: * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025: // NamespaceSupport.java - generic Namespace support for SAX.
026: // http://www.saxproject.org
027: // Written by David Megginson
028: // This class is in the Public Domain. NO WARRANTY!
029: // $Id: NamespaceSupport.java,v 1.1 2005/04/14 21:45:18 kohsuke Exp $
030: package com.sun.xml.internal.txw2;
031:
032: import java.util.EmptyStackException;
033: import java.util.Enumeration;
034: import java.util.Hashtable;
035: import java.util.Vector;
036:
037: /**
038: * Encapsulate Namespace logic for use by applications using SAX,
039: * or internally by SAX drivers.
040: *
041: * <blockquote>
042: * <em>This module, both source code and documentation, is in the
043: * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
044: * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
045: * for further information.
046: * </blockquote>
047: *
048: * <p>This class encapsulates the logic of Namespace processing: it
049: * tracks the declarations currently in force for each context and
050: * automatically processes qualified XML names into their Namespace
051: * parts; it can also be used in reverse for generating XML qnames
052: * from Namespaces.</p>
053: *
054: * <p>Namespace support objects are reusable, but the reset method
055: * must be invoked between each session.</p>
056: *
057: * <p>Here is a simple session:</p>
058: *
059: * <pre>
060: * String parts[] = new String[3];
061: * NamespaceSupport support = new NamespaceSupport();
062: *
063: * support.pushContext();
064: * support.declarePrefix("", "http://www.w3.org/1999/xhtml");
065: * support.declarePrefix("dc", "http://www.purl.org/dc#");
066: *
067: * parts = support.processName("p", parts, false);
068: * System.out.println("Namespace URI: " + parts[0]);
069: * System.out.println("Local name: " + parts[1]);
070: * System.out.println("Raw name: " + parts[2]);
071: *
072: * parts = support.processName("dc:title", parts, false);
073: * System.out.println("Namespace URI: " + parts[0]);
074: * System.out.println("Local name: " + parts[1]);
075: * System.out.println("Raw name: " + parts[2]);
076: *
077: * support.popContext();
078: * </pre>
079: *
080: * <p>Note that this class is optimized for the use case where most
081: * elements do not contain Namespace declarations: if the same
082: * prefix/URI mapping is repeated for each context (for example), this
083: * class will be somewhat less efficient.</p>
084: *
085: * <p>Although SAX drivers (parsers) may choose to use this class to
086: * implement namespace handling, they are not required to do so.
087: * Applications must track namespace information themselves if they
088: * want to use namespace information.
089: *
090: * @since SAX 2.0
091: * @author David Megginson
092: * @version 2.0.1 (sax2r2)
093: */
094: final class NamespaceSupport {
095:
096: ////////////////////////////////////////////////////////////////////
097: // Constants.
098: ////////////////////////////////////////////////////////////////////
099:
100: /**
101: * The XML Namespace URI as a constant.
102: * The value is <code>http://www.w3.org/XML/1998/namespace</code>
103: * as defined in the "Namespaces in XML" * recommendation.
104: *
105: * <p>This is the Namespace URI that is automatically mapped
106: * to the "xml" prefix.</p>
107: */
108: public final static String XMLNS = "http://www.w3.org/XML/1998/namespace";
109:
110: /**
111: * The namespace declaration URI as a constant.
112: * The value is <code>http://www.w3.org/xmlns/2000/</code>, as defined
113: * in a backwards-incompatible erratum to the "Namespaces in XML"
114: * recommendation. Because that erratum postdated SAX2, SAX2 defaults
115: * to the original recommendation, and does not normally use this URI.
116: *
117: *
118: * <p>This is the Namespace URI that is optionally applied to
119: * <em>xmlns</em> and <em>xmlns:*</em> attributes, which are used to
120: * declare namespaces. </p>
121: *
122: * @since SAX 2.1alpha
123: * @see #setNamespaceDeclUris
124: * @see #isNamespaceDeclUris
125: */
126: public final static String NSDECL = "http://www.w3.org/xmlns/2000/";
127:
128: /**
129: * An empty enumeration.
130: */
131: private final static Enumeration EMPTY_ENUMERATION = new Vector()
132: .elements();
133:
134: ////////////////////////////////////////////////////////////////////
135: // Constructor.
136: ////////////////////////////////////////////////////////////////////
137:
138: /**
139: * Create a new Namespace support object.
140: */
141: public NamespaceSupport() {
142: reset();
143: }
144:
145: ////////////////////////////////////////////////////////////////////
146: // Context management.
147: ////////////////////////////////////////////////////////////////////
148:
149: /**
150: * Reset this Namespace support object for reuse.
151: *
152: * <p>It is necessary to invoke this method before reusing the
153: * Namespace support object for a new session. If namespace
154: * declaration URIs are to be supported, that flag must also
155: * be set to a non-default value.
156: * </p>
157: *
158: * @see #setNamespaceDeclUris
159: */
160: public void reset() {
161: contexts = new Context[32];
162: namespaceDeclUris = false;
163: contextPos = 0;
164: contexts[contextPos] = currentContext = new Context();
165: currentContext.declarePrefix("xml", XMLNS);
166: }
167:
168: /**
169: * Start a new Namespace context.
170: * The new context will automatically inherit
171: * the declarations of its parent context, but it will also keep
172: * track of which declarations were made within this context.
173: *
174: * <p>Event callback code should start a new context once per element.
175: * This means being ready to call this in either of two places.
176: * For elements that don't include namespace declarations, the
177: * <em>ContentHandler.startElement()</em> callback is the right place.
178: * For elements with such a declaration, it'd done in the first
179: * <em>ContentHandler.startPrefixMapping()</em> callback.
180: * A boolean flag can be used to
181: * track whether a context has been started yet. When either of
182: * those methods is called, it checks the flag to see if a new context
183: * needs to be started. If so, it starts the context and sets the
184: * flag. After <em>ContentHandler.startElement()</em>
185: * does that, it always clears the flag.
186: *
187: * <p>Normally, SAX drivers would push a new context at the beginning
188: * of each XML element. Then they perform a first pass over the
189: * attributes to process all namespace declarations, making
190: * <em>ContentHandler.startPrefixMapping()</em> callbacks.
191: * Then a second pass is made, to determine the namespace-qualified
192: * names for all attributes and for the element name.
193: * Finally all the information for the
194: * <em>ContentHandler.startElement()</em> callback is available,
195: * so it can then be made.
196: *
197: * <p>The Namespace support object always starts with a base context
198: * already in force: in this context, only the "xml" prefix is
199: * declared.</p>
200: *
201: * @see org.xml.sax.ContentHandler
202: * @see #popContext
203: */
204: public void pushContext() {
205: int max = contexts.length;
206:
207: contextPos++;
208:
209: // Extend the array if necessary
210: if (contextPos >= max) {
211: Context newContexts[] = new Context[max * 2];
212: System.arraycopy(contexts, 0, newContexts, 0, max);
213: max *= 2;
214: contexts = newContexts;
215: }
216:
217: // Allocate the context if necessary.
218: currentContext = contexts[contextPos];
219: if (currentContext == null) {
220: contexts[contextPos] = currentContext = new Context();
221: }
222:
223: // Set the parent, if any.
224: if (contextPos > 0) {
225: currentContext.setParent(contexts[contextPos - 1]);
226: }
227: }
228:
229: /**
230: * Revert to the previous Namespace context.
231: *
232: * <p>Normally, you should pop the context at the end of each
233: * XML element. After popping the context, all Namespace prefix
234: * mappings that were previously in force are restored.</p>
235: *
236: * <p>You must not attempt to declare additional Namespace
237: * prefixes after popping a context, unless you push another
238: * context first.</p>
239: *
240: * @see #pushContext
241: */
242: public void popContext() {
243: contexts[contextPos].clear();
244: contextPos--;
245: if (contextPos < 0) {
246: throw new EmptyStackException();
247: }
248: currentContext = contexts[contextPos];
249: }
250:
251: ////////////////////////////////////////////////////////////////////
252: // Operations within a context.
253: ////////////////////////////////////////////////////////////////////
254:
255: /**
256: * Declare a Namespace prefix. All prefixes must be declared
257: * before they are referenced. For example, a SAX driver (parser)
258: * would scan an element's attributes
259: * in two passes: first for namespace declarations,
260: * then a second pass using {@link #processName processName()} to
261: * interpret prefixes against (potentially redefined) prefixes.
262: *
263: * <p>This method declares a prefix in the current Namespace
264: * context; the prefix will remain in force until this context
265: * is popped, unless it is shadowed in a descendant context.</p>
266: *
267: * <p>To declare the default element Namespace, use the empty string as
268: * the prefix.</p>
269: *
270: * <p>Note that there is an asymmetry in this library: {@link
271: * #getPrefix getPrefix} will not return the "" prefix,
272: * even if you have declared a default element namespace.
273: * To check for a default namespace,
274: * you have to look it up explicitly using {@link #getURI getURI}.
275: * This asymmetry exists to make it easier to look up prefixes
276: * for attribute names, where the default prefix is not allowed.</p>
277: *
278: * @param prefix The prefix to declare, or the empty string to
279: * indicate the default element namespace. This may never have
280: * the value "xml" or "xmlns".
281: * @param uri The Namespace URI to associate with the prefix.
282: * @return true if the prefix was legal, false otherwise
283: *
284: * @see #processName
285: * @see #getURI
286: * @see #getPrefix
287: */
288: public boolean declarePrefix(String prefix, String uri) {
289: if (prefix.equals("xml") || prefix.equals("xmlns")) {
290: return false;
291: } else {
292: currentContext.declarePrefix(prefix, uri);
293: return true;
294: }
295: }
296:
297: /**
298: * Process a raw XML qualified name, after all declarations in the
299: * current context have been handled by {@link #declarePrefix
300: * declarePrefix()}.
301: *
302: * <p>This method processes a raw XML qualified name in the
303: * current context by removing the prefix and looking it up among
304: * the prefixes currently declared. The return value will be the
305: * array supplied by the caller, filled in as follows:</p>
306: *
307: * <dl>
308: * <dt>parts[0]</dt>
309: * <dd>The Namespace URI, or an empty string if none is
310: * in use.</dd>
311: * <dt>parts[1]</dt>
312: * <dd>The local name (without prefix).</dd>
313: * <dt>parts[2]</dt>
314: * <dd>The original raw name.</dd>
315: * </dl>
316: *
317: * <p>All of the strings in the array will be internalized. If
318: * the raw name has a prefix that has not been declared, then
319: * the return value will be null.</p>
320: *
321: * <p>Note that attribute names are processed differently than
322: * element names: an unprefixed element name will receive the
323: * default Namespace (if any), while an unprefixed attribute name
324: * will not.</p>
325: *
326: * @param qName The XML qualified name to be processed.
327: * @param parts An array supplied by the caller, capable of
328: * holding at least three members.
329: * @param isAttribute A flag indicating whether this is an
330: * attribute name (true) or an element name (false).
331: * @return The supplied array holding three internalized strings
332: * representing the Namespace URI (or empty string), the
333: * local name, and the XML qualified name; or null if there
334: * is an undeclared prefix.
335: * @see #declarePrefix
336: * @see java.lang.String#intern */
337: public String[] processName(String qName, String parts[],
338: boolean isAttribute) {
339: String myParts[] = currentContext.processName(qName,
340: isAttribute);
341: if (myParts == null) {
342: return null;
343: } else {
344: parts[0] = myParts[0];
345: parts[1] = myParts[1];
346: parts[2] = myParts[2];
347: return parts;
348: }
349: }
350:
351: /**
352: * Look up a prefix and get the currently-mapped Namespace URI.
353: *
354: * <p>This method looks up the prefix in the current context.
355: * Use the empty string ("") for the default Namespace.</p>
356: *
357: * @param prefix The prefix to look up.
358: * @return The associated Namespace URI, or null if the prefix
359: * is undeclared in this context.
360: * @see #getPrefix
361: * @see #getPrefixes
362: */
363: public String getURI(String prefix) {
364: return currentContext.getURI(prefix);
365: }
366:
367: /**
368: * Return an enumeration of all prefixes whose declarations are
369: * active in the current context.
370: * This includes declarations from parent contexts that have
371: * not been overridden.
372: *
373: * <p><strong>Note:</strong> if there is a default prefix, it will not be
374: * returned in this enumeration; check for the default prefix
375: * using the {@link #getURI getURI} with an argument of "".</p>
376: *
377: * @return An enumeration of prefixes (never empty).
378: * @see #getDeclaredPrefixes
379: * @see #getURI
380: */
381: public Enumeration getPrefixes() {
382: return currentContext.getPrefixes();
383: }
384:
385: /**
386: * Return one of the prefixes mapped to a Namespace URI.
387: *
388: * <p>If more than one prefix is currently mapped to the same
389: * URI, this method will make an arbitrary selection; if you
390: * want all of the prefixes, use the {@link #getPrefixes}
391: * method instead.</p>
392: *
393: * <p><strong>Note:</strong> this will never return the empty (default) prefix;
394: * to check for a default prefix, use the {@link #getURI getURI}
395: * method with an argument of "".</p>
396: *
397: * @param uri the namespace URI
398: * @return one of the prefixes currently mapped to the URI supplied,
399: * or null if none is mapped or if the URI is assigned to
400: * the default namespace
401: * @see #getPrefixes(java.lang.String)
402: * @see #getURI
403: */
404: public String getPrefix(String uri) {
405: return currentContext.getPrefix(uri);
406: }
407:
408: /**
409: * Return an enumeration of all prefixes for a given URI whose
410: * declarations are active in the current context.
411: * This includes declarations from parent contexts that have
412: * not been overridden.
413: *
414: * <p>This method returns prefixes mapped to a specific Namespace
415: * URI. The xml: prefix will be included. If you want only one
416: * prefix that's mapped to the Namespace URI, and you don't care
417: * which one you get, use the {@link #getPrefix getPrefix}
418: * method instead.</p>
419: *
420: * <p><strong>Note:</strong> the empty (default) prefix is <em>never</em> included
421: * in this enumeration; to check for the presence of a default
422: * Namespace, use the {@link #getURI getURI} method with an
423: * argument of "".</p>
424: *
425: * @param uri The Namespace URI.
426: * @return An enumeration of prefixes (never empty).
427: * @see #getPrefix
428: * @see #getDeclaredPrefixes
429: * @see #getURI
430: */
431: public Enumeration getPrefixes(String uri) {
432: Vector prefixes = new Vector();
433: Enumeration allPrefixes = getPrefixes();
434: while (allPrefixes.hasMoreElements()) {
435: String prefix = (String) allPrefixes.nextElement();
436: if (uri.equals(getURI(prefix))) {
437: prefixes.addElement(prefix);
438: }
439: }
440: return prefixes.elements();
441: }
442:
443: /**
444: * Return an enumeration of all prefixes declared in this context.
445: *
446: * <p>The empty (default) prefix will be included in this
447: * enumeration; note that this behaviour differs from that of
448: * {@link #getPrefix} and {@link #getPrefixes}.</p>
449: *
450: * @return An enumeration of all prefixes declared in this
451: * context.
452: * @see #getPrefixes
453: * @see #getURI
454: */
455: public Enumeration getDeclaredPrefixes() {
456: return currentContext.getDeclaredPrefixes();
457: }
458:
459: /**
460: * Controls whether namespace declaration attributes are placed
461: * into the {@link #NSDECL NSDECL} namespace
462: * by {@link #processName processName()}. This may only be
463: * changed before any contexts have been pushed.
464: *
465: * @since SAX 2.1alpha
466: *
467: * @exception IllegalStateException when attempting to set this
468: * after any context has been pushed.
469: */
470: public void setNamespaceDeclUris(boolean value) {
471: if (contextPos != 0)
472: throw new IllegalStateException();
473: if (value == namespaceDeclUris)
474: return;
475: namespaceDeclUris = value;
476: if (value)
477: currentContext.declarePrefix("xmlns", NSDECL);
478: else {
479: contexts[contextPos] = currentContext = new Context();
480: currentContext.declarePrefix("xml", XMLNS);
481: }
482: }
483:
484: /**
485: * Returns true if namespace declaration attributes are placed into
486: * a namespace. This behavior is not the default.
487: *
488: * @since SAX 2.1alpha
489: */
490: public boolean isNamespaceDeclUris() {
491: return namespaceDeclUris;
492: }
493:
494: ////////////////////////////////////////////////////////////////////
495: // Internal state.
496: ////////////////////////////////////////////////////////////////////
497:
498: private Context contexts[];
499: private Context currentContext;
500: private int contextPos;
501: private boolean namespaceDeclUris;
502:
503: ////////////////////////////////////////////////////////////////////
504: // Internal classes.
505: ////////////////////////////////////////////////////////////////////
506:
507: /**
508: * Internal class for a single Namespace context.
509: *
510: * <p>This module caches and reuses Namespace contexts,
511: * so the number allocated
512: * will be equal to the element depth of the document, not to the total
513: * number of elements (i.e. 5-10 rather than tens of thousands).
514: * Also, data structures used to represent contexts are shared when
515: * possible (child contexts without declarations) to further reduce
516: * the amount of memory that's consumed.
517: * </p>
518: */
519: final class Context {
520:
521: /**
522: * Create the root-level Namespace context.
523: */
524: Context() {
525: copyTables();
526: }
527:
528: /**
529: * (Re)set the parent of this Namespace context.
530: * The context must either have been freshly constructed,
531: * or must have been cleared.
532: *
533: * @param context The parent Namespace context object.
534: */
535: void setParent(Context parent) {
536: this .parent = parent;
537: declarations = null;
538: prefixTable = parent.prefixTable;
539: uriTable = parent.uriTable;
540: elementNameTable = parent.elementNameTable;
541: attributeNameTable = parent.attributeNameTable;
542: defaultNS = parent.defaultNS;
543: declSeen = false;
544: }
545:
546: /**
547: * Makes associated state become collectible,
548: * invalidating this context.
549: * {@link #setParent} must be called before
550: * this context may be used again.
551: */
552: void clear() {
553: parent = null;
554: prefixTable = null;
555: uriTable = null;
556: elementNameTable = null;
557: attributeNameTable = null;
558: defaultNS = "";
559: }
560:
561: /**
562: * Declare a Namespace prefix for this context.
563: *
564: * @param prefix The prefix to declare.
565: * @param uri The associated Namespace URI.
566: * @see org.xml.sax.helpers.NamespaceSupport#declarePrefix
567: */
568: void declarePrefix(String prefix, String uri) {
569: // Lazy processing...
570: // if (!declsOK)
571: // throw new IllegalStateException (
572: // "can't declare any more prefixes in this context");
573: if (!declSeen) {
574: copyTables();
575: }
576: if (declarations == null) {
577: declarations = new Vector();
578: }
579:
580: prefix = prefix.intern();
581: uri = uri.intern();
582: if ("".equals(prefix)) {
583: defaultNS = uri;
584: } else {
585: prefixTable.put(prefix, uri);
586: uriTable.put(uri, prefix); // may wipe out another prefix
587: }
588: declarations.addElement(prefix);
589: }
590:
591: /**
592: * Process an XML qualified name in this context.
593: *
594: * @param qName The XML qualified name.
595: * @param isAttribute true if this is an attribute name.
596: * @return An array of three strings containing the
597: * URI part (or empty string), the local part,
598: * and the raw name, all internalized, or null
599: * if there is an undeclared prefix.
600: * @see org.xml.sax.helpers.NamespaceSupport#processName
601: */
602: String[] processName(String qName, boolean isAttribute) {
603: String name[];
604: Hashtable table;
605:
606: // Select the appropriate table.
607: if (isAttribute) {
608: table = attributeNameTable;
609: } else {
610: table = elementNameTable;
611: }
612:
613: // Start by looking in the cache, and
614: // return immediately if the name
615: // is already known in this content
616: name = (String[]) table.get(qName);
617: if (name != null) {
618: return name;
619: }
620:
621: // We haven't seen this name in this
622: // context before. Maybe in the parent
623: // context, but we can't assume prefix
624: // bindings are the same.
625: name = new String[3];
626: name[2] = qName.intern();
627: int index = qName.indexOf(':');
628:
629: // No prefix.
630: if (index == -1) {
631: if (isAttribute) {
632: if (qName == "xmlns" && namespaceDeclUris)
633: name[0] = NSDECL;
634: else
635: name[0] = "";
636: } else {
637: name[0] = defaultNS;
638: }
639: name[1] = name[2];
640: }
641:
642: // Prefix
643: else {
644: String prefix = qName.substring(0, index);
645: String local = qName.substring(index + 1);
646: String uri;
647: if ("".equals(prefix)) {
648: uri = defaultNS;
649: } else {
650: uri = (String) prefixTable.get(prefix);
651: }
652: if (uri == null
653: || (!isAttribute && "xmlns".equals(prefix))) {
654: return null;
655: }
656: name[0] = uri;
657: name[1] = local.intern();
658: }
659:
660: // Save in the cache for future use.
661: // (Could be shared with parent context...)
662: table.put(name[2], name);
663: return name;
664: }
665:
666: /**
667: * Look up the URI associated with a prefix in this context.
668: *
669: * @param prefix The prefix to look up.
670: * @return The associated Namespace URI, or null if none is
671: * declared.
672: * @see org.xml.sax.helpers.NamespaceSupport#getURI
673: */
674: String getURI(String prefix) {
675: if ("".equals(prefix)) {
676: return defaultNS;
677: } else if (prefixTable == null) {
678: return null;
679: } else {
680: return (String) prefixTable.get(prefix);
681: }
682: }
683:
684: /**
685: * Look up one of the prefixes associated with a URI in this context.
686: *
687: * <p>Since many prefixes may be mapped to the same URI,
688: * the return value may be unreliable.</p>
689: *
690: * @param uri The URI to look up.
691: * @return The associated prefix, or null if none is declared.
692: * @see org.xml.sax.helpers.NamespaceSupport#getPrefix
693: */
694: String getPrefix(String uri) {
695: if (uriTable == null) {
696: return null;
697: } else {
698: return (String) uriTable.get(uri);
699: }
700: }
701:
702: /**
703: * Return an enumeration of prefixes declared in this context.
704: *
705: * @return An enumeration of prefixes (possibly empty).
706: * @see org.xml.sax.helpers.NamespaceSupport#getDeclaredPrefixes
707: */
708: Enumeration getDeclaredPrefixes() {
709: if (declarations == null) {
710: return EMPTY_ENUMERATION;
711: } else {
712: return declarations.elements();
713: }
714: }
715:
716: /**
717: * Return an enumeration of all prefixes currently in force.
718: *
719: * <p>The default prefix, if in force, is <em>not</em>
720: * returned, and will have to be checked for separately.</p>
721: *
722: * @return An enumeration of prefixes (never empty).
723: * @see org.xml.sax.helpers.NamespaceSupport#getPrefixes
724: */
725: Enumeration getPrefixes() {
726: if (prefixTable == null) {
727: return EMPTY_ENUMERATION;
728: } else {
729: return prefixTable.keys();
730: }
731: }
732:
733: ////////////////////////////////////////////////////////////////
734: // Internal methods.
735: ////////////////////////////////////////////////////////////////
736:
737: /**
738: * Copy on write for the internal tables in this context.
739: *
740: * <p>This class is optimized for the normal case where most
741: * elements do not contain Namespace declarations.</p>
742: */
743: private void copyTables() {
744: if (prefixTable != null) {
745: prefixTable = (Hashtable) prefixTable.clone();
746: } else {
747: prefixTable = new Hashtable();
748: }
749: if (uriTable != null) {
750: uriTable = (Hashtable) uriTable.clone();
751: } else {
752: uriTable = new Hashtable();
753: }
754: elementNameTable = new Hashtable();
755: attributeNameTable = new Hashtable();
756: declSeen = true;
757: }
758:
759: ////////////////////////////////////////////////////////////////
760: // Protected state.
761: ////////////////////////////////////////////////////////////////
762:
763: Hashtable prefixTable;
764: Hashtable uriTable;
765: Hashtable elementNameTable;
766: Hashtable attributeNameTable;
767: String defaultNS = "";
768:
769: ////////////////////////////////////////////////////////////////
770: // Internal state.
771: ////////////////////////////////////////////////////////////////
772:
773: private Vector declarations = null;
774: private boolean declSeen = false;
775: private Context parent = null;
776: }
777: }
778:
779: // end of NamespaceSupport.java
|