KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xerces > impl > XMLNamespaceBinder


1 /*
2  * Copyright 2000-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.xerces.impl;
18
19 import org.apache.xerces.impl.msg.XMLMessageFormatter;
20 import org.apache.xerces.util.SymbolTable;
21 import org.apache.xerces.util.XMLSymbols;
22 import org.apache.xerces.xni.Augmentations;
23 import org.apache.xerces.xni.NamespaceContext;
24 import org.apache.xerces.xni.QName;
25 import org.apache.xerces.xni.XMLAttributes;
26 import org.apache.xerces.xni.XMLDocumentHandler;
27 import org.apache.xerces.xni.XMLLocator;
28 import org.apache.xerces.xni.XMLResourceIdentifier;
29 import org.apache.xerces.xni.XMLString;
30 import org.apache.xerces.xni.XNIException;
31 import org.apache.xerces.xni.parser.XMLComponent;
32 import org.apache.xerces.xni.parser.XMLComponentManager;
33 import org.apache.xerces.xni.parser.XMLConfigurationException;
34 import org.apache.xerces.xni.parser.XMLDocumentFilter;
35 import org.apache.xerces.xni.parser.XMLDocumentSource;
36
37 /**
38  * This class performs namespace binding on the startElement and endElement
39  * method calls and passes all other methods through to the registered
40  * document handler. This class can be configured to only pass the
41  * start and end prefix mappings (start/endPrefixMapping).
42  * <p>
43  * This component requires the following features and properties from the
44  * component manager that uses it:
45  * <ul>
46  * <li>http://xml.org/sax/features/namespaces</li>
47  * <li>http://apache.org/xml/properties/internal/symbol-table</li>
48  * <li>http://apache.org/xml/properties/internal/error-reporter</li>
49  * </ul>
50  *
51  * @xerces.internal
52  *
53  * @author Andy Clark, IBM
54  *
55  * @version $Id: XMLNamespaceBinder.java,v 1.34 2004/10/04 21:45:48 mrglavas Exp $
56  */

57 public class XMLNamespaceBinder
58     implements XMLComponent, XMLDocumentFilter {
59
60     //
61
// Constants
62
//
63

64     // feature identifiers
65

66     /** Feature identifier: namespaces. */
67     protected static final String JavaDoc NAMESPACES =
68         Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE;
69
70     // property identifiers
71

72     /** Property identifier: symbol table. */
73     protected static final String JavaDoc SYMBOL_TABLE =
74         Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
75
76     /** Property identifier: error reporter. */
77     protected static final String JavaDoc ERROR_REPORTER =
78         Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
79
80     // recognized features and properties
81

82     /** Recognized features. */
83     private static final String JavaDoc[] RECOGNIZED_FEATURES = {
84         NAMESPACES,
85     };
86
87     /** Feature defaults. */
88     private static final Boolean JavaDoc[] FEATURE_DEFAULTS = {
89         null,
90     };
91
92     /** Recognized properties. */
93     private static final String JavaDoc[] RECOGNIZED_PROPERTIES = {
94         SYMBOL_TABLE,
95         ERROR_REPORTER,
96     };
97
98     /** Property defaults. */
99     private static final Object JavaDoc[] PROPERTY_DEFAULTS = {
100         null,
101         null,
102     };
103
104     //
105
// Data
106
//
107

108     // features
109

110     /** Namespaces. */
111     protected boolean fNamespaces;
112
113     // properties
114

115     /** Symbol table. */
116     protected SymbolTable fSymbolTable;
117
118     /** Error reporter. */
119     protected XMLErrorReporter fErrorReporter;
120
121     // handlers
122

123     /** Document handler. */
124     protected XMLDocumentHandler fDocumentHandler;
125
126     protected XMLDocumentSource fDocumentSource;
127
128     // settings
129

130     /** Only pass start and end prefix mapping events. */
131     protected boolean fOnlyPassPrefixMappingEvents;
132
133     // shared context
134

135     /** Namespace context. */
136     private NamespaceContext fNamespaceContext;
137
138     // temp vars
139

140     /** Attribute QName. */
141     private QName fAttributeQName = new QName();
142
143     //
144
// Constructors
145
//
146

147     /** Default constructor. */
148     public XMLNamespaceBinder() {
149     } // <init>()
150

151     //
152
// Public methods
153
//
154

155     // settings
156

157     /**
158      * Sets whether the namespace binder only passes the prefix mapping
159      * events to the registered document handler or passes all document
160      * events.
161      *
162      * @param onlyPassPrefixMappingEvents True to pass only the prefix
163      * mapping events; false to pass
164      * all events.
165      */

166     public void setOnlyPassPrefixMappingEvents(boolean onlyPassPrefixMappingEvents) {
167         fOnlyPassPrefixMappingEvents = onlyPassPrefixMappingEvents;
168     } // setOnlyPassPrefixMappingEvents(boolean)
169

170     /**
171      * Returns true if the namespace binder only passes the prefix mapping
172      * events to the registered document handler; false if the namespace
173      * binder passes all document events.
174      */

175     public boolean getOnlyPassPrefixMappingEvents() {
176         return fOnlyPassPrefixMappingEvents;
177     } // getOnlyPassPrefixMappingEvents():boolean
178

179     //
180
// XMLComponent methods
181
//
182

183     /**
184      * Resets the component. The component can query the component manager
185      * about any features and properties that affect the operation of the
186      * component.
187      *
188      * @param componentManager The component manager.
189      *
190      * @throws SAXException Thrown by component on initialization error.
191      * For example, if a feature or property is
192      * required for the operation of the component, the
193      * component manager may throw a
194      * SAXNotRecognizedException or a
195      * SAXNotSupportedException.
196      */

197     public void reset(XMLComponentManager componentManager)
198         throws XNIException {
199
200         // features
201
try {
202             fNamespaces = componentManager.getFeature(NAMESPACES);
203         }
204         catch (XMLConfigurationException e) {
205             fNamespaces = true;
206         }
207
208         // Xerces properties
209
fSymbolTable = (SymbolTable)componentManager.getProperty(SYMBOL_TABLE);
210         fErrorReporter = (XMLErrorReporter)componentManager.getProperty(ERROR_REPORTER);
211
212     } // reset(XMLComponentManager)
213

214     /**
215      * Returns a list of feature identifiers that are recognized by
216      * this component. This method may return null if no features
217      * are recognized by this component.
218      */

219     public String JavaDoc[] getRecognizedFeatures() {
220         return (String JavaDoc[])(RECOGNIZED_FEATURES.clone());
221     } // getRecognizedFeatures():String[]
222

223     /**
224      * Sets the state of a feature. This method is called by the component
225      * manager any time after reset when a feature changes state.
226      * <p>
227      * <strong>Note:</strong> Components should silently ignore features
228      * that do not affect the operation of the component.
229      *
230      * @param featureId The feature identifier.
231      * @param state The state of the feature.
232      *
233      * @throws SAXNotRecognizedException The component should not throw
234      * this exception.
235      * @throws SAXNotSupportedException The component should not throw
236      * this exception.
237      */

238     public void setFeature(String JavaDoc featureId, boolean state)
239         throws XMLConfigurationException {
240     } // setFeature(String,boolean)
241

242     /**
243      * Returns a list of property identifiers that are recognized by
244      * this component. This method may return null if no properties
245      * are recognized by this component.
246      */

247     public String JavaDoc[] getRecognizedProperties() {
248         return (String JavaDoc[])(RECOGNIZED_PROPERTIES.clone());
249     } // getRecognizedProperties():String[]
250

251     /**
252      * Sets the value of a property during parsing.
253      *
254      * @param propertyId
255      * @param value
256      */

257     public void setProperty(String JavaDoc propertyId, Object JavaDoc value)
258         throws XMLConfigurationException {
259
260         // Xerces properties
261
if (propertyId.startsWith(Constants.XERCES_PROPERTY_PREFIX)) {
262             final int suffixLength = propertyId.length() - Constants.XERCES_PROPERTY_PREFIX.length();
263             
264             if (suffixLength == Constants.SYMBOL_TABLE_PROPERTY.length() &&
265                 propertyId.endsWith(Constants.SYMBOL_TABLE_PROPERTY)) {
266                 fSymbolTable = (SymbolTable)value;
267             }
268             else if (suffixLength == Constants.ERROR_REPORTER_PROPERTY.length() &&
269                 propertyId.endsWith(Constants.ERROR_REPORTER_PROPERTY)) {
270                 fErrorReporter = (XMLErrorReporter)value;
271             }
272             return;
273         }
274
275     } // setProperty(String,Object)
276

277     /**
278      * Returns the default state for a feature, or null if this
279      * component does not want to report a default value for this
280      * feature.
281      *
282      * @param featureId The feature identifier.
283      *
284      * @since Xerces 2.2.0
285      */

286     public Boolean JavaDoc getFeatureDefault(String JavaDoc featureId) {
287         for (int i = 0; i < RECOGNIZED_FEATURES.length; i++) {
288             if (RECOGNIZED_FEATURES[i].equals(featureId)) {
289                 return FEATURE_DEFAULTS[i];
290             }
291         }
292         return null;
293     } // getFeatureDefault(String):Boolean
294

295     /**
296      * Returns the default state for a property, or null if this
297      * component does not want to report a default value for this
298      * property.
299      *
300      * @param propertyId The property identifier.
301      *
302      * @since Xerces 2.2.0
303      */

304     public Object JavaDoc getPropertyDefault(String JavaDoc propertyId) {
305         for (int i = 0; i < RECOGNIZED_PROPERTIES.length; i++) {
306             if (RECOGNIZED_PROPERTIES[i].equals(propertyId)) {
307                 return PROPERTY_DEFAULTS[i];
308             }
309         }
310         return null;
311     } // getPropertyDefault(String):Object
312

313     //
314
// XMLDocumentSource methods
315
//
316

317     /** Sets the document handler to receive information about the document. */
318     public void setDocumentHandler(XMLDocumentHandler documentHandler) {
319         fDocumentHandler = documentHandler;
320     } // setDocumentHandler(XMLDocumentHandler)
321

322     /** Returns the document handler */
323     public XMLDocumentHandler getDocumentHandler() {
324         return fDocumentHandler;
325     } // setDocumentHandler(XMLDocumentHandler)
326

327
328     //
329
// XMLDocumentHandler methods
330
//
331

332     /** Sets the document source */
333     public void setDocumentSource(XMLDocumentSource source){
334         fDocumentSource = source;
335     } // setDocumentSource
336

337     /** Returns the document source */
338     public XMLDocumentSource getDocumentSource (){
339         return fDocumentSource;
340     } // getDocumentSource
341

342
343     /**
344      * This method notifies the start of a general entity.
345      * <p>
346      * <strong>Note:</strong> This method is not called for entity references
347      * appearing as part of attribute values.
348      *
349      * @param name The name of the general entity.
350      * @param identifier The resource identifier.
351      * @param encoding The auto-detected IANA encoding name of the entity
352      * stream. This value will be null in those situations
353      * where the entity encoding is not auto-detected (e.g.
354      * internal entities or a document entity that is
355      * parsed from a java.io.Reader).
356      * @param augs Additional information that may include infoset augmentations
357      *
358      * @exception XNIException Thrown by handler to signal an error.
359      */

360     public void startGeneralEntity(String JavaDoc name,
361                                    XMLResourceIdentifier identifier,
362                                    String JavaDoc encoding, Augmentations augs)
363         throws XNIException {
364         if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
365             fDocumentHandler.startGeneralEntity(name, identifier, encoding, augs);
366         }
367     } // startEntity(String,String,String,String,String)
368

369     /**
370      * Notifies of the presence of a TextDecl line in an entity. If present,
371      * this method will be called immediately following the startEntity call.
372      * <p>
373      * <strong>Note:</strong> This method will never be called for the
374      * document entity; it is only called for external general entities
375      * referenced in document content.
376      * <p>
377      * <strong>Note:</strong> This method is not called for entity references
378      * appearing as part of attribute values.
379      *
380      * @param version The XML version, or null if not specified.
381      * @param encoding The IANA encoding name of the entity.
382      * @param augs Additional information that may include infoset augmentations
383      *
384      * @throws XNIException Thrown by handler to signal an error.
385      */

386     public void textDecl(String JavaDoc version, String JavaDoc encoding, Augmentations augs)
387         throws XNIException {
388         if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
389             fDocumentHandler.textDecl(version, encoding, augs);
390         }
391     } // textDecl(String,String)
392

393     /**
394      * The start of the document.
395      *
396      * @param locator The system identifier of the entity if the entity
397      * is external, null otherwise.
398      * @param encoding The auto-detected IANA encoding name of the entity
399      * stream. This value will be null in those situations
400      * where the entity encoding is not auto-detected (e.g.
401      * internal entities or a document entity that is
402      * parsed from a java.io.Reader).
403      * @param namespaceContext
404      * The namespace context in effect at the
405      * start of this document.
406      * This object represents the current context.
407      * Implementors of this class are responsible
408      * for copying the namespace bindings from the
409      * the current context (and its parent contexts)
410      * if that information is important.
411      * @param augs Additional information that may include infoset augmentations
412      *
413      * @throws XNIException Thrown by handler to signal an error.
414      */

415     public void startDocument(XMLLocator locator, String JavaDoc encoding,
416                                 NamespaceContext namespaceContext, Augmentations augs)
417                               throws XNIException {
418         fNamespaceContext = namespaceContext;
419
420         if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
421             fDocumentHandler.startDocument(locator, encoding, namespaceContext, augs);
422         }
423     } // startDocument(XMLLocator,String)
424

425     /**
426      * Notifies of the presence of an XMLDecl line in the document. If
427      * present, this method will be called immediately following the
428      * startDocument call.
429      *
430      * @param version The XML version.
431      * @param encoding The IANA encoding name of the document, or null if
432      * not specified.
433      * @param standalone The standalone value, or null if not specified.
434      * @param augs Additional information that may include infoset augmentations
435      *
436      * @throws XNIException Thrown by handler to signal an error.
437      */

438     public void xmlDecl(String JavaDoc version, String JavaDoc encoding, String JavaDoc standalone, Augmentations augs)
439         throws XNIException {
440         if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
441             fDocumentHandler.xmlDecl(version, encoding, standalone, augs);
442         }
443     } // xmlDecl(String,String,String)
444

445     /**
446      * Notifies of the presence of the DOCTYPE line in the document.
447      *
448      * @param rootElement The name of the root element.
449      * @param publicId The public identifier if an external DTD or null
450      * if the external DTD is specified using SYSTEM.
451      * @param systemId The system identifier if an external DTD, null
452      * otherwise.
453      * @param augs Additional information that may include infoset augmentations
454      *
455      * @throws XNIException Thrown by handler to signal an error.
456      */

457     public void doctypeDecl(String JavaDoc rootElement,
458                             String JavaDoc publicId, String JavaDoc systemId, Augmentations augs)
459         throws XNIException {
460         if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
461             fDocumentHandler.doctypeDecl(rootElement, publicId, systemId, augs);
462         }
463     } // doctypeDecl(String,String,String)
464

465     /**
466      * A comment.
467      *
468      * @param text The text in the comment.
469      * @param augs Additional information that may include infoset augmentations
470      *
471      * @throws XNIException Thrown by application to signal an error.
472      */

473     public void comment(XMLString text, Augmentations augs) throws XNIException {
474         if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
475             fDocumentHandler.comment(text, augs);
476         }
477     } // comment(XMLString)
478

479     /**
480      * A processing instruction. Processing instructions consist of a
481      * target name and, optionally, text data. The data is only meaningful
482      * to the application.
483      * <p>
484      * Typically, a processing instruction's data will contain a series
485      * of pseudo-attributes. These pseudo-attributes follow the form of
486      * element attributes but are <strong>not</strong> parsed or presented
487      * to the application as anything other than text. The application is
488      * responsible for parsing the data.
489      *
490      * @param target The target.
491      * @param data The data or null if none specified.
492      * @param augs Additional information that may include infoset augmentations
493      *
494      * @throws XNIException Thrown by handler to signal an error.
495      */

496     public void processingInstruction(String JavaDoc target, XMLString data, Augmentations augs)
497         throws XNIException {
498         if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
499             fDocumentHandler.processingInstruction(target, data, augs);
500         }
501     } // processingInstruction(String,XMLString)
502

503
504     /**
505      * Binds the namespaces. This method will handle calling the
506      * document handler to start the prefix mappings.
507      * <p>
508      * <strong>Note:</strong> This method makes use of the
509      * fAttributeQName variable. Any contents of the variable will
510      * be destroyed. Caller should copy the values out of this
511      * temporary variable before calling this method.
512      *
513      * @param element The name of the element.
514      * @param attributes The element attributes.
515      * @param augs Additional information that may include infoset augmentations
516      *
517      * @throws XNIException Thrown by handler to signal an error.
518      */

519     public void startElement(QName element, XMLAttributes attributes, Augmentations augs)
520         throws XNIException {
521
522         if (fNamespaces) {
523             handleStartElement(element, attributes, augs, false);
524         }
525         else if (fDocumentHandler != null) {
526             fDocumentHandler.startElement(element, attributes, augs);
527         }
528
529
530     } // startElement(QName,XMLAttributes)
531

532     /**
533      * An empty element.
534      *
535      * @param element The name of the element.
536      * @param attributes The element attributes.
537      * @param augs Additional information that may include infoset augmentations
538      *
539      * @throws XNIException Thrown by handler to signal an error.
540      */

541     public void emptyElement(QName element, XMLAttributes attributes, Augmentations augs)
542         throws XNIException {
543
544         if (fNamespaces) {
545             handleStartElement(element, attributes, augs, true);
546             handleEndElement(element, augs, true);
547         }
548         else if (fDocumentHandler != null) {
549             fDocumentHandler.emptyElement(element, attributes, augs);
550         }
551
552     } // emptyElement(QName,XMLAttributes)
553

554     /**
555      * Character content.
556      *
557      * @param text The content.
558      * @param augs Additional information that may include infoset augmentations
559      *
560      * @throws XNIException Thrown by handler to signal an error.
561      */

562     public void characters(XMLString text, Augmentations augs) throws XNIException {
563         if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
564             fDocumentHandler.characters(text, augs);
565         }
566     } // characters(XMLString)
567

568     /**
569      * Ignorable whitespace. For this method to be called, the document
570      * source must have some way of determining that the text containing
571      * only whitespace characters should be considered ignorable. For
572      * example, the validator can determine if a length of whitespace
573      * characters in the document are ignorable based on the element
574      * content model.
575      *
576      * @param text The ignorable whitespace.
577      * @param augs Additional information that may include infoset augmentations
578      *
579      * @throws XNIException Thrown by handler to signal an error.
580      */

581     public void ignorableWhitespace(XMLString text, Augmentations augs) throws XNIException {
582         if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
583             fDocumentHandler.ignorableWhitespace(text, augs);
584         }
585     } // ignorableWhitespace(XMLString)
586

587     /**
588      * The end of an element.
589      *
590      * @param element The name of the element.
591      * @param augs Additional information that may include infoset augmentations
592      *
593      * @throws XNIException Thrown by handler to signal an error.
594      */

595     public void endElement(QName element, Augmentations augs) throws XNIException {
596
597         if (fNamespaces) {
598             handleEndElement(element, augs, false);
599         }
600         else if (fDocumentHandler != null) {
601             fDocumentHandler.endElement(element, augs);
602         }
603
604     } // endElement(QName)
605

606     /**
607      * The start of a CDATA section.
608      * @param augs Additional information that may include infoset augmentations
609      *
610      * @throws XNIException Thrown by handler to signal an error.
611      */

612     public void startCDATA(Augmentations augs) throws XNIException {
613         if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
614             fDocumentHandler.startCDATA(augs);
615         }
616     } // startCDATA()
617

618     /**
619      * The end of a CDATA section.
620      * @param augs Additional information that may include infoset augmentations
621      *
622      * @throws XNIException Thrown by handler to signal an error.
623      */

624     public void endCDATA(Augmentations augs) throws XNIException {
625         if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
626             fDocumentHandler.endCDATA(augs);
627         }
628     } // endCDATA()
629

630     /**
631      * The end of the document.
632      * @param augs Additional information that may include infoset augmentations
633      *
634      * @throws XNIException Thrown by handler to signal an error.
635      */

636     public void endDocument(Augmentations augs) throws XNIException {
637         if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
638             fDocumentHandler.endDocument(augs);
639         }
640     } // endDocument()
641

642     /**
643      * This method notifies the end of a general entity.
644      * <p>
645      * <strong>Note:</strong> This method is not called for entity references
646      * appearing as part of attribute values.
647      *
648      * @param name The name of the entity.
649      * @param augs Additional information that may include infoset augmentations
650      *
651      * @exception XNIException
652      * Thrown by handler to signal an error.
653      */

654     public void endGeneralEntity(String JavaDoc name, Augmentations augs) throws XNIException {
655         if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
656             fDocumentHandler.endGeneralEntity(name, augs);
657         }
658     } // endEntity(String)
659

660     //
661
// Protected methods
662
//
663

664     /** Handles start element. */
665     protected void handleStartElement(QName element, XMLAttributes attributes,
666                                       Augmentations augs,
667                                       boolean isEmpty) throws XNIException {
668
669         // add new namespace context
670
fNamespaceContext.pushContext();
671
672         if (element.prefix == XMLSymbols.PREFIX_XMLNS) {
673             fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
674                                        "ElementXMLNSPrefix",
675                                        new Object JavaDoc[]{element.rawname},
676                                        XMLErrorReporter.SEVERITY_FATAL_ERROR);
677         }
678         
679         // search for new namespace bindings
680
int length = attributes.getLength();
681         for (int i = 0; i < length; i++) {
682             String JavaDoc localpart = attributes.getLocalName(i);
683             String JavaDoc prefix = attributes.getPrefix(i);
684             // when it's of form xmlns="..." or xmlns:prefix="...",
685
// it's a namespace declaration. but prefix:xmlns="..." isn't.
686
if (prefix == XMLSymbols.PREFIX_XMLNS ||
687                 prefix == XMLSymbols.EMPTY_STRING && localpart == XMLSymbols.PREFIX_XMLNS) {
688
689                 // get the internalized value of this attribute
690
String JavaDoc uri = fSymbolTable.addSymbol(attributes.getValue(i));
691
692                 // 1. "xmlns" can't be bound to any namespace
693
if (prefix == XMLSymbols.PREFIX_XMLNS && localpart == XMLSymbols.PREFIX_XMLNS) {
694                     fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
695                                                "CantBindXMLNS",
696                                                new Object JavaDoc[]{attributes.getQName(i)},
697                                                XMLErrorReporter.SEVERITY_FATAL_ERROR);
698                 }
699                 
700                 // 2. the namespace for "xmlns" can't be bound to any prefix
701
if (uri == NamespaceContext.XMLNS_URI) {
702                     fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
703                                                "CantBindXMLNS",
704                                                new Object JavaDoc[]{attributes.getQName(i)},
705                                                XMLErrorReporter.SEVERITY_FATAL_ERROR);
706                 }
707                 
708                 // 3. "xml" can't be bound to any other namespace than it's own
709
if (localpart == XMLSymbols.PREFIX_XML) {
710                     if (uri != NamespaceContext.XML_URI) {
711                         fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
712                                                    "CantBindXML",
713                                                    new Object JavaDoc[]{attributes.getQName(i)},
714                                                    XMLErrorReporter.SEVERITY_FATAL_ERROR);
715                     }
716                 }
717                 // 4. the namespace for "xml" can't be bound to any other prefix
718
else {
719                     if (uri ==NamespaceContext.XML_URI) {
720                         fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
721                                                    "CantBindXML",
722                                                    new Object JavaDoc[]{attributes.getQName(i)},
723                                                    XMLErrorReporter.SEVERITY_FATAL_ERROR);
724                     }
725                 }
726
727                 prefix = localpart != XMLSymbols.PREFIX_XMLNS ? localpart : XMLSymbols.EMPTY_STRING;
728
729                 // http://www.w3.org/TR/1999/REC-xml-names-19990114/#dt-prefix
730
// We should only report an error if there is a prefix,
731
// that is, the local part is not "xmlns". -SG
732
// Since this is an error condition in XML 1.0,
733
// and should be relatively uncommon in XML 1.1,
734
// making this test into a method call to reuse code
735
// should be acceptable. - NG
736
if(prefixBoundToNullURI(uri, localpart)) {
737                     fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
738                                                "EmptyPrefixedAttName",
739                                                new Object JavaDoc[]{attributes.getQName(i)},
740                                                XMLErrorReporter.SEVERITY_FATAL_ERROR);
741                     continue;
742                 }
743
744                 // declare prefix in context
745
fNamespaceContext.declarePrefix(prefix, uri.length() != 0 ? uri : null);
746
747             }
748         }
749
750         // bind the element
751
String JavaDoc prefix = element.prefix != null
752                       ? element.prefix : XMLSymbols.EMPTY_STRING;
753         element.uri = fNamespaceContext.getURI(prefix);
754         if (element.prefix == null && element.uri != null) {
755             element.prefix = XMLSymbols.EMPTY_STRING;
756         }
757         if (element.prefix != null && element.uri == null) {
758             fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
759                                        "ElementPrefixUnbound",
760                                        new Object JavaDoc[]{element.prefix, element.rawname},
761                                        XMLErrorReporter.SEVERITY_FATAL_ERROR);
762         }
763
764         // bind the attributes
765
for (int i = 0; i < length; i++) {
766             attributes.getName(i, fAttributeQName);
767             String JavaDoc aprefix = fAttributeQName.prefix != null
768                            ? fAttributeQName.prefix : XMLSymbols.EMPTY_STRING;
769             String JavaDoc arawname = fAttributeQName.rawname;
770             if (arawname == XMLSymbols.PREFIX_XMLNS) {
771                 fAttributeQName.uri = fNamespaceContext.getURI(XMLSymbols.PREFIX_XMLNS);
772                 attributes.setName(i, fAttributeQName);
773             }
774             else if (aprefix != XMLSymbols.EMPTY_STRING) {
775                 fAttributeQName.uri = fNamespaceContext.getURI(aprefix);
776                 if (fAttributeQName.uri == null) {
777                     fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
778                                                "AttributePrefixUnbound",
779                                                new Object JavaDoc[]{element.rawname,arawname,aprefix},
780                                                XMLErrorReporter.SEVERITY_FATAL_ERROR);
781                 }
782                 attributes.setName(i, fAttributeQName);
783             }
784         }
785
786         // verify that duplicate attributes don't exist
787
// Example: <foo xmlns:a='NS' xmlns:b='NS' a:attr='v1' b:attr='v2'/>
788
int attrCount = attributes.getLength();
789         for (int i = 0; i < attrCount - 1; i++) {
790             String JavaDoc auri = attributes.getURI(i);
791             if (auri == null || auri == NamespaceContext.XMLNS_URI) {
792                 continue;
793             }
794             String JavaDoc alocalpart = attributes.getLocalName(i);
795             for (int j = i + 1; j < attrCount; j++) {
796                 String JavaDoc blocalpart = attributes.getLocalName(j);
797                 String JavaDoc buri = attributes.getURI(j);
798                 if (alocalpart == blocalpart && auri == buri) {
799                     fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
800                                                "AttributeNSNotUnique",
801                                                new Object JavaDoc[]{element.rawname,alocalpart, auri},
802                                                XMLErrorReporter.SEVERITY_FATAL_ERROR);
803                 }
804             }
805         }
806
807         // call handler
808
if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
809             if (isEmpty) {
810                 fDocumentHandler.emptyElement(element, attributes, augs);
811             }
812             else {
813                 fDocumentHandler.startElement(element, attributes, augs);
814             }
815         }
816
817
818     } // handleStartElement(QName,XMLAttributes,boolean)
819

820     /** Handles end element. */
821     protected void handleEndElement(QName element, Augmentations augs, boolean isEmpty)
822         throws XNIException {
823
824         // bind element
825
String JavaDoc eprefix = element.prefix != null ? element.prefix : XMLSymbols.EMPTY_STRING;
826         element.uri = fNamespaceContext.getURI(eprefix);
827         if (element.uri != null) {
828             element.prefix = eprefix;
829         }
830
831         // call handlers
832
if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
833             if (!isEmpty) {
834                 fDocumentHandler.endElement(element, augs);
835             }
836         }
837
838         // pop context
839
fNamespaceContext.popContext();
840
841     } // handleEndElement(QName,boolean)
842

843     // returns true iff the given prefix is bound to "" *and*
844
// this is disallowed by the version of XML namespaces in use.
845
protected boolean prefixBoundToNullURI(String JavaDoc uri, String JavaDoc localpart) {
846         return (uri == XMLSymbols.EMPTY_STRING && localpart != XMLSymbols.PREFIX_XMLNS);
847     } // prefixBoundToNullURI(String, String): boolean
848

849 } // class XMLNamespaceBinder
850
Popular Tags