Save This Page
Home » Xerces-J-src.2.9.1 » org.apache.xerces » impl » [javadoc | source]
    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    * 
    9    *      http://www.apache.org/licenses/LICENSE-2.0
   10    * 
   11    * Unless required by applicable law or agreed to in writing, software
   12    * distributed under the License is distributed on an "AS IS" BASIS,
   13    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    * See the License for the specific language governing permissions and
   15    * limitations under the License.
   16    */
   17   
   18   package org.apache.xerces.impl;
   19   
   20   import org.apache.xerces.impl.msg.XMLMessageFormatter;
   21   import org.apache.xerces.util.SymbolTable;
   22   import org.apache.xerces.util.XMLSymbols;
   23   import org.apache.xerces.xni.Augmentations;
   24   import org.apache.xerces.xni.NamespaceContext;
   25   import org.apache.xerces.xni.QName;
   26   import org.apache.xerces.xni.XMLAttributes;
   27   import org.apache.xerces.xni.XMLDocumentHandler;
   28   import org.apache.xerces.xni.XMLLocator;
   29   import org.apache.xerces.xni.XMLResourceIdentifier;
   30   import org.apache.xerces.xni.XMLString;
   31   import org.apache.xerces.xni.XNIException;
   32   import org.apache.xerces.xni.parser.XMLComponent;
   33   import org.apache.xerces.xni.parser.XMLComponentManager;
   34   import org.apache.xerces.xni.parser.XMLConfigurationException;
   35   import org.apache.xerces.xni.parser.XMLDocumentFilter;
   36   import org.apache.xerces.xni.parser.XMLDocumentSource;
   37   
   38   /**
   39    * This class performs namespace binding on the startElement and endElement
   40    * method calls and passes all other methods through to the registered
   41    * document handler. This class can be configured to only pass the
   42    * start and end prefix mappings (start/endPrefixMapping).
   43    * <p>
   44    * This component requires the following features and properties from the
   45    * component manager that uses it:
   46    * <ul>
   47    *  <li>http://xml.org/sax/features/namespaces</li>
   48    *  <li>http://apache.org/xml/properties/internal/symbol-table</li>
   49    *  <li>http://apache.org/xml/properties/internal/error-reporter</li>
   50    * </ul>
   51    * 
   52    * @xerces.internal
   53    *
   54    * @author Andy Clark, IBM
   55    *
   56    * @version $Id: XMLNamespaceBinder.java 572055 2007-09-02 17:55:43Z mrglavas $
   57    */
   58   public class XMLNamespaceBinder
   59       implements XMLComponent, XMLDocumentFilter {
   60   
   61       //
   62       // Constants
   63       //
   64   
   65       // feature identifiers
   66   
   67       /** Feature identifier: namespaces. */
   68       protected static final String NAMESPACES =
   69           Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE;
   70   
   71       // property identifiers
   72   
   73       /** Property identifier: symbol table. */
   74       protected static final String SYMBOL_TABLE =
   75           Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
   76   
   77       /** Property identifier: error reporter. */
   78       protected static final String ERROR_REPORTER =
   79           Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
   80   
   81       // recognized features and properties
   82   
   83       /** Recognized features. */
   84       private static final String[] RECOGNIZED_FEATURES = {
   85           NAMESPACES,
   86       };
   87   
   88       /** Feature defaults. */
   89       private static final Boolean[] FEATURE_DEFAULTS = {
   90           null,
   91       };
   92   
   93       /** Recognized properties. */
   94       private static final String[] RECOGNIZED_PROPERTIES = {
   95           SYMBOL_TABLE,
   96           ERROR_REPORTER,
   97       };
   98   
   99       /** Property defaults. */
  100       private static final Object[] PROPERTY_DEFAULTS = {
  101           null,
  102           null,
  103       };
  104   
  105       //
  106       // Data
  107       //
  108   
  109       // features
  110   
  111       /** Namespaces. */
  112       protected boolean fNamespaces;
  113   
  114       // properties
  115   
  116       /** Symbol table. */
  117       protected SymbolTable fSymbolTable;
  118   
  119       /** Error reporter. */
  120       protected XMLErrorReporter fErrorReporter;
  121   
  122       // handlers
  123   
  124       /** Document handler. */
  125       protected XMLDocumentHandler fDocumentHandler;
  126   
  127       protected XMLDocumentSource fDocumentSource;
  128   
  129       // settings
  130   
  131       /** Only pass start and end prefix mapping events. */
  132       protected boolean fOnlyPassPrefixMappingEvents;
  133   
  134       // shared context
  135   
  136       /** Namespace context. */
  137       private NamespaceContext fNamespaceContext;
  138   
  139       // temp vars
  140   
  141       /** Attribute QName. */
  142       private final QName fAttributeQName = new QName();
  143   
  144       //
  145       // Constructors
  146       //
  147   
  148       /** Default constructor. */
  149       public XMLNamespaceBinder() {
  150       } // <init>()
  151   
  152       //
  153       // Public methods
  154       //
  155   
  156       // settings
  157   
  158       /**
  159        * Sets whether the namespace binder only passes the prefix mapping
  160        * events to the registered document handler or passes all document
  161        * events.
  162        *
  163        * @param onlyPassPrefixMappingEvents True to pass only the prefix
  164        *                                    mapping events; false to pass
  165        *                                    all events.
  166        */
  167       public void setOnlyPassPrefixMappingEvents(boolean onlyPassPrefixMappingEvents) {
  168           fOnlyPassPrefixMappingEvents = onlyPassPrefixMappingEvents;
  169       } // setOnlyPassPrefixMappingEvents(boolean)
  170   
  171       /**
  172        * Returns true if the namespace binder only passes the prefix mapping
  173        * events to the registered document handler; false if the namespace
  174        * binder passes all document events.
  175        */
  176       public boolean getOnlyPassPrefixMappingEvents() {
  177           return fOnlyPassPrefixMappingEvents;
  178       } // getOnlyPassPrefixMappingEvents():boolean
  179   
  180       //
  181       // XMLComponent methods
  182       //
  183   
  184       /**
  185        * Resets the component. The component can query the component manager
  186        * about any features and properties that affect the operation of the
  187        * component.
  188        *
  189        * @param componentManager The component manager.
  190        *
  191        * @throws SAXException Thrown by component on initialization error.
  192        *                      For example, if a feature or property is
  193        *                      required for the operation of the component, the
  194        *                      component manager may throw a
  195        *                      SAXNotRecognizedException or a
  196        *                      SAXNotSupportedException.
  197        */
  198       public void reset(XMLComponentManager componentManager)
  199           throws XNIException {
  200   
  201           // features
  202           try {
  203               fNamespaces = componentManager.getFeature(NAMESPACES);
  204           }
  205           catch (XMLConfigurationException e) {
  206               fNamespaces = true;
  207           }
  208   
  209           // Xerces properties
  210           fSymbolTable = (SymbolTable)componentManager.getProperty(SYMBOL_TABLE);
  211           fErrorReporter = (XMLErrorReporter)componentManager.getProperty(ERROR_REPORTER);
  212   
  213       } // reset(XMLComponentManager)
  214   
  215       /**
  216        * Returns a list of feature identifiers that are recognized by
  217        * this component. This method may return null if no features
  218        * are recognized by this component.
  219        */
  220       public String[] getRecognizedFeatures() {
  221           return (String[])(RECOGNIZED_FEATURES.clone());
  222       } // getRecognizedFeatures():String[]
  223   
  224       /**
  225        * Sets the state of a feature. This method is called by the component
  226        * manager any time after reset when a feature changes state.
  227        * <p>
  228        * <strong>Note:</strong> Components should silently ignore features
  229        * that do not affect the operation of the component.
  230        *
  231        * @param featureId The feature identifier.
  232        * @param state     The state of the feature.
  233        *
  234        * @throws SAXNotRecognizedException The component should not throw
  235        *                                   this exception.
  236        * @throws SAXNotSupportedException The component should not throw
  237        *                                  this exception.
  238        */
  239       public void setFeature(String featureId, boolean state)
  240           throws XMLConfigurationException {
  241       } // setFeature(String,boolean)
  242   
  243       /**
  244        * Returns a list of property identifiers that are recognized by
  245        * this component. This method may return null if no properties
  246        * are recognized by this component.
  247        */
  248       public String[] getRecognizedProperties() {
  249           return (String[])(RECOGNIZED_PROPERTIES.clone());
  250       } // getRecognizedProperties():String[]
  251   
  252       /**
  253        * Sets the value of a property during parsing.
  254        *
  255        * @param propertyId
  256        * @param value
  257        */
  258       public void setProperty(String propertyId, Object value)
  259           throws XMLConfigurationException {
  260   
  261           // Xerces properties
  262           if (propertyId.startsWith(Constants.XERCES_PROPERTY_PREFIX)) {
  263           	final int suffixLength = propertyId.length() - Constants.XERCES_PROPERTY_PREFIX.length();
  264           	
  265               if (suffixLength == Constants.SYMBOL_TABLE_PROPERTY.length() && 
  266                   propertyId.endsWith(Constants.SYMBOL_TABLE_PROPERTY)) {
  267                   fSymbolTable = (SymbolTable)value;
  268               }
  269               else if (suffixLength == Constants.ERROR_REPORTER_PROPERTY.length() && 
  270                   propertyId.endsWith(Constants.ERROR_REPORTER_PROPERTY)) {
  271                   fErrorReporter = (XMLErrorReporter)value;
  272               }
  273               return;
  274           }
  275   
  276       } // setProperty(String,Object)
  277   
  278       /** 
  279        * Returns the default state for a feature, or null if this
  280        * component does not want to report a default value for this
  281        * feature.
  282        *
  283        * @param featureId The feature identifier.
  284        *
  285        * @since Xerces 2.2.0
  286        */
  287       public Boolean getFeatureDefault(String featureId) {
  288           for (int i = 0; i < RECOGNIZED_FEATURES.length; i++) {
  289               if (RECOGNIZED_FEATURES[i].equals(featureId)) {
  290                   return FEATURE_DEFAULTS[i];
  291               }
  292           }
  293           return null;
  294       } // getFeatureDefault(String):Boolean
  295   
  296       /** 
  297        * Returns the default state for a property, or null if this
  298        * component does not want to report a default value for this
  299        * property. 
  300        *
  301        * @param propertyId The property identifier.
  302        *
  303        * @since Xerces 2.2.0
  304        */
  305       public Object getPropertyDefault(String propertyId) {
  306           for (int i = 0; i < RECOGNIZED_PROPERTIES.length; i++) {
  307               if (RECOGNIZED_PROPERTIES[i].equals(propertyId)) {
  308                   return PROPERTY_DEFAULTS[i];
  309               }
  310           }
  311           return null;
  312       } // getPropertyDefault(String):Object
  313   
  314       //
  315       // XMLDocumentSource methods
  316       //
  317   
  318       /** Sets the document handler to receive information about the document. */
  319       public void setDocumentHandler(XMLDocumentHandler documentHandler) {
  320           fDocumentHandler = documentHandler;
  321       } // setDocumentHandler(XMLDocumentHandler)
  322   
  323       /** Returns the document handler */
  324       public XMLDocumentHandler getDocumentHandler() {
  325           return fDocumentHandler;
  326       } // setDocumentHandler(XMLDocumentHandler)
  327   
  328   
  329       //
  330       // XMLDocumentHandler methods
  331       //
  332   
  333       /** Sets the document source */
  334       public void setDocumentSource(XMLDocumentSource source){
  335           fDocumentSource = source;
  336       } // setDocumentSource
  337   
  338       /** Returns the document source */
  339       public XMLDocumentSource getDocumentSource (){
  340           return fDocumentSource;
  341       } // getDocumentSource
  342   
  343   
  344       /**
  345        * This method notifies the start of a general entity.
  346        * <p>
  347        * <strong>Note:</strong> This method is not called for entity references
  348        * appearing as part of attribute values.
  349        * 
  350        * @param name     The name of the general entity.
  351        * @param identifier The resource identifier.
  352        * @param encoding The auto-detected IANA encoding name of the entity
  353        *                 stream. This value will be null in those situations
  354        *                 where the entity encoding is not auto-detected (e.g.
  355        *                 internal entities or a document entity that is
  356        *                 parsed from a java.io.Reader).
  357        * @param augs     Additional information that may include infoset augmentations
  358        *                 
  359        * @exception XNIException Thrown by handler to signal an error.
  360        */
  361       public void startGeneralEntity(String name,
  362                                      XMLResourceIdentifier identifier,
  363                                      String encoding, Augmentations augs) 
  364           throws XNIException {
  365           if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
  366               fDocumentHandler.startGeneralEntity(name, identifier, encoding, augs);
  367           }
  368       } // startEntity(String,String,String,String,String)
  369   
  370       /**
  371        * Notifies of the presence of a TextDecl line in an entity. If present,
  372        * this method will be called immediately following the startEntity call.
  373        * <p>
  374        * <strong>Note:</strong> This method will never be called for the
  375        * document entity; it is only called for external general entities
  376        * referenced in document content.
  377        * <p>
  378        * <strong>Note:</strong> This method is not called for entity references
  379        * appearing as part of attribute values.
  380        *
  381        * @param version  The XML version, or null if not specified.
  382        * @param encoding The IANA encoding name of the entity.
  383        * @param augs     Additional information that may include infoset augmentations
  384        *
  385        * @throws XNIException Thrown by handler to signal an error.
  386        */
  387       public void textDecl(String version, String encoding, Augmentations augs)
  388           throws XNIException {
  389           if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
  390               fDocumentHandler.textDecl(version, encoding, augs);
  391           }
  392       } // textDecl(String,String)
  393   
  394       /**
  395        * The start of the document.
  396        *
  397        * @param locator  The system identifier of the entity if the entity
  398        *                 is external, null otherwise.
  399        * @param encoding The auto-detected IANA encoding name of the entity
  400        *                 stream. This value will be null in those situations
  401        *                 where the entity encoding is not auto-detected (e.g.
  402        *                 internal entities or a document entity that is
  403        *                 parsed from a java.io.Reader).
  404        * @param namespaceContext
  405        *                 The namespace context in effect at the
  406        *                 start of this document.
  407        *                 This object represents the current context.
  408        *                 Implementors of this class are responsible
  409        *                 for copying the namespace bindings from the
  410        *                 the current context (and its parent contexts)
  411        *                 if that information is important.
  412        * @param augs     Additional information that may include infoset augmentations
  413        *
  414        * @throws XNIException Thrown by handler to signal an error.
  415        */
  416   	public void startDocument(XMLLocator locator, String encoding,
  417                                   NamespaceContext namespaceContext, Augmentations augs)
  418   		                      throws XNIException {
  419   		fNamespaceContext = namespaceContext;
  420   
  421   		if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
  422   			fDocumentHandler.startDocument(locator, encoding, namespaceContext, augs);
  423   		}
  424   	} // startDocument(XMLLocator,String)
  425   
  426       /**
  427        * Notifies of the presence of an XMLDecl line in the document. If
  428        * present, this method will be called immediately following the
  429        * startDocument call.
  430        *
  431        * @param version    The XML version.
  432        * @param encoding   The IANA encoding name of the document, or null if
  433        *                   not specified.
  434        * @param standalone The standalone value, or null if not specified.
  435        * @param augs     Additional information that may include infoset augmentations
  436        *
  437        * @throws XNIException Thrown by handler to signal an error.
  438        */
  439       public void xmlDecl(String version, String encoding, String standalone, Augmentations augs)
  440           throws XNIException {
  441           if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
  442               fDocumentHandler.xmlDecl(version, encoding, standalone, augs);
  443           }
  444       } // xmlDecl(String,String,String)
  445   
  446       /**
  447        * Notifies of the presence of the DOCTYPE line in the document.
  448        *
  449        * @param rootElement The name of the root element.
  450        * @param publicId    The public identifier if an external DTD or null
  451        *                    if the external DTD is specified using SYSTEM.
  452        * @param systemId    The system identifier if an external DTD, null
  453        *                    otherwise.
  454        * @param augs     Additional information that may include infoset augmentations
  455        *
  456        * @throws XNIException Thrown by handler to signal an error.
  457        */
  458       public void doctypeDecl(String rootElement,
  459                               String publicId, String systemId, Augmentations augs)
  460           throws XNIException {
  461           if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
  462               fDocumentHandler.doctypeDecl(rootElement, publicId, systemId, augs);
  463           }
  464       } // doctypeDecl(String,String,String)
  465   
  466       /**
  467        * A comment.
  468        *
  469        * @param text The text in the comment.
  470        * @param augs     Additional information that may include infoset augmentations
  471        *
  472        * @throws XNIException Thrown by application to signal an error.
  473        */
  474       public void comment(XMLString text, Augmentations augs) throws XNIException {
  475           if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
  476               fDocumentHandler.comment(text, augs);
  477           }
  478       } // comment(XMLString)
  479   
  480       /**
  481        * A processing instruction. Processing instructions consist of a
  482        * target name and, optionally, text data. The data is only meaningful
  483        * to the application.
  484        * <p>
  485        * Typically, a processing instruction's data will contain a series
  486        * of pseudo-attributes. These pseudo-attributes follow the form of
  487        * element attributes but are <strong>not</strong> parsed or presented
  488        * to the application as anything other than text. The application is
  489        * responsible for parsing the data.
  490        *
  491        * @param target The target.
  492        * @param data   The data or null if none specified.
  493        * @param augs     Additional information that may include infoset augmentations
  494        *
  495        * @throws XNIException Thrown by handler to signal an error.
  496        */
  497       public void processingInstruction(String target, XMLString data, Augmentations augs)
  498           throws XNIException {
  499           if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
  500               fDocumentHandler.processingInstruction(target, data, augs);
  501           }
  502       } // processingInstruction(String,XMLString)
  503   
  504   
  505       /**
  506        * Binds the namespaces. This method will handle calling the
  507        * document handler to start the prefix mappings.
  508        * <p>
  509        * <strong>Note:</strong> This method makes use of the
  510        * fAttributeQName variable. Any contents of the variable will
  511        * be destroyed. Caller should copy the values out of this
  512        * temporary variable before calling this method.
  513        *
  514        * @param element    The name of the element.
  515        * @param attributes The element attributes.
  516        * @param augs     Additional information that may include infoset augmentations
  517        *
  518        * @throws XNIException Thrown by handler to signal an error.
  519        */
  520       public void startElement(QName element, XMLAttributes attributes, Augmentations augs)
  521           throws XNIException {
  522   
  523           if (fNamespaces) {
  524               handleStartElement(element, attributes, augs, false);
  525           }
  526           else if (fDocumentHandler != null) {
  527               fDocumentHandler.startElement(element, attributes, augs);
  528           }
  529   
  530   
  531       } // startElement(QName,XMLAttributes)
  532   
  533       /**
  534        * An empty element.
  535        *
  536        * @param element    The name of the element.
  537        * @param attributes The element attributes.
  538        * @param augs     Additional information that may include infoset augmentations
  539        *
  540        * @throws XNIException Thrown by handler to signal an error.
  541        */
  542       public void emptyElement(QName element, XMLAttributes attributes, Augmentations augs)
  543           throws XNIException {
  544   
  545           if (fNamespaces) {
  546               handleStartElement(element, attributes, augs, true);
  547               handleEndElement(element, augs, true);
  548           }
  549           else if (fDocumentHandler != null) {
  550               fDocumentHandler.emptyElement(element, attributes, augs);
  551           }
  552   
  553       } // emptyElement(QName,XMLAttributes)
  554   
  555       /**
  556        * Character content.
  557        *
  558        * @param text The content.
  559        * @param augs     Additional information that may include infoset augmentations
  560        *
  561        * @throws XNIException Thrown by handler to signal an error.
  562        */
  563       public void characters(XMLString text, Augmentations augs) throws XNIException {
  564           if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
  565               fDocumentHandler.characters(text, augs);
  566           }
  567       } // characters(XMLString)
  568   
  569       /**
  570        * Ignorable whitespace. For this method to be called, the document
  571        * source must have some way of determining that the text containing
  572        * only whitespace characters should be considered ignorable. For
  573        * example, the validator can determine if a length of whitespace
  574        * characters in the document are ignorable based on the element
  575        * content model.
  576        *
  577        * @param text The ignorable whitespace.
  578        * @param augs     Additional information that may include infoset augmentations
  579        *
  580        * @throws XNIException Thrown by handler to signal an error.
  581        */
  582       public void ignorableWhitespace(XMLString text, Augmentations augs) throws XNIException {
  583           if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
  584               fDocumentHandler.ignorableWhitespace(text, augs);
  585           }
  586       } // ignorableWhitespace(XMLString)
  587   
  588       /**
  589        * The end of an element.
  590        *
  591        * @param element The name of the element.
  592        * @param augs     Additional information that may include infoset augmentations
  593        *
  594        * @throws XNIException Thrown by handler to signal an error.
  595        */
  596       public void endElement(QName element, Augmentations augs) throws XNIException {
  597   
  598           if (fNamespaces) {
  599               handleEndElement(element, augs, false);
  600           }
  601           else if (fDocumentHandler != null) {
  602               fDocumentHandler.endElement(element, augs);
  603           }
  604   
  605       } // endElement(QName)
  606   
  607       /**
  608        * The start of a CDATA section.
  609        * @param augs     Additional information that may include infoset augmentations
  610        *
  611        * @throws XNIException Thrown by handler to signal an error.
  612        */
  613       public void startCDATA(Augmentations augs) throws XNIException {
  614           if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
  615               fDocumentHandler.startCDATA(augs);
  616           }
  617       } // startCDATA()
  618   
  619       /**
  620        * The end of a CDATA section.
  621        * @param augs     Additional information that may include infoset augmentations
  622        *
  623        * @throws XNIException Thrown by handler to signal an error.
  624        */
  625       public void endCDATA(Augmentations augs) throws XNIException {
  626           if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
  627               fDocumentHandler.endCDATA(augs);
  628           }
  629       } // endCDATA()
  630   
  631       /**
  632        * The end of the document.
  633        * @param augs     Additional information that may include infoset augmentations
  634        *
  635        * @throws XNIException Thrown by handler to signal an error.
  636        */
  637       public void endDocument(Augmentations augs) throws XNIException {
  638           if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
  639               fDocumentHandler.endDocument(augs);
  640           }
  641       } // endDocument()
  642   
  643       /**
  644        * This method notifies the end of a general entity.
  645        * <p>
  646        * <strong>Note:</strong> This method is not called for entity references
  647        * appearing as part of attribute values.
  648        * 
  649        * @param name   The name of the entity.
  650        * @param augs   Additional information that may include infoset augmentations
  651        *               
  652        * @exception XNIException
  653        *                   Thrown by handler to signal an error.
  654        */
  655       public void endGeneralEntity(String name, Augmentations augs) throws XNIException {
  656           if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
  657               fDocumentHandler.endGeneralEntity(name, augs);
  658           }
  659       } // endEntity(String)
  660   
  661       //
  662       // Protected methods
  663       //
  664   
  665       /** Handles start element. */
  666       protected void handleStartElement(QName element, XMLAttributes attributes,
  667                                         Augmentations augs,
  668                                         boolean isEmpty) throws XNIException {
  669   
  670           // add new namespace context
  671           fNamespaceContext.pushContext();
  672   
  673           if (element.prefix == XMLSymbols.PREFIX_XMLNS) {
  674               fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
  675                                          "ElementXMLNSPrefix",
  676                                          new Object[]{element.rawname},
  677                                          XMLErrorReporter.SEVERITY_FATAL_ERROR);
  678           }
  679           
  680           // search for new namespace bindings
  681           int length = attributes.getLength();
  682           for (int i = 0; i < length; i++) {
  683               String localpart = attributes.getLocalName(i);
  684               String prefix = attributes.getPrefix(i);
  685               // when it's of form xmlns="..." or xmlns:prefix="...",
  686               // it's a namespace declaration. but prefix:xmlns="..." isn't.
  687               if (prefix == XMLSymbols.PREFIX_XMLNS ||
  688                   prefix == XMLSymbols.EMPTY_STRING && localpart == XMLSymbols.PREFIX_XMLNS) {
  689   
  690                   // get the internalized value of this attribute
  691                   String uri = fSymbolTable.addSymbol(attributes.getValue(i));
  692   
  693                   // 1. "xmlns" can't be bound to any namespace
  694                   if (prefix == XMLSymbols.PREFIX_XMLNS && localpart == XMLSymbols.PREFIX_XMLNS) {
  695                       fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
  696                                                  "CantBindXMLNS",
  697                                                  new Object[]{attributes.getQName(i)},
  698                                                  XMLErrorReporter.SEVERITY_FATAL_ERROR);
  699                   }
  700                   
  701                   // 2. the namespace for "xmlns" can't be bound to any prefix
  702                   if (uri == NamespaceContext.XMLNS_URI) {
  703                       fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
  704                                                  "CantBindXMLNS",
  705                                                  new Object[]{attributes.getQName(i)},
  706                                                  XMLErrorReporter.SEVERITY_FATAL_ERROR);
  707                   }
  708                   
  709                   // 3. "xml" can't be bound to any other namespace than it's own
  710                   if (localpart == XMLSymbols.PREFIX_XML) {
  711                       if (uri != NamespaceContext.XML_URI) {
  712                           fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
  713                                                      "CantBindXML",
  714                                                      new Object[]{attributes.getQName(i)},
  715                                                      XMLErrorReporter.SEVERITY_FATAL_ERROR);
  716                       }
  717                   }
  718                   // 4. the namespace for "xml" can't be bound to any other prefix
  719                   else {
  720                       if (uri ==NamespaceContext.XML_URI) {
  721                           fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
  722                                                      "CantBindXML",
  723                                                      new Object[]{attributes.getQName(i)},
  724                                                      XMLErrorReporter.SEVERITY_FATAL_ERROR);
  725                       }
  726                   }
  727   
  728                   prefix = localpart != XMLSymbols.PREFIX_XMLNS ? localpart : XMLSymbols.EMPTY_STRING;
  729   
  730                   // http://www.w3.org/TR/1999/REC-xml-names-19990114/#dt-prefix
  731                   // We should only report an error if there is a prefix,
  732                   // that is, the local part is not "xmlns". -SG
  733                   // Since this is an error condition in XML 1.0,
  734                   // and should be relatively uncommon in XML 1.1,
  735                   // making this test into a method call to reuse code
  736                   // should be acceptable.  - NG
  737                   if(prefixBoundToNullURI(uri, localpart)) {
  738                       fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
  739                                                  "EmptyPrefixedAttName",
  740                                                  new Object[]{attributes.getQName(i)},
  741                                                  XMLErrorReporter.SEVERITY_FATAL_ERROR);
  742                       continue;
  743                   }
  744   
  745                   // declare prefix in context
  746                   fNamespaceContext.declarePrefix(prefix, uri.length() != 0 ? uri : null);
  747   
  748               }
  749           }
  750   
  751           // bind the element
  752           String prefix = element.prefix != null
  753                         ? element.prefix : XMLSymbols.EMPTY_STRING;
  754           element.uri = fNamespaceContext.getURI(prefix);
  755           if (element.prefix == null && element.uri != null) {
  756               element.prefix = XMLSymbols.EMPTY_STRING;
  757           }
  758           if (element.prefix != null && element.uri == null) {
  759               fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
  760                                          "ElementPrefixUnbound",
  761                                          new Object[]{element.prefix, element.rawname},
  762                                          XMLErrorReporter.SEVERITY_FATAL_ERROR);
  763           }
  764   
  765           // bind the attributes
  766           for (int i = 0; i < length; i++) {
  767               attributes.getName(i, fAttributeQName);
  768               String aprefix = fAttributeQName.prefix != null
  769                              ? fAttributeQName.prefix : XMLSymbols.EMPTY_STRING;
  770               String arawname = fAttributeQName.rawname;
  771               if (arawname == XMLSymbols.PREFIX_XMLNS) {
  772                   fAttributeQName.uri = fNamespaceContext.getURI(XMLSymbols.PREFIX_XMLNS);
  773                   attributes.setName(i, fAttributeQName);
  774               }
  775               else if (aprefix != XMLSymbols.EMPTY_STRING) {
  776                   fAttributeQName.uri = fNamespaceContext.getURI(aprefix);
  777                   if (fAttributeQName.uri == null) {
  778                       fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
  779                                                  "AttributePrefixUnbound",
  780                                                  new Object[]{element.rawname,arawname,aprefix},
  781                                                  XMLErrorReporter.SEVERITY_FATAL_ERROR);
  782                   }
  783                   attributes.setName(i, fAttributeQName);
  784               }
  785           }
  786   
  787           // verify that duplicate attributes don't exist
  788           // Example: <foo xmlns:a='NS' xmlns:b='NS' a:attr='v1' b:attr='v2'/>
  789           int attrCount = attributes.getLength();
  790           for (int i = 0; i < attrCount - 1; i++) {
  791               String auri = attributes.getURI(i);
  792               if (auri == null || auri == NamespaceContext.XMLNS_URI) {
  793                   continue;
  794               }
  795               String alocalpart = attributes.getLocalName(i);
  796               for (int j = i + 1; j < attrCount; j++) {
  797                   String blocalpart = attributes.getLocalName(j);
  798                   String buri = attributes.getURI(j);
  799                   if (alocalpart == blocalpart && auri == buri) {
  800                       fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
  801                                                  "AttributeNSNotUnique",
  802                                                  new Object[]{element.rawname,alocalpart, auri},
  803                                                  XMLErrorReporter.SEVERITY_FATAL_ERROR);
  804                   }
  805               }
  806           }
  807   
  808           // call handler
  809           if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
  810               if (isEmpty) {
  811                   fDocumentHandler.emptyElement(element, attributes, augs);
  812               }
  813               else {
  814                   fDocumentHandler.startElement(element, attributes, augs);
  815               }
  816           }
  817   
  818   
  819       } // handleStartElement(QName,XMLAttributes,boolean)
  820   
  821       /** Handles end element. */
  822       protected void handleEndElement(QName element, Augmentations augs, boolean isEmpty)
  823           throws XNIException {
  824   
  825           // bind element
  826           String eprefix = element.prefix != null ? element.prefix : XMLSymbols.EMPTY_STRING;
  827           element.uri = fNamespaceContext.getURI(eprefix);
  828           if (element.uri != null) {
  829               element.prefix = eprefix;
  830           }
  831   
  832           // call handlers
  833           if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
  834               if (!isEmpty) {
  835                   fDocumentHandler.endElement(element, augs);
  836               }
  837           }
  838   
  839           // pop context
  840           fNamespaceContext.popContext();
  841   
  842       } // handleEndElement(QName,boolean)
  843   
  844       // returns true iff the given prefix is bound to "" *and*
  845       // this is disallowed by the version of XML namespaces in use.
  846       protected boolean prefixBoundToNullURI(String uri, String localpart) {
  847           return (uri == XMLSymbols.EMPTY_STRING && localpart != XMLSymbols.PREFIX_XMLNS); 
  848       } // prefixBoundToNullURI(String, String):  boolean
  849   
  850   } // class XMLNamespaceBinder

Save This Page
Home » Xerces-J-src.2.9.1 » org.apache.xerces » impl » [javadoc | source]