FileDocCategorySizeDatePackage
XMLNamespaceBinder.javaAPI DocApache Xerces 3.0.134141Fri Sep 14 20:33:52 BST 2007org.apache.xerces.impl

XMLNamespaceBinder

public class XMLNamespaceBinder extends Object implements org.apache.xerces.xni.parser.XMLDocumentFilter, org.apache.xerces.xni.parser.XMLComponent
This class performs namespace binding on the startElement and endElement method calls and passes all other methods through to the registered document handler. This class can be configured to only pass the start and end prefix mappings (start/endPrefixMapping).

This component requires the following features and properties from the component manager that uses it:

  • http://xml.org/sax/features/namespaces
  • http://apache.org/xml/properties/internal/symbol-table
  • http://apache.org/xml/properties/internal/error-reporter
xerces.internal
author
Andy Clark, IBM
version
$Id: XMLNamespaceBinder.java 572055 2007-09-02 17:55:43Z mrglavas $

Fields Summary
protected static final String
NAMESPACES
Feature identifier: namespaces.
protected static final String
SYMBOL_TABLE
Property identifier: symbol table.
protected static final String
ERROR_REPORTER
Property identifier: error reporter.
private static final String[]
RECOGNIZED_FEATURES
Recognized features.
private static final Boolean[]
FEATURE_DEFAULTS
Feature defaults.
private static final String[]
RECOGNIZED_PROPERTIES
Recognized properties.
private static final Object[]
PROPERTY_DEFAULTS
Property defaults.
protected boolean
fNamespaces
Namespaces.
protected org.apache.xerces.util.SymbolTable
fSymbolTable
Symbol table.
protected XMLErrorReporter
fErrorReporter
Error reporter.
protected org.apache.xerces.xni.XMLDocumentHandler
fDocumentHandler
Document handler.
protected org.apache.xerces.xni.parser.XMLDocumentSource
fDocumentSource
protected boolean
fOnlyPassPrefixMappingEvents
Only pass start and end prefix mapping events.
private org.apache.xerces.xni.NamespaceContext
fNamespaceContext
Namespace context.
private final org.apache.xerces.xni.QName
fAttributeQName
Attribute QName.
Constructors Summary
public XMLNamespaceBinder()
Default constructor.


    //
    // Constructors
    //

       
      
    
Methods Summary
public voidcharacters(org.apache.xerces.xni.XMLString text, org.apache.xerces.xni.Augmentations augs)
Character content.

param
text The content.
param
augs Additional information that may include infoset augmentations
throws
XNIException Thrown by handler to signal an error.

        if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
            fDocumentHandler.characters(text, augs);
        }
    
public voidcomment(org.apache.xerces.xni.XMLString text, org.apache.xerces.xni.Augmentations augs)
A comment.

param
text The text in the comment.
param
augs Additional information that may include infoset augmentations
throws
XNIException Thrown by application to signal an error.

        if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
            fDocumentHandler.comment(text, augs);
        }
    
public voiddoctypeDecl(java.lang.String rootElement, java.lang.String publicId, java.lang.String systemId, org.apache.xerces.xni.Augmentations augs)
Notifies of the presence of the DOCTYPE line in the document.

param
rootElement The name of the root element.
param
publicId The public identifier if an external DTD or null if the external DTD is specified using SYSTEM.
param
systemId The system identifier if an external DTD, null otherwise.
param
augs Additional information that may include infoset augmentations
throws
XNIException Thrown by handler to signal an error.

        if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
            fDocumentHandler.doctypeDecl(rootElement, publicId, systemId, augs);
        }
    
public voidemptyElement(org.apache.xerces.xni.QName element, org.apache.xerces.xni.XMLAttributes attributes, org.apache.xerces.xni.Augmentations augs)
An empty element.

param
element The name of the element.
param
attributes The element attributes.
param
augs Additional information that may include infoset augmentations
throws
XNIException Thrown by handler to signal an error.


        if (fNamespaces) {
            handleStartElement(element, attributes, augs, true);
            handleEndElement(element, augs, true);
        }
        else if (fDocumentHandler != null) {
            fDocumentHandler.emptyElement(element, attributes, augs);
        }

    
public voidendCDATA(org.apache.xerces.xni.Augmentations augs)
The end of a CDATA section.

param
augs Additional information that may include infoset augmentations
throws
XNIException Thrown by handler to signal an error.

        if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
            fDocumentHandler.endCDATA(augs);
        }
    
public voidendDocument(org.apache.xerces.xni.Augmentations augs)
The end of the document.

param
augs Additional information that may include infoset augmentations
throws
XNIException Thrown by handler to signal an error.

        if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
            fDocumentHandler.endDocument(augs);
        }
    
public voidendElement(org.apache.xerces.xni.QName element, org.apache.xerces.xni.Augmentations augs)
The end of an element.

param
element The name of the element.
param
augs Additional information that may include infoset augmentations
throws
XNIException Thrown by handler to signal an error.


        if (fNamespaces) {
            handleEndElement(element, augs, false);
        }
        else if (fDocumentHandler != null) {
            fDocumentHandler.endElement(element, augs);
        }

    
public voidendGeneralEntity(java.lang.String name, org.apache.xerces.xni.Augmentations augs)
This method notifies the end of a general entity.

Note: This method is not called for entity references appearing as part of attribute values.

param
name The name of the entity.
param
augs Additional information that may include infoset augmentations
exception
XNIException Thrown by handler to signal an error.

        if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
            fDocumentHandler.endGeneralEntity(name, augs);
        }
    
public org.apache.xerces.xni.XMLDocumentHandlergetDocumentHandler()
Returns the document handler

        return fDocumentHandler;
    
public org.apache.xerces.xni.parser.XMLDocumentSourcegetDocumentSource()
Returns the document source

        return fDocumentSource;
    
public java.lang.BooleangetFeatureDefault(java.lang.String featureId)
Returns the default state for a feature, or null if this component does not want to report a default value for this feature.

param
featureId The feature identifier.
since
Xerces 2.2.0

        for (int i = 0; i < RECOGNIZED_FEATURES.length; i++) {
            if (RECOGNIZED_FEATURES[i].equals(featureId)) {
                return FEATURE_DEFAULTS[i];
            }
        }
        return null;
    
public booleangetOnlyPassPrefixMappingEvents()
Returns true if the namespace binder only passes the prefix mapping events to the registered document handler; false if the namespace binder passes all document events.

        return fOnlyPassPrefixMappingEvents;
    
public java.lang.ObjectgetPropertyDefault(java.lang.String propertyId)
Returns the default state for a property, or null if this component does not want to report a default value for this property.

param
propertyId The property identifier.
since
Xerces 2.2.0

        for (int i = 0; i < RECOGNIZED_PROPERTIES.length; i++) {
            if (RECOGNIZED_PROPERTIES[i].equals(propertyId)) {
                return PROPERTY_DEFAULTS[i];
            }
        }
        return null;
    
public java.lang.String[]getRecognizedFeatures()
Returns a list of feature identifiers that are recognized by this component. This method may return null if no features are recognized by this component.

        return (String[])(RECOGNIZED_FEATURES.clone());
    
public java.lang.String[]getRecognizedProperties()
Returns a list of property identifiers that are recognized by this component. This method may return null if no properties are recognized by this component.

        return (String[])(RECOGNIZED_PROPERTIES.clone());
    
protected voidhandleEndElement(org.apache.xerces.xni.QName element, org.apache.xerces.xni.Augmentations augs, boolean isEmpty)
Handles end element.


        // bind element
        String eprefix = element.prefix != null ? element.prefix : XMLSymbols.EMPTY_STRING;
        element.uri = fNamespaceContext.getURI(eprefix);
        if (element.uri != null) {
            element.prefix = eprefix;
        }

        // call handlers
        if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
            if (!isEmpty) {
                fDocumentHandler.endElement(element, augs);
            }
        }

        // pop context
        fNamespaceContext.popContext();

    
protected voidhandleStartElement(org.apache.xerces.xni.QName element, org.apache.xerces.xni.XMLAttributes attributes, org.apache.xerces.xni.Augmentations augs, boolean isEmpty)
Handles start element.


        // add new namespace context
        fNamespaceContext.pushContext();

        if (element.prefix == XMLSymbols.PREFIX_XMLNS) {
            fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
                                       "ElementXMLNSPrefix",
                                       new Object[]{element.rawname},
                                       XMLErrorReporter.SEVERITY_FATAL_ERROR);
        }
        
        // search for new namespace bindings
        int length = attributes.getLength();
        for (int i = 0; i < length; i++) {
            String localpart = attributes.getLocalName(i);
            String prefix = attributes.getPrefix(i);
            // when it's of form xmlns="..." or xmlns:prefix="...",
            // it's a namespace declaration. but prefix:xmlns="..." isn't.
            if (prefix == XMLSymbols.PREFIX_XMLNS ||
                prefix == XMLSymbols.EMPTY_STRING && localpart == XMLSymbols.PREFIX_XMLNS) {

                // get the internalized value of this attribute
                String uri = fSymbolTable.addSymbol(attributes.getValue(i));

                // 1. "xmlns" can't be bound to any namespace
                if (prefix == XMLSymbols.PREFIX_XMLNS && localpart == XMLSymbols.PREFIX_XMLNS) {
                    fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
                                               "CantBindXMLNS",
                                               new Object[]{attributes.getQName(i)},
                                               XMLErrorReporter.SEVERITY_FATAL_ERROR);
                }
                
                // 2. the namespace for "xmlns" can't be bound to any prefix
                if (uri == NamespaceContext.XMLNS_URI) {
                    fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
                                               "CantBindXMLNS",
                                               new Object[]{attributes.getQName(i)},
                                               XMLErrorReporter.SEVERITY_FATAL_ERROR);
                }
                
                // 3. "xml" can't be bound to any other namespace than it's own
                if (localpart == XMLSymbols.PREFIX_XML) {
                    if (uri != NamespaceContext.XML_URI) {
                        fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
                                                   "CantBindXML",
                                                   new Object[]{attributes.getQName(i)},
                                                   XMLErrorReporter.SEVERITY_FATAL_ERROR);
                    }
                }
                // 4. the namespace for "xml" can't be bound to any other prefix
                else {
                    if (uri ==NamespaceContext.XML_URI) {
                        fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
                                                   "CantBindXML",
                                                   new Object[]{attributes.getQName(i)},
                                                   XMLErrorReporter.SEVERITY_FATAL_ERROR);
                    }
                }

                prefix = localpart != XMLSymbols.PREFIX_XMLNS ? localpart : XMLSymbols.EMPTY_STRING;

                // http://www.w3.org/TR/1999/REC-xml-names-19990114/#dt-prefix
                // We should only report an error if there is a prefix,
                // that is, the local part is not "xmlns". -SG
                // Since this is an error condition in XML 1.0,
                // and should be relatively uncommon in XML 1.1,
                // making this test into a method call to reuse code
                // should be acceptable.  - NG
                if(prefixBoundToNullURI(uri, localpart)) {
                    fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
                                               "EmptyPrefixedAttName",
                                               new Object[]{attributes.getQName(i)},
                                               XMLErrorReporter.SEVERITY_FATAL_ERROR);
                    continue;
                }

                // declare prefix in context
                fNamespaceContext.declarePrefix(prefix, uri.length() != 0 ? uri : null);

            }
        }

        // bind the element
        String prefix = element.prefix != null
                      ? element.prefix : XMLSymbols.EMPTY_STRING;
        element.uri = fNamespaceContext.getURI(prefix);
        if (element.prefix == null && element.uri != null) {
            element.prefix = XMLSymbols.EMPTY_STRING;
        }
        if (element.prefix != null && element.uri == null) {
            fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
                                       "ElementPrefixUnbound",
                                       new Object[]{element.prefix, element.rawname},
                                       XMLErrorReporter.SEVERITY_FATAL_ERROR);
        }

        // bind the attributes
        for (int i = 0; i < length; i++) {
            attributes.getName(i, fAttributeQName);
            String aprefix = fAttributeQName.prefix != null
                           ? fAttributeQName.prefix : XMLSymbols.EMPTY_STRING;
            String arawname = fAttributeQName.rawname;
            if (arawname == XMLSymbols.PREFIX_XMLNS) {
                fAttributeQName.uri = fNamespaceContext.getURI(XMLSymbols.PREFIX_XMLNS);
                attributes.setName(i, fAttributeQName);
            }
            else if (aprefix != XMLSymbols.EMPTY_STRING) {
                fAttributeQName.uri = fNamespaceContext.getURI(aprefix);
                if (fAttributeQName.uri == null) {
                    fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
                                               "AttributePrefixUnbound",
                                               new Object[]{element.rawname,arawname,aprefix},
                                               XMLErrorReporter.SEVERITY_FATAL_ERROR);
                }
                attributes.setName(i, fAttributeQName);
            }
        }

        // verify that duplicate attributes don't exist
        // Example: <foo xmlns:a='NS' xmlns:b='NS' a:attr='v1' b:attr='v2'/>
        int attrCount = attributes.getLength();
        for (int i = 0; i < attrCount - 1; i++) {
            String auri = attributes.getURI(i);
            if (auri == null || auri == NamespaceContext.XMLNS_URI) {
                continue;
            }
            String alocalpart = attributes.getLocalName(i);
            for (int j = i + 1; j < attrCount; j++) {
                String blocalpart = attributes.getLocalName(j);
                String buri = attributes.getURI(j);
                if (alocalpart == blocalpart && auri == buri) {
                    fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
                                               "AttributeNSNotUnique",
                                               new Object[]{element.rawname,alocalpart, auri},
                                               XMLErrorReporter.SEVERITY_FATAL_ERROR);
                }
            }
        }

        // call handler
        if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
            if (isEmpty) {
                fDocumentHandler.emptyElement(element, attributes, augs);
            }
            else {
                fDocumentHandler.startElement(element, attributes, augs);
            }
        }


    
public voidignorableWhitespace(org.apache.xerces.xni.XMLString text, org.apache.xerces.xni.Augmentations augs)
Ignorable whitespace. For this method to be called, the document source must have some way of determining that the text containing only whitespace characters should be considered ignorable. For example, the validator can determine if a length of whitespace characters in the document are ignorable based on the element content model.

param
text The ignorable whitespace.
param
augs Additional information that may include infoset augmentations
throws
XNIException Thrown by handler to signal an error.

        if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
            fDocumentHandler.ignorableWhitespace(text, augs);
        }
    
protected booleanprefixBoundToNullURI(java.lang.String uri, java.lang.String localpart)

        return (uri == XMLSymbols.EMPTY_STRING && localpart != XMLSymbols.PREFIX_XMLNS); 
    
public voidprocessingInstruction(java.lang.String target, org.apache.xerces.xni.XMLString data, org.apache.xerces.xni.Augmentations augs)
A processing instruction. Processing instructions consist of a target name and, optionally, text data. The data is only meaningful to the application.

Typically, a processing instruction's data will contain a series of pseudo-attributes. These pseudo-attributes follow the form of element attributes but are not parsed or presented to the application as anything other than text. The application is responsible for parsing the data.

param
target The target.
param
data The data or null if none specified.
param
augs Additional information that may include infoset augmentations
throws
XNIException Thrown by handler to signal an error.

        if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
            fDocumentHandler.processingInstruction(target, data, augs);
        }
    
public voidreset(org.apache.xerces.xni.parser.XMLComponentManager componentManager)
Resets the component. The component can query the component manager about any features and properties that affect the operation of the component.

param
componentManager The component manager.
throws
SAXException Thrown by component on initialization error. For example, if a feature or property is required for the operation of the component, the component manager may throw a SAXNotRecognizedException or a SAXNotSupportedException.


        // features
        try {
            fNamespaces = componentManager.getFeature(NAMESPACES);
        }
        catch (XMLConfigurationException e) {
            fNamespaces = true;
        }

        // Xerces properties
        fSymbolTable = (SymbolTable)componentManager.getProperty(SYMBOL_TABLE);
        fErrorReporter = (XMLErrorReporter)componentManager.getProperty(ERROR_REPORTER);

    
public voidsetDocumentHandler(org.apache.xerces.xni.XMLDocumentHandler documentHandler)
Sets the document handler to receive information about the document.

        fDocumentHandler = documentHandler;
    
public voidsetDocumentSource(org.apache.xerces.xni.parser.XMLDocumentSource source)
Sets the document source

        fDocumentSource = source;
    
public voidsetFeature(java.lang.String featureId, boolean state)
Sets the state of a feature. This method is called by the component manager any time after reset when a feature changes state.

Note: Components should silently ignore features that do not affect the operation of the component.

param
featureId The feature identifier.
param
state The state of the feature.
throws
SAXNotRecognizedException The component should not throw this exception.
throws
SAXNotSupportedException The component should not throw this exception.

    
public voidsetOnlyPassPrefixMappingEvents(boolean onlyPassPrefixMappingEvents)
Sets whether the namespace binder only passes the prefix mapping events to the registered document handler or passes all document events.

param
onlyPassPrefixMappingEvents True to pass only the prefix mapping events; false to pass all events.

        fOnlyPassPrefixMappingEvents = onlyPassPrefixMappingEvents;
    
public voidsetProperty(java.lang.String propertyId, java.lang.Object value)
Sets the value of a property during parsing.

param
propertyId
param
value


        // Xerces properties
        if (propertyId.startsWith(Constants.XERCES_PROPERTY_PREFIX)) {
        	final int suffixLength = propertyId.length() - Constants.XERCES_PROPERTY_PREFIX.length();
        	
            if (suffixLength == Constants.SYMBOL_TABLE_PROPERTY.length() && 
                propertyId.endsWith(Constants.SYMBOL_TABLE_PROPERTY)) {
                fSymbolTable = (SymbolTable)value;
            }
            else if (suffixLength == Constants.ERROR_REPORTER_PROPERTY.length() && 
                propertyId.endsWith(Constants.ERROR_REPORTER_PROPERTY)) {
                fErrorReporter = (XMLErrorReporter)value;
            }
            return;
        }

    
public voidstartCDATA(org.apache.xerces.xni.Augmentations augs)
The start of a CDATA section.

param
augs Additional information that may include infoset augmentations
throws
XNIException Thrown by handler to signal an error.

        if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
            fDocumentHandler.startCDATA(augs);
        }
    
public voidstartDocument(org.apache.xerces.xni.XMLLocator locator, java.lang.String encoding, org.apache.xerces.xni.NamespaceContext namespaceContext, org.apache.xerces.xni.Augmentations augs)
The start of the document.

param
locator The system identifier of the entity if the entity is external, null otherwise.
param
encoding The auto-detected IANA encoding name of the entity stream. This value will be null in those situations where the entity encoding is not auto-detected (e.g. internal entities or a document entity that is parsed from a java.io.Reader).
param
namespaceContext The namespace context in effect at the start of this document. This object represents the current context. Implementors of this class are responsible for copying the namespace bindings from the the current context (and its parent contexts) if that information is important.
param
augs Additional information that may include infoset augmentations
throws
XNIException Thrown by handler to signal an error.

		fNamespaceContext = namespaceContext;

		if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
			fDocumentHandler.startDocument(locator, encoding, namespaceContext, augs);
		}
	
public voidstartElement(org.apache.xerces.xni.QName element, org.apache.xerces.xni.XMLAttributes attributes, org.apache.xerces.xni.Augmentations augs)
Binds the namespaces. This method will handle calling the document handler to start the prefix mappings.

Note: This method makes use of the fAttributeQName variable. Any contents of the variable will be destroyed. Caller should copy the values out of this temporary variable before calling this method.

param
element The name of the element.
param
attributes The element attributes.
param
augs Additional information that may include infoset augmentations
throws
XNIException Thrown by handler to signal an error.


        if (fNamespaces) {
            handleStartElement(element, attributes, augs, false);
        }
        else if (fDocumentHandler != null) {
            fDocumentHandler.startElement(element, attributes, augs);
        }


    
public voidstartGeneralEntity(java.lang.String name, org.apache.xerces.xni.XMLResourceIdentifier identifier, java.lang.String encoding, org.apache.xerces.xni.Augmentations augs)
This method notifies the start of a general entity.

Note: This method is not called for entity references appearing as part of attribute values.

param
name The name of the general entity.
param
identifier The resource identifier.
param
encoding The auto-detected IANA encoding name of the entity stream. This value will be null in those situations where the entity encoding is not auto-detected (e.g. internal entities or a document entity that is parsed from a java.io.Reader).
param
augs Additional information that may include infoset augmentations
exception
XNIException Thrown by handler to signal an error.

        if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
            fDocumentHandler.startGeneralEntity(name, identifier, encoding, augs);
        }
    
public voidtextDecl(java.lang.String version, java.lang.String encoding, org.apache.xerces.xni.Augmentations augs)
Notifies of the presence of a TextDecl line in an entity. If present, this method will be called immediately following the startEntity call.

Note: This method will never be called for the document entity; it is only called for external general entities referenced in document content.

Note: This method is not called for entity references appearing as part of attribute values.

param
version The XML version, or null if not specified.
param
encoding The IANA encoding name of the entity.
param
augs Additional information that may include infoset augmentations
throws
XNIException Thrown by handler to signal an error.

        if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
            fDocumentHandler.textDecl(version, encoding, augs);
        }
    
public voidxmlDecl(java.lang.String version, java.lang.String encoding, java.lang.String standalone, org.apache.xerces.xni.Augmentations augs)
Notifies of the presence of an XMLDecl line in the document. If present, this method will be called immediately following the startDocument call.

param
version The XML version.
param
encoding The IANA encoding name of the document, or null if not specified.
param
standalone The standalone value, or null if not specified.
param
augs Additional information that may include infoset augmentations
throws
XNIException Thrown by handler to signal an error.

        if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
            fDocumentHandler.xmlDecl(version, encoding, standalone, augs);
        }