FileDocCategorySizeDatePackage
XMLDocumentFragmentScannerImpl.javaAPI DocJava SE 5 API70398Fri Aug 26 14:55:46 BST 2005com.sun.org.apache.xerces.internal.impl

XMLDocumentFragmentScannerImpl

public class XMLDocumentFragmentScannerImpl extends XMLScanner implements XMLEntityHandler, XMLDocumentScanner, XMLComponent
This class is responsible for scanning the structure and content of document fragments. The scanner acts as the source for the document information which is communicated to the document handler.

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

  • http://xml.org/sax/features/validation
  • http://apache.org/xml/features/scanner/notify-char-refs
  • http://apache.org/xml/features/scanner/notify-builtin-refs
  • http://apache.org/xml/properties/internal/symbol-table
  • http://apache.org/xml/properties/internal/error-reporter
  • http://apache.org/xml/properties/internal/entity-manager
author
Glenn Marcy, IBM
author
Andy Clark, IBM
author
Arnaud Le Hors, IBM
author
Eric Ye, IBM
version
$Id: XMLDocumentFragmentScannerImpl.java,v 1.52 2004/04/08 22:24:52 mrglavas Exp $

Fields Summary
protected SecurityManager
fSecurityManager
protected static final int
SCANNER_STATE_START_OF_MARKUP
Scanner state: start of markup.
protected static final int
SCANNER_STATE_COMMENT
Scanner state: comment.
protected static final int
SCANNER_STATE_PI
Scanner state: processing instruction.
protected static final int
SCANNER_STATE_DOCTYPE
Scanner state: DOCTYPE.
protected static final int
SCANNER_STATE_ROOT_ELEMENT
Scanner state: root element.
protected static final int
SCANNER_STATE_CONTENT
Scanner state: content.
protected static final int
SCANNER_STATE_REFERENCE
Scanner state: reference.
protected static final int
SCANNER_STATE_END_OF_INPUT
Scanner state: end of input.
protected static final int
SCANNER_STATE_TERMINATED
Scanner state: terminated.
protected static final int
SCANNER_STATE_CDATA
Scanner state: CDATA section.
protected static final int
SCANNER_STATE_TEXT_DECL
Scanner state: Text declaration.
protected static final String
NAMESPACES
Feature identifier: namespaces.
protected static final String
NOTIFY_BUILTIN_REFS
Feature identifier: notify built-in refereces.
protected static final String
ENTITY_RESOLVER
Property identifier: entity resolver.
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.
private static final boolean
DEBUG_SCANNER_STATE
Debug scanner state.
private static final boolean
DEBUG_DISPATCHER
Debug dispatcher.
protected static final boolean
DEBUG_CONTENT_SCANNING
Debug content dispatcher scanning.
protected XMLDocumentHandler
fDocumentHandler
Document handler.
protected int[]
fEntityStack
Entity stack.
protected int
fMarkupDepth
Markup depth.
protected int
fScannerState
Scanner state.
protected boolean
fInScanContent
SubScanner state: inside scanContent method.
protected boolean
fHasExternalDTD
has external dtd
protected boolean
fStandalone
Standalone.
protected int
fElementAttributeLimit
protected ExternalSubsetResolver
fExternalSubsetResolver
External subset resolver.
protected QName
fCurrentElement
Current element.
protected ElementStack
fElementStack
Element stack.
protected boolean
fNotifyBuiltInRefs
Notify built-in references.
protected Dispatcher
fDispatcher
Active dispatcher.
protected Dispatcher
fContentDispatcher
Content dispatcher.
protected QName
fElementQName
Element QName.
protected QName
fAttributeQName
Attribute QName.
protected XMLAttributesImpl
fAttributes
Element attributes.
protected XMLString
fTempString
String.
protected XMLString
fTempString2
String.
private String[]
fStrings
Array of 3 strings.
private XMLStringBuffer
fStringBuffer
String buffer.
private XMLStringBuffer
fStringBuffer2
String buffer.
private QName
fQName
Another QName.
private final char[]
fSingleChar
Single character array.
private XMLEntityManager.ExternalEntity
fExternalEntity
External entity.
private boolean
fSawSpace
Saw spaces after element name or between attributes. This is reserved for the case where scanning of a start element spans several methods, as is the case when scanning the start of a root element where a DTD external subset may be read after scanning the element name.
Constructors Summary
public XMLDocumentFragmentScannerImpl()
Default constructor.


    //
    // Constructors
    //

       
      
Methods Summary
protected com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$DispatchercreateContentDispatcher()
Creates a content dispatcher.

        return new FragmentContentDispatcher();
    
public voidendEntity(java.lang.String name, com.sun.org.apache.xerces.internal.xni.Augmentations augs)
This method notifies the end of an entity. The DTD has the pseudo-name of "[dtd]" parameter entity names start with '%'; and general entities are just specified by their name.

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


        // flush possible pending output buffer - see scanContent
        if (fInScanContent && fStringBuffer.length != 0
            && fDocumentHandler != null) {
            fDocumentHandler.characters(fStringBuffer, null);
            fStringBuffer.length = 0; // make sure we know it's been flushed
        }

        super.endEntity(name, augs);

        // make sure markup is properly balanced
        if (fMarkupDepth != fEntityStack[fEntityDepth]) {
            reportFatalError("MarkupEntityMismatch", null);
        }

        // call handler
        if (fDocumentHandler != null && !fScanningAttribute) {
            if (!name.equals("[xml]")) {
                fDocumentHandler.endGeneralEntity(name, augs);
            }
        }
        
    
public java.lang.StringgetDispatcherName(com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$Dispatcher dispatcher)
Returns the dispatcher name.


        if (DEBUG_DISPATCHER) {
            if (dispatcher != null) {
                String name = dispatcher.getClass().getName();
                int index = name.lastIndexOf('.");
                if (index != -1) {
                    name = name.substring(index + 1);
                    index = name.lastIndexOf('$");
                    if (index != -1) {
                        name = name.substring(index + 1);
                    }
                }
                return name;
            }
        }
        return "null";

    
public com.sun.org.apache.xerces.internal.xni.XMLDocumentHandlergetDocumentHandler()
Returns the document handler

        return fDocumentHandler;
    
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 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 java.lang.StringgetScannerStateName(int state)
Returns the scanner state name.


        switch (state) {
            case SCANNER_STATE_DOCTYPE: return "SCANNER_STATE_DOCTYPE";
            case SCANNER_STATE_ROOT_ELEMENT: return "SCANNER_STATE_ROOT_ELEMENT";
            case SCANNER_STATE_START_OF_MARKUP: return "SCANNER_STATE_START_OF_MARKUP";
            case SCANNER_STATE_COMMENT: return "SCANNER_STATE_COMMENT";
            case SCANNER_STATE_PI: return "SCANNER_STATE_PI";
            case SCANNER_STATE_CONTENT: return "SCANNER_STATE_CONTENT";
            case SCANNER_STATE_REFERENCE: return "SCANNER_STATE_REFERENCE";
            case SCANNER_STATE_END_OF_INPUT: return "SCANNER_STATE_END_OF_INPUT";
            case SCANNER_STATE_TERMINATED: return "SCANNER_STATE_TERMINATED";
            case SCANNER_STATE_CDATA: return "SCANNER_STATE_CDATA";
            case SCANNER_STATE_TEXT_DECL: return "SCANNER_STATE_TEXT_DECL";
        }

        return "??? ("+state+')";

    
private voidhandleCharacter(char c, java.lang.String entity)
Calls document handler with a single character resulting from built-in entity resolution.

param
c
param
entity built-in name

        if (fDocumentHandler != null) {
            if (fNotifyBuiltInRefs) {
                fDocumentHandler.startGeneralEntity(entity, null, null, null);
            }
            
            fSingleChar[0] = c;
            fTempString.setValues(fSingleChar, 0, 1);
            fDocumentHandler.characters(fTempString, null);
            
            if (fNotifyBuiltInRefs) {
                fDocumentHandler.endGeneralEntity(entity, null);
            }
        }
    
protected inthandleEndElement(com.sun.org.apache.xerces.internal.xni.QName element, boolean isEmpty)
Handles the end element. This method will make sure that the end element name matches the current element and notify the handler about the end of the element and the end of any relevent prefix mappings.

Note: This method uses the fQName variable. The contents of this variable will be destroyed.

param
element The element.
return
The element depth.
throws
XNIException Thrown if the handler throws a SAX exception upon notification.


        fMarkupDepth--;
        // check that this element was opened in the same entity
        if (fMarkupDepth < fEntityStack[fEntityDepth - 1]) {
            reportFatalError("ElementEntityMismatch",
                             new Object[]{fCurrentElement.rawname});
        }
        // make sure the elements match
        QName startElement = fQName;
        fElementStack.popElement(startElement);
        if (element.rawname != startElement.rawname) {
            reportFatalError("ETagRequired",
                             new Object[]{startElement.rawname});
        }

        // bind namespaces
        if (fNamespaces) {
            element.uri = startElement.uri;
        }
        
        // call handler
        if (fDocumentHandler != null && !isEmpty) {
            fDocumentHandler.endElement(element, null);
        }

        return fMarkupDepth;

    
public voidreset(com.sun.org.apache.xerces.internal.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.


        super.reset(componentManager);

        // other settings
        //fDocumentSystemId = null;

        // sax features
        fAttributes.setNamespaces(fNamespaces);

        // initialize vars
        fMarkupDepth = 0;
        fCurrentElement = null;
        fElementStack.clear();
        fHasExternalDTD = false;
        fStandalone = false;
        fInScanContent = false;

		// setup dispatcher
        try {
            fSecurityManager = (SecurityManager)componentManager.getProperty(Constants.SECURITY_MANAGER);
        } catch (XMLConfigurationException e) {
            fSecurityManager = null;
        }
        
		fElementAttributeLimit = (fSecurityManager != null)?fSecurityManager.getElementAttrLimit():0;
		setScannerState(SCANNER_STATE_CONTENT);
		setDispatcher(fContentDispatcher);

        if (fParserSettings) {
            // parser settings have changed. reset them.
        	
            // xerces features
            try {
                fNotifyBuiltInRefs = componentManager.getFeature(NOTIFY_BUILTIN_REFS);
            } catch (XMLConfigurationException e) {
                fNotifyBuiltInRefs = false;
            }
            
            // xerces properties
            try {
                Object resolver = componentManager.getProperty(ENTITY_RESOLVER);
                fExternalSubsetResolver = (resolver instanceof ExternalSubsetResolver) ?
                    (ExternalSubsetResolver) resolver : null;
            }
            catch (XMLConfigurationException e) {
                fExternalSubsetResolver = null;
            }
        }

    
protected voidscanAttribute(com.sun.org.apache.xerces.internal.xni.XMLAttributes attributes)
Scans an attribute.

[41] Attribute ::= Name Eq AttValue

Note: This method assumes that the next character on the stream is the first character of the attribute name.

Note: This method uses the fAttributeQName and fQName variables. The contents of these variables will be destroyed.

param
attributes The attributes list for the scanned attribute.

        if (DEBUG_CONTENT_SCANNING) System.out.println(">>> scanAttribute()");

        // name
        if (fNamespaces) {
            fEntityScanner.scanQName(fAttributeQName);
        }
        else {
            String name = fEntityScanner.scanName();
            fAttributeQName.setValues(null, name, name, null);
        }

        // equals
        fEntityScanner.skipSpaces();
        if (!fEntityScanner.skipChar('=")) {
            reportFatalError("EqRequiredInAttribute",
                             new Object[]{fCurrentElement.rawname,fAttributeQName.rawname});
        }
        fEntityScanner.skipSpaces();

        // content
        int oldLen = attributes.getLength();
        int attrIndex = attributes.addAttribute(fAttributeQName, XMLSymbols.fCDATASymbol, null);

        // WFC: Unique Att Spec
        if (oldLen == attributes.getLength()) {
            reportFatalError("AttributeNotUnique",
                             new Object[]{fCurrentElement.rawname,
                                          fAttributeQName.rawname});
        }
        //REVISIT: one more case needs to be included: external PE and standalone is no
        boolean isVC =  fHasExternalDTD && !fStandalone;        
        scanAttributeValue(fTempString, fTempString2,
                           fAttributeQName.rawname, isVC, 
                           fCurrentElement.rawname);
        attributes.setValue(attrIndex, fTempString.toString());
        attributes.setNonNormalizedValue(attrIndex, fTempString2.toString());
        attributes.setSpecified(attrIndex, true);

        if (DEBUG_CONTENT_SCANNING) System.out.println("<<< scanAttribute()");
    
protected booleanscanCDATASection(boolean complete)
Scans a CDATA section.

Note: This method uses the fTempString and fStringBuffer variables.

param
complete True if the CDATA section is to be scanned completely.
return
True if CDATA is completely scanned.

        
        // call handler
        if (fDocumentHandler != null) {
            fDocumentHandler.startCDATA(null);
        }

        while (true) {
            fStringBuffer.clear();
            if (!fEntityScanner.scanData("]]", fStringBuffer)) {
                if (fDocumentHandler != null && fStringBuffer.length > 0) {
                    fDocumentHandler.characters(fStringBuffer, null);
                }
                int brackets = 0;
                while (fEntityScanner.skipChar(']")) {
                    brackets++;
                }
                if (fDocumentHandler != null && brackets > 0) {
                    fStringBuffer.clear();
                    if (brackets > XMLEntityManager.DEFAULT_BUFFER_SIZE) {
                        // Handle large sequences of ']'
                        int chunks = brackets / XMLEntityManager.DEFAULT_BUFFER_SIZE;
                        int remainder = brackets % XMLEntityManager.DEFAULT_BUFFER_SIZE;
                        for (int i = 0; i < XMLEntityManager.DEFAULT_BUFFER_SIZE; i++) {
                            fStringBuffer.append(']");
                        }
                        for (int i = 0; i < chunks; i++) {
                            fDocumentHandler.characters(fStringBuffer, null);
                        }
                        if (remainder != 0) {
                            fStringBuffer.length = remainder;
                            fDocumentHandler.characters(fStringBuffer, null);
                        }
                    }
                    else {
                    	for (int i = 0; i < brackets; i++) {
                    	    fStringBuffer.append(']");
                    	}
                       fDocumentHandler.characters(fStringBuffer, null);
                    }
                }
                if (fEntityScanner.skipChar('>")) {
                    break;
                }
                if (fDocumentHandler != null) {
                    fStringBuffer.clear();
                    fStringBuffer.append("]]");
                    fDocumentHandler.characters(fStringBuffer, null);
                }
            }
            else {
                if (fDocumentHandler != null) {
                    fDocumentHandler.characters(fStringBuffer, null);
                }
                int c = fEntityScanner.peekChar();
                if (c != -1 && isInvalidLiteral(c)) {
                    if (XMLChar.isHighSurrogate(c)) {
                        fStringBuffer.clear();
                        scanSurrogates(fStringBuffer);
                        if (fDocumentHandler != null) {
                            fDocumentHandler.characters(fStringBuffer, null);
                        }
                    }
                    else {
                        reportFatalError("InvalidCharInCDSect",
                                        new Object[]{Integer.toString(c,16)});
                        fEntityScanner.scanChar();
                    }
                }
            }
        }
        fMarkupDepth--;

        // call handler
        if (fDocumentHandler != null) {
            fDocumentHandler.endCDATA(null);
        }

        return true;

    
protected voidscanCharReference()
Scans a character reference.

[66] CharRef ::= '&#' [0-9]+ ';' | '&#x' [0-9a-fA-F]+ ';'


        fStringBuffer2.clear();
        int ch = scanCharReferenceValue(fStringBuffer2, null);
        fMarkupDepth--;
        if (ch != -1) {
            // call handler
            if (fDocumentHandler != null) {
                if (fNotifyCharRefs) {
                    fDocumentHandler.startGeneralEntity(fCharRefLiteral, null, null, null);
                }
                Augmentations augs = null;
                if (fValidation && ch <= 0x20) {
                    augs = new AugmentationsImpl();
                    augs.putItem(Constants.CHAR_REF_PROBABLE_WS, Boolean.TRUE);
                }
                fDocumentHandler.characters(fStringBuffer2, augs);
                if (fNotifyCharRefs) {
                    fDocumentHandler.endGeneralEntity(fCharRefLiteral, null);
                }
            }
        }

    
protected voidscanComment()
Scans a comment.

[15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'

Note: Called after scanning past '<!--'


        scanComment(fStringBuffer);
        fMarkupDepth--;

        // call handler
        if (fDocumentHandler != null) {
            fDocumentHandler.comment(fStringBuffer, null);
        }

    
protected intscanContent()
Scans element content.

return
Returns the next character on the stream.


        XMLString content = fTempString;
        int c = fEntityScanner.scanContent(content);
        if (c == '\r") {
            // happens when there is the character reference 
            fEntityScanner.scanChar();
            fStringBuffer.clear();
            fStringBuffer.append(fTempString);
            fStringBuffer.append((char)c);
            content = fStringBuffer;
            c = -1;
        }
        if (fDocumentHandler != null && content.length > 0) {
            fDocumentHandler.characters(content, null);
        }

        if (c == ']" && fTempString.length == 0) {
            fStringBuffer.clear();
            fStringBuffer.append((char)fEntityScanner.scanChar());
            // remember where we are in case we get an endEntity before we
            // could flush the buffer out - this happens when we're parsing an
            // entity which ends with a ]
            fInScanContent = true;
            //
            // We work on a single character basis to handle cases such as:
            // ']]]>' which we might otherwise miss.
            //
            if (fEntityScanner.skipChar(']")) {
                fStringBuffer.append(']");
                while (fEntityScanner.skipChar(']")) {
                    fStringBuffer.append(']");
                }
                if (fEntityScanner.skipChar('>")) {
                    reportFatalError("CDEndInContent", null);
                }
            }
            if (fDocumentHandler != null && fStringBuffer.length != 0) {
                fDocumentHandler.characters(fStringBuffer, null);
            }
            fInScanContent = false;
            c = -1;
        }
        return c;

    
public booleanscanDocument(boolean complete)
Scans a document.

param
complete True if the scanner should scan the document completely, pushing all events to the registered document handler. A value of false indicates that that the scanner should only scan the next portion of the document and return. A scanner instance is permitted to completely scan a document if it does not support this "pull" scanning model.
return
True if there is more to scan, false otherwise.

        
        // reset entity scanner
        fEntityScanner = fEntityManager.getEntityScanner();
        
        // keep dispatching "events"
        fEntityManager.setEntityHandler(this);
        do {
            if (!fDispatcher.dispatch(complete)) {
                return false;
            }
        } while (complete);

        // return success
        return true;

    
protected intscanEndElement()
Scans an end element.

[42] ETag ::= '</' Name S? '>'

Note: This method uses the fElementQName variable. The contents of this variable will be destroyed. The caller should copy the needed information out of this variable before calling this method.

return
The element depth.

        if (DEBUG_CONTENT_SCANNING) System.out.println(">>> scanEndElement()");

        fElementStack.popElement(fElementQName) ;

        // Take advantage of the fact that next string _should_ be "fElementQName.rawName",
        //In scanners most of the time is consumed on checks done for XML characters, we can
        // optimize on it and avoid the checks done for endElement,
        //we will also avoid symbol table lookup - neeraj.bajaj@sun.com

        // this should work both for namespace processing true or false...

        //REVISIT: if the string is not the same as expected.. we need to do better error handling..
        //We can skip this for now... In any case if the string doesn't match -- document is not well formed.
        if (!fEntityScanner.skipString(fElementQName.rawname)) {
            reportFatalError("ETagRequired", new Object[]{fElementQName.rawname});
        }

        // end
        fEntityScanner.skipSpaces();
        if (!fEntityScanner.skipChar('>")) {
            reportFatalError("ETagUnterminated",
                             new Object[]{fElementQName.rawname});
        }
        fMarkupDepth--;

        //we have increased the depth for two markup "<" characters
        fMarkupDepth--;
      
        // check that this element was opened in the same entity
        if (fMarkupDepth < fEntityStack[fEntityDepth - 1]) {
            reportFatalError("ElementEntityMismatch",
                             new Object[]{fCurrentElement.rawname});
        }

        // call handler
        if (fDocumentHandler != null ) {
            fDocumentHandler.endElement(fElementQName, null);
        }

        return fMarkupDepth;
 
    
protected voidscanEntityReference()
Scans an entity reference.

throws
IOException Thrown if i/o error occurs.
throws
XNIException Thrown if handler throws exception upon notification.


        // name
        String name = fEntityScanner.scanName();
        if (name == null) {
            reportFatalError("NameRequiredInReference", null);
            return;
        }

        // end
        if (!fEntityScanner.skipChar(';")) {
            reportFatalError("SemicolonRequiredInReference", new Object []{name});
        }
        fMarkupDepth--;

        // handle built-in entities
        if (name == fAmpSymbol) {
            handleCharacter('&", fAmpSymbol);
        }
        else if (name == fLtSymbol) {
            handleCharacter('<", fLtSymbol);
        }
        else if (name == fGtSymbol) {
            handleCharacter('>", fGtSymbol);
        }
        else if (name == fQuotSymbol) {
            handleCharacter('"", fQuotSymbol);
        }
        else if (name == fAposSymbol) {
            handleCharacter('\'", fAposSymbol);
        }
        // start general entity
        else if (fEntityManager.isUnparsedEntity(name)) {
            reportFatalError("ReferenceToUnparsedEntity", new Object[]{name});
        }
        else {
            if (!fEntityManager.isDeclaredEntity(name)) {
                //REVISIT: one more case needs to be included: external PE and standalone is no
                if ( fHasExternalDTD && !fStandalone) {
                    if (fValidation)
                        fErrorReporter.reportError( XMLMessageFormatter.XML_DOMAIN,"EntityNotDeclared", 
                                                    new Object[]{name}, XMLErrorReporter.SEVERITY_ERROR);
                }
                else 
                    reportFatalError("EntityNotDeclared", new Object[]{name});
            }
            fEntityManager.startEntity(name, false);
        }

    
protected voidscanPIData(java.lang.String target, com.sun.org.apache.xerces.internal.xni.XMLString data)
Scans a processing data. This is needed to handle the situation where a document starts with a processing instruction whose target name starts with "xml". (e.g. xmlfoo)

param
target The PI target
param
data The string to fill in with the data


        super.scanPIData(target, data);
        fMarkupDepth--;

        // call handler
        if (fDocumentHandler != null) {
            fDocumentHandler.processingInstruction(target, data, null);
        }

    
protected booleanscanStartElement()
Scans a start element. This method will handle the binding of namespace information and notifying the handler of the start of the element.

[44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
[40] STag ::= '<' Name (S Attribute)* S? '>'

Note: This method assumes that the leading '<' character has been consumed.

Note: This method uses the fElementQName and fAttributes variables. The contents of these variables will be destroyed. The caller should copy important information out of these variables before calling this method.

return
True if element is empty. (i.e. It matches production [44].

        if (DEBUG_CONTENT_SCANNING) System.out.println(">>> scanStartElement()");

        // name
        if (fNamespaces) {
            fEntityScanner.scanQName(fElementQName);
        }
        else {
            String name = fEntityScanner.scanName();
            fElementQName.setValues(null, name, name, null);
        }
        String rawname = fElementQName.rawname;

        // push element stack
        fCurrentElement = fElementStack.pushElement(fElementQName);

        // attributes
        boolean empty = false;
        fAttributes.removeAllAttributes();
        do {
            // spaces
            boolean sawSpace = fEntityScanner.skipSpaces();

            // end tag?
            int c = fEntityScanner.peekChar();
            if (c == '>") {
                fEntityScanner.scanChar();
                break;
            }
            else if (c == '/") {
                fEntityScanner.scanChar();
                if (!fEntityScanner.skipChar('>")) {
                    reportFatalError("ElementUnterminated",
                                     new Object[]{rawname});
                }
                empty = true;
                break;
            }
            else if (!isValidNameStartChar(c) || !sawSpace) {
                // Second chance. Check if this character is a high
                // surrogate of a valid name start character.
                if (!isValidNameStartHighSurrogate(c) || !sawSpace) {
                    reportFatalError("ElementUnterminated",
                                     new Object[] { rawname });
                }
            }

            // attributes
            scanAttribute(fAttributes);
            if (fSecurityManager != null && fAttributes.getLength() > fElementAttributeLimit){                
                fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
                                             "ElementAttributeLimit",
                                             new Object[]{rawname, new Integer(fAttributes.getLength()) },
                                             XMLErrorReporter.SEVERITY_FATAL_ERROR );
            }           
        } while (true);

        // call handler
        if (fDocumentHandler != null) {
            if (empty) {

                //decrease the markup depth..
                fMarkupDepth--;
                // check that this element was opened in the same entity
                if (fMarkupDepth < fEntityStack[fEntityDepth - 1]) {
                    reportFatalError("ElementEntityMismatch",
                                     new Object[]{fCurrentElement.rawname});
                }

                fDocumentHandler.emptyElement(fElementQName, fAttributes, null);

                //pop the element off the stack..
                fElementStack.popElement(fElementQName);
            }
            else {
                fDocumentHandler.startElement(fElementQName, fAttributes, null);
            }
        }

        if (DEBUG_CONTENT_SCANNING) System.out.println("<<< scanStartElement(): "+empty);
        return empty;

    
protected booleanscanStartElementAfterName()
Scans the remainder of a start or empty tag after the element name.

see
#scanStartElement
return
True if element is empty.

        String rawname = fElementQName.rawname;

        // push element stack
        fCurrentElement = fElementStack.pushElement(fElementQName);

        // attributes
        boolean empty = false;
        fAttributes.removeAllAttributes();
        do {
        	
            // end tag?
            int c = fEntityScanner.peekChar();
            if (c == '>") {
                fEntityScanner.scanChar();
                break;
            }
            else if (c == '/") {
                fEntityScanner.scanChar();
                if (!fEntityScanner.skipChar('>")) {
                    reportFatalError("ElementUnterminated",
                                     new Object[]{rawname});
                }
                empty = true;
                break;
            }
            else if (!isValidNameStartChar(c) || !fSawSpace) {
                // Second chance. Check if this character is a high
                // surrogate of a valid name start character.
                if (!isValidNameStartHighSurrogate(c) || !fSawSpace) {
                    reportFatalError("ElementUnterminated",
                                     new Object[] { rawname });
                }
            }

            // attributes
            scanAttribute(fAttributes);
            
            // spaces
            fSawSpace = fEntityScanner.skipSpaces();

        } while (true);

        // call handler
        if (fDocumentHandler != null) {
            if (empty) {

                //decrease the markup depth..
                fMarkupDepth--;
                // check that this element was opened in the same entity
                if (fMarkupDepth < fEntityStack[fEntityDepth - 1]) {
                    reportFatalError("ElementEntityMismatch",
                                     new Object[]{fCurrentElement.rawname});
                }

                fDocumentHandler.emptyElement(fElementQName, fAttributes, null);

                //pop the element off the stack..
                fElementStack.popElement(fElementQName);
            }
            else {
                fDocumentHandler.startElement(fElementQName, fAttributes, null);
            }
        }

        if (DEBUG_CONTENT_SCANNING) System.out.println("<<< scanStartElementAfterName(): "+empty);
        return empty;
    
protected voidscanStartElementName()
Scans the name of an element in a start or empty tag.

see
#scanStartElement()

        // name
        if (fNamespaces) {
            fEntityScanner.scanQName(fElementQName);
        }
        else {
            String name = fEntityScanner.scanName();
            fElementQName.setValues(null, name, name, null);
        }
        // Must skip spaces here because the DTD scanner
        // would consume them at the end of the external subset.
        fSawSpace = fEntityScanner.skipSpaces();
    
protected voidscanXMLDeclOrTextDecl(boolean scanningTextDecl)
Scans an XML or text declaration.

[23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
[24] VersionInfo ::= S 'version' Eq (' VersionNum ' | " VersionNum ")
[80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' | "'" EncName "'" )
[81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
[32] SDDecl ::= S 'standalone' Eq (("'" ('yes' | 'no') "'")
| ('"' ('yes' | 'no') '"'))

[77] TextDecl ::= '<?xml' VersionInfo? EncodingDecl S? '?>'

param
scanningTextDecl True if a text declaration is to be scanned instead of an XML declaration.


        // scan decl
        super.scanXMLDeclOrTextDecl(scanningTextDecl, fStrings);
        fMarkupDepth--;

        // pseudo-attribute values
        String version = fStrings[0];
        String encoding = fStrings[1];
        String standalone = fStrings[2];

        // set standalone
        fStandalone = standalone != null && standalone.equals("yes");
        fEntityManager.setStandalone(fStandalone);

        // call handler
        if (fDocumentHandler != null) {
            if (scanningTextDecl) {
                fDocumentHandler.textDecl(version, encoding, null);
            }
            else {
                fDocumentHandler.xmlDecl(version, encoding, standalone, null);
            }
        }

        // set encoding on reader
        if (encoding != null && !fEntityScanner.fCurrentEntity.isDeclaredEncoding()) {
            fEntityScanner.setEncoding(encoding);
        }

    
protected final voidsetDispatcher(com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$Dispatcher dispatcher)
Sets the dispatcher.

param
dispatcher The new dispatcher.

        fDispatcher = dispatcher;
        if (DEBUG_DISPATCHER) {
            System.out.print("%%% setDispatcher: ");
            System.out.print(getDispatcherName(dispatcher));
            System.out.println();
        }
    
public voidsetDocumentHandler(com.sun.org.apache.xerces.internal.xni.XMLDocumentHandler documentHandler)
setDocumentHandler

param
documentHandler

        fDocumentHandler = documentHandler;
    
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.


        super.setFeature(featureId, state);
            
        // Xerces properties
        if (featureId.startsWith(Constants.XERCES_FEATURE_PREFIX)) {
            final int suffixLength = featureId.length() - Constants.XERCES_FEATURE_PREFIX.length();
            if (suffixLength == Constants.NOTIFY_BUILTIN_REFS_FEATURE.length() && 
                featureId.endsWith(Constants.NOTIFY_BUILTIN_REFS_FEATURE)) {
                fNotifyBuiltInRefs = state;
            }
        }

    
public voidsetInputSource(com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource inputSource)
Sets the input source.

param
inputSource The input source.
throws
IOException Thrown on i/o error.

        fEntityManager.setEntityHandler(this);
        fEntityManager.startEntity("$fragment$", inputSource, false, true);
        //fDocumentSystemId = fEntityManager.expandSystemId(inputSource.getSystemId());
    
public voidsetProperty(java.lang.String propertyId, java.lang.Object value)
Sets the value of a property. This method is called by the component manager any time after reset when a property changes value.

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

param
propertyId The property identifier.
param
value The value of the property.
throws
SAXNotRecognizedException The component should not throw this exception.
throws
SAXNotSupportedException The component should not throw this exception.

        
        super.setProperty(propertyId, value);

        // Xerces properties
        if (propertyId.startsWith(Constants.XERCES_PROPERTY_PREFIX)) {
            final int suffixLength = propertyId.length() - Constants.XERCES_PROPERTY_PREFIX.length();
            if (suffixLength == Constants.ENTITY_MANAGER_PROPERTY.length() && 
                propertyId.endsWith(Constants.ENTITY_MANAGER_PROPERTY)) {
                fEntityManager = (XMLEntityManager)value;
                return;
            }
            if (suffixLength == Constants.ENTITY_RESOLVER_PROPERTY.length() && 
                propertyId.endsWith(Constants.ENTITY_RESOLVER_PROPERTY)) {
                fExternalSubsetResolver = (value instanceof ExternalSubsetResolver) ?
                    (ExternalSubsetResolver) value : null;
                return;
            }
        }
        
    
protected final voidsetScannerState(int state)
Sets the scanner state.

param
state The new scanner state.


        fScannerState = state;
        if (DEBUG_SCANNER_STATE) {
            System.out.print("### setScannerState: ");
            System.out.print(getScannerStateName(state));
            System.out.println();
        }

    
public voidstartEntity(java.lang.String name, com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier identifier, java.lang.String encoding, com.sun.org.apache.xerces.internal.xni.Augmentations augs)
This method notifies of the start of an entity. The DTD has the pseudo-name of "[dtd]" parameter entity names start with '%'; and general entities are just specified by their name.

param
name The name of the 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
throws
XNIException Thrown by handler to signal an error.


        // keep track of this entity before fEntityDepth is increased
        if (fEntityDepth == fEntityStack.length) {
            int[] entityarray = new int[fEntityStack.length * 2];
            System.arraycopy(fEntityStack, 0, entityarray, 0, fEntityStack.length);
            fEntityStack = entityarray;
        }
        fEntityStack[fEntityDepth] = fMarkupDepth;

        super.startEntity(name, identifier, encoding, augs);

        // WFC:  entity declared in external subset in standalone doc
        if(fStandalone && fEntityManager.isEntityDeclInExternalSubset(name)) {
            reportFatalError("MSG_REFERENCE_TO_EXTERNALLY_DECLARED_ENTITY_WHEN_STANDALONE",
                new Object[]{name});
        }

        // call handler
        if (fDocumentHandler != null && !fScanningAttribute) {
            if (!name.equals("[xml]")) {
                fDocumentHandler.startGeneralEntity(name, identifier, encoding, augs);
            }
        }