xmlscanner.java

来自「JAVA的一些源码 JAVA2 STANDARD EDITION DEVELO」· Java 代码 · 共 1,453 行 · 第 1/4 页

JAVA
1,453
字号
    }    // common scanning methods    /**     * Scans an XML or text declaration.     * <p>     * <pre>     * [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? '?>'     * </pre>     *     * @param scanningTextDecl True if a text declaration is to     *                         be scanned instead of an XML     *                         declaration.     * @param pseudoAttributeValues An array of size 3 to return the version,     *                         encoding and standalone pseudo attribute values     *                         (in that order).     *     * <strong>Note:</strong> This method uses fString, anything in it     * at the time of calling is lost.     */    protected void scanXMLDeclOrTextDecl(boolean scanningTextDecl,                                         String[] pseudoAttributeValues)         throws IOException, XNIException {        // pseudo-attribute values        String version = null;        String encoding = null;        String standalone = null;        // scan pseudo-attributes        final int STATE_VERSION = 0;        final int STATE_ENCODING = 1;        final int STATE_STANDALONE = 2;        final int STATE_DONE = 3;        int state = STATE_VERSION;        boolean dataFoundForTarget = false;        boolean sawSpace = fEntityScanner.skipDeclSpaces();        // since pseudoattributes are *not* attributes,        // their quotes don't need to be preserved in external parameter entities.        // the XMLEntityScanner#scanLiteral method will continue to        // emit -1 in such cases when it finds a quote; this is        // fine for other methods that parse scanned entities,        // but not for the scanning of pseudoattributes.  So,        // temporarily, we must mark the current entity as not being "literal"        XMLEntityManager.ScannedEntity currEnt = fEntityManager.getCurrentEntity();        boolean currLiteral = currEnt.literal;        currEnt.literal = false;        while (fEntityScanner.peekChar() != '?') {            dataFoundForTarget = true;            String name = scanPseudoAttribute(scanningTextDecl, fString);            switch (state) {                case STATE_VERSION: {                    if (name == fVersionSymbol) {                        if (!sawSpace) {                            reportFatalError(scanningTextDecl                                       ? "SpaceRequiredBeforeVersionInTextDecl"                                       : "SpaceRequiredBeforeVersionInXMLDecl",                                             null);                        }                        version = fString.toString();                        state = STATE_ENCODING;                        if (!versionSupported(version)) {                            reportFatalError(getVersionNotSupportedKey(),                                              new Object[]{version});                        }                    }                    else if (name == fEncodingSymbol) {                        if (!scanningTextDecl) {                            reportFatalError("VersionInfoRequired", null);                        }                        if (!sawSpace) {                            reportFatalError(scanningTextDecl                                      ? "SpaceRequiredBeforeEncodingInTextDecl"                                      : "SpaceRequiredBeforeEncodingInXMLDecl",                                             null);                        }                        encoding = fString.toString();                        state = scanningTextDecl ? STATE_DONE : STATE_STANDALONE;                    }                    else {                        if (scanningTextDecl) {                            reportFatalError("EncodingDeclRequired", null);                        }                        else {                            reportFatalError("VersionInfoRequired", null);                        }                    }                    break;                }                case STATE_ENCODING: {                    if (name == fEncodingSymbol) {                        if (!sawSpace) {                            reportFatalError(scanningTextDecl                                      ? "SpaceRequiredBeforeEncodingInTextDecl"                                      : "SpaceRequiredBeforeEncodingInXMLDecl",                                             null);                        }                        encoding = fString.toString();                        state = scanningTextDecl ? STATE_DONE : STATE_STANDALONE;                        // TODO: check encoding name; set encoding on                        //       entity scanner                    }                    else if (!scanningTextDecl && name == fStandaloneSymbol) {                        if (!sawSpace) {                            reportFatalError("SpaceRequiredBeforeStandalone",                                             null);                        }                        standalone = fString.toString();                        state = STATE_DONE;                        if (!standalone.equals("yes") && !standalone.equals("no")) {                            reportFatalError("SDDeclInvalid", new Object[] {standalone});                        }                    }                    else {                        reportFatalError("EncodingDeclRequired", null);                    }                    break;                }                case STATE_STANDALONE: {                    if (name == fStandaloneSymbol) {                        if (!sawSpace) {                            reportFatalError("SpaceRequiredBeforeStandalone",                                             null);                        }                        standalone = fString.toString();                        state = STATE_DONE;                        if (!standalone.equals("yes") && !standalone.equals("no")) {                            reportFatalError("SDDeclInvalid", new Object[] {standalone});                        }                    }                    else {                        reportFatalError("EncodingDeclRequired", null);                    }                    break;                }                default: {                    reportFatalError("NoMorePseudoAttributes", null);                }            }            sawSpace = fEntityScanner.skipDeclSpaces();        }        // restore original literal value        if(currLiteral)             currEnt.literal = true;        // REVISIT: should we remove this error reporting?        if (scanningTextDecl && state != STATE_DONE) {            reportFatalError("MorePseudoAttributes", null);        }                // If there is no data in the xml or text decl then we fail to report error         // for version or encoding info above.        if (scanningTextDecl) {            if (!dataFoundForTarget && encoding == null) {                reportFatalError("EncodingDeclRequired", null);            }        }        else {            if (!dataFoundForTarget && version == null) {                reportFatalError("VersionInfoRequired", null);            }        }        // end        if (!fEntityScanner.skipChar('?')) {            reportFatalError("XMLDeclUnterminated", null);        }        if (!fEntityScanner.skipChar('>')) {            reportFatalError("XMLDeclUnterminated", null);        }                // fill in return array        pseudoAttributeValues[0] = version;        pseudoAttributeValues[1] = encoding;        pseudoAttributeValues[2] = standalone;    } // scanXMLDeclOrTextDecl(boolean)    /**     * Scans a pseudo attribute.     *     * @param scanningTextDecl True if scanning this pseudo-attribute for a     *                         TextDecl; false if scanning XMLDecl. This      *                         flag is needed to report the correct type of     *                         error.     * @param value            The string to fill in with the attribute      *                         value.     *     * @return The name of the attribute     *     * <strong>Note:</strong> This method uses fStringBuffer2, anything in it     * at the time of calling is lost.     */    public String scanPseudoAttribute(boolean scanningTextDecl,                                       XMLString value)         throws IOException, XNIException {        // REVISIT: This method is used for generic scanning of         // pseudo attributes, but since there are only three such        // attributes: version, encoding, and standalone there are        // for performant ways of scanning them. Every decl must        // have a version, and in TextDecls this version must        // be followed by an encoding declaration. Also the        // methods we invoke on the scanners allow non-ASCII        // characters to be parsed in the decls, but since        // we don't even know what the actual encoding of the        // document is until we scan the encoding declaration        // you cannot reliably read any characters outside        // of the ASCII range here. -- mrglavas        String name = fEntityScanner.scanName();        XMLEntityManager.print(fEntityManager.getCurrentEntity());        if (name == null) {            reportFatalError("PseudoAttrNameExpected", null);        }        fEntityScanner.skipDeclSpaces();        if (!fEntityScanner.skipChar('=')) {            reportFatalError(scanningTextDecl ? "EqRequiredInTextDecl"                             : "EqRequiredInXMLDecl", new Object[]{name});        }        fEntityScanner.skipDeclSpaces();        int quote = fEntityScanner.peekChar();        if (quote != '\'' && quote != '"') {            reportFatalError(scanningTextDecl ? "QuoteRequiredInTextDecl"                             : "QuoteRequiredInXMLDecl" , new Object[]{name});        }        fEntityScanner.scanChar();        int c = fEntityScanner.scanLiteral(quote, value);        if (c != quote) {            fStringBuffer2.clear();            do {                fStringBuffer2.append(value);                if (c != -1) {                    if (c == '&' || c == '%' || c == '<' || c == ']') {                        fStringBuffer2.append((char)fEntityScanner.scanChar());                    }                    // REVISIT: Even if you could reliably read non-ASCII chars                    // why bother scanning for surrogates here? Only ASCII chars                    // match the productions in XMLDecls and TextDecls. -- mrglavas                    else if (XMLChar.isHighSurrogate(c)) {                        scanSurrogates(fStringBuffer2);                    }                    else if (isInvalidLiteral(c)) {                        String key = scanningTextDecl                            ? "InvalidCharInTextDecl" : "InvalidCharInXMLDecl";                        reportFatalError(key,                                       new Object[] {Integer.toString(c, 16)});                        fEntityScanner.scanChar();                    }                }                c = fEntityScanner.scanLiteral(quote, value);            } while (c != quote);            fStringBuffer2.append(value);            value.setValues(fStringBuffer2);        }        if (!fEntityScanner.skipChar(quote)) {            reportFatalError(scanningTextDecl ? "CloseQuoteMissingInTextDecl"                             : "CloseQuoteMissingInXMLDecl",                             new Object[]{name});        }        // return        return name;    } // scanPseudoAttribute(XMLString):String        /**     * Scans a processing instruction.     * <p>     * <pre>     * [16] PI ::= '&lt;?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'     * [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))     * </pre>     * <strong>Note:</strong> This method uses fString, anything in it     * at the time of calling is lost.     */    protected void scanPI() throws IOException, XNIException {        // target        fReportEntity = false;        String target = null;        if(fNamespaces) {            target = fEntityScanner.scanNCName();        } else {            target = fEntityScanner.scanName();        }        if (target == null) {            reportFatalError("PITargetRequired", null);        }        // scan data        scanPIData(target, fString);        fReportEntity = true;    } // scanPI()    /**     * Scans a processing data. This is needed to handle the situation     * where a document starts with a processing instruction whose      * target name <em>starts with</em> "xml". (e.g. xmlfoo)     *     * <strong>Note:</strong> This method uses fStringBuffer, anything in it     * at the time of calling is lost.     *     * @param target The PI target     * @param data The string to fill in with the data     */    protected void scanPIData(String target, XMLString data)         throws IOException, XNIException {        // check target        if (target.length() == 3) {            char c0 = Character.toLowerCase(target.charAt(0));            char c1 = Character.toLowerCase(target.charAt(1));            char c2 = Character.toLowerCase(target.charAt(2));            if (c0 == 'x' && c1 == 'm' && c2 == 'l') {                reportFatalError("ReservedPITarget", null);            }        }        // spaces        if (!fEntityScanner.skipSpaces()) {            if (fEntityScanner.skipString("?>")) {                // we found the end, there is no data                data.clear();                return;            }            else {                if(fNamespaces && fEntityScanner.peekChar() == ':') {                     fEntityScanner.scanChar();                    XMLStringBuffer colonName = new XMLStringBuffer(target);                    colonName.append(":");                    String str = fEntityScanner.scanName();                    if (str != null)                        colonName.append(str);                    reportFatalError("ColonNotLegalWithNS", new Object[] {colonName.toString()});                    fEntityScanner.skipSpaces();                } else {                    // if there is data there should be some space                    reportFatalError("SpaceRequiredInPI", null);                }            }        }        fStringBuffer.clear();        // data        if (fEntityScanner.scanData("?>", fStringBuffer)) {            do {                int c = fEntityScanner.peekChar();                if (c != -1) {                    if (XMLChar.isHighSurrogate(c)) {                        scanSurrogates(fStringBuffer);                    }                    else if (isInvalidLiteral(c)) {                        reportFatalError("InvalidCharInPI",                                         new Object[]{Integer.toHexString(c)});

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?