/** * Scans External ID and return the public and system IDs. * * @param identifiers An array of size 2 to return the system id, and public id (in that order). * @param optionalSystemId Specifies whether the system id is optional. * <p><strong>Note:</strong> This method uses fString and fStringBuffer, anything in them at * the time of calling is lost. */ protected void scanExternalID(String[] identifiers, boolean optionalSystemId) throws IOException, XNIException { String systemId = null; String publicId = null; if (fEntityScanner.skipString("PUBLIC")) { if (!fEntityScanner.skipSpaces()) { reportFatalError("SpaceRequiredAfterPUBLIC", null); } scanPubidLiteral(fString); publicId = fString.toString(); if (!fEntityScanner.skipSpaces() && !optionalSystemId) { reportFatalError("SpaceRequiredBetweenPublicAndSystem", null); } } if (publicId != null || fEntityScanner.skipString("SYSTEM")) { if (publicId == null && !fEntityScanner.skipSpaces()) { reportFatalError("SpaceRequiredAfterSYSTEM", null); } int quote = fEntityScanner.peekChar(); if (quote != '\'' && quote != '"') { if (publicId != null && optionalSystemId) { // looks like we don't have any system id // simply return the public id identifiers[0] = null; identifiers[1] = publicId; return; } reportFatalError("QuoteRequiredInSystemID", null); } fEntityScanner.scanChar(); XMLString ident = fString; if (fEntityScanner.scanLiteral(quote, ident) != quote) { fStringBuffer.clear(); do { fStringBuffer.append(ident); int c = fEntityScanner.peekChar(); if (XMLChar.isMarkup(c) || c == ']') { fStringBuffer.append((char) fEntityScanner.scanChar()); } else if (c != -1 && isInvalidLiteral(c)) { reportFatalError("InvalidCharInSystemID", new Object[] {Integer.toString(c, 16)}); } } while (fEntityScanner.scanLiteral(quote, ident) != quote); fStringBuffer.append(ident); ident = fStringBuffer; } systemId = ident.toString(); if (!fEntityScanner.skipChar(quote)) { reportFatalError("SystemIDUnterminated", null); } } // store result in array identifiers[0] = systemId; identifiers[1] = publicId; }
/** * 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 * <p><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 { String name = scanPseudoAttributeName(); // XMLEntityManager.print(fEntityManager.getCurrentEntity()); if (name == null) { reportFatalError("PseudoAttrNameExpected", null); } fEntityScanner.skipSpaces(); if (!fEntityScanner.skipChar('=')) { reportFatalError( scanningTextDecl ? "EqRequiredInTextDecl" : "EqRequiredInXMLDecl", new Object[] {name}); } fEntityScanner.skipSpaces(); 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()); } 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 an attribute value and normalizes whitespace converting all whitespace characters to * space characters. * * <p>[10] AttValue ::= '"' ([^<&"] | Reference)* '"' | "'" ([^<&'] | Reference)* "'" * * @param value The XMLString to fill in with the value. * @param nonNormalizedValue The XMLString to fill in with the non-normalized value. * @param atName The name of the attribute being parsed (for error msgs). * @param checkEntities true if undeclared entities should be reported as VC violation, false if * undeclared entities should be reported as WFC violation. * @param eleName The name of element to which this attribute belongs. * <p><strong>Note:</strong> This method uses fStringBuffer2, anything in it at the time of * calling is lost. */ protected void scanAttributeValue( XMLString value, XMLString nonNormalizedValue, String atName, boolean checkEntities, String eleName) throws IOException, XNIException { // quote int quote = fEntityScanner.peekChar(); if (quote != '\'' && quote != '"') { reportFatalError("OpenQuoteExpected", new Object[] {eleName, atName}); } fEntityScanner.scanChar(); int entityDepth = fEntityDepth; int c = fEntityScanner.scanLiteral(quote, value); if (DEBUG_ATTR_NORMALIZATION) { System.out.println("** scanLiteral -> \"" + value.toString() + "\""); } fStringBuffer2.clear(); fStringBuffer2.append(value); normalizeWhitespace(value); if (DEBUG_ATTR_NORMALIZATION) { System.out.println("** normalizeWhitespace -> \"" + value.toString() + "\""); } if (c != quote) { fScanningAttribute = true; fStringBuffer.clear(); do { fStringBuffer.append(value); if (DEBUG_ATTR_NORMALIZATION) { System.out.println("** value2: \"" + fStringBuffer.toString() + "\""); } if (c == '&') { fEntityScanner.skipChar('&'); if (entityDepth == fEntityDepth) { fStringBuffer2.append('&'); } if (fEntityScanner.skipChar('#')) { if (entityDepth == fEntityDepth) { fStringBuffer2.append('#'); } int ch = scanCharReferenceValue(fStringBuffer, fStringBuffer2); if (ch != -1) { if (DEBUG_ATTR_NORMALIZATION) { System.out.println("** value3: \"" + fStringBuffer.toString() + "\""); } } } else { String entityName = fEntityScanner.scanName(); if (entityName == null) { reportFatalError("NameRequiredInReference", null); } else if (entityDepth == fEntityDepth) { fStringBuffer2.append(entityName); } if (!fEntityScanner.skipChar(';')) { reportFatalError("SemicolonRequiredInReference", new Object[] {entityName}); } else if (entityDepth == fEntityDepth) { fStringBuffer2.append(';'); } if (entityName == fAmpSymbol) { fStringBuffer.append('&'); if (DEBUG_ATTR_NORMALIZATION) { System.out.println("** value5: \"" + fStringBuffer.toString() + "\""); } } else if (entityName == fAposSymbol) { fStringBuffer.append('\''); if (DEBUG_ATTR_NORMALIZATION) { System.out.println("** value7: \"" + fStringBuffer.toString() + "\""); } } else if (entityName == fLtSymbol) { fStringBuffer.append('<'); if (DEBUG_ATTR_NORMALIZATION) { System.out.println("** value9: \"" + fStringBuffer.toString() + "\""); } } else if (entityName == fGtSymbol) { fStringBuffer.append('>'); if (DEBUG_ATTR_NORMALIZATION) { System.out.println("** valueB: \"" + fStringBuffer.toString() + "\""); } } else if (entityName == fQuotSymbol) { fStringBuffer.append('"'); if (DEBUG_ATTR_NORMALIZATION) { System.out.println("** valueD: \"" + fStringBuffer.toString() + "\""); } } else { if (fEntityManager.isExternalEntity(entityName)) { reportFatalError("ReferenceToExternalEntity", new Object[] {entityName}); } else { if (!fEntityManager.isDeclaredEntity(entityName)) { // WFC & VC: Entity Declared if (checkEntities) { if (fValidation) { fErrorReporter.reportError( XMLMessageFormatter.XML_DOMAIN, "EntityNotDeclared", new Object[] {entityName}, XMLErrorReporter.SEVERITY_ERROR); } } else { reportFatalError("EntityNotDeclared", new Object[] {entityName}); } } fEntityManager.startEntity(entityName, true); } } } } else if (c == '<') { reportFatalError("LessthanInAttValue", new Object[] {eleName, atName}); fEntityScanner.scanChar(); if (entityDepth == fEntityDepth) { fStringBuffer2.append((char) c); } } else if (c == '%' || c == ']') { fEntityScanner.scanChar(); fStringBuffer.append((char) c); if (entityDepth == fEntityDepth) { fStringBuffer2.append((char) c); } if (DEBUG_ATTR_NORMALIZATION) { System.out.println("** valueF: \"" + fStringBuffer.toString() + "\""); } } else if (c == '\n' || c == '\r') { fEntityScanner.scanChar(); fStringBuffer.append(' '); if (entityDepth == fEntityDepth) { fStringBuffer2.append('\n'); } } else if (c != -1 && XMLChar.isHighSurrogate(c)) { fStringBuffer3.clear(); if (scanSurrogates(fStringBuffer3)) { fStringBuffer.append(fStringBuffer3); if (entityDepth == fEntityDepth) { fStringBuffer2.append(fStringBuffer3); } if (DEBUG_ATTR_NORMALIZATION) { System.out.println("** valueI: \"" + fStringBuffer.toString() + "\""); } } } else if (c != -1 && isInvalidLiteral(c)) { reportFatalError( "InvalidCharInAttValue", new Object[] {eleName, atName, Integer.toString(c, 16)}); fEntityScanner.scanChar(); if (entityDepth == fEntityDepth) { fStringBuffer2.append((char) c); } } c = fEntityScanner.scanLiteral(quote, value); if (entityDepth == fEntityDepth) { fStringBuffer2.append(value); } normalizeWhitespace(value); } while (c != quote || entityDepth != fEntityDepth); fStringBuffer.append(value); if (DEBUG_ATTR_NORMALIZATION) { System.out.println("** valueN: \"" + fStringBuffer.toString() + "\""); } value.setValues(fStringBuffer); fScanningAttribute = false; } nonNormalizedValue.setValues(fStringBuffer2); // quote int cquote = fEntityScanner.scanChar(); if (cquote != quote) { reportFatalError("CloseQuoteExpected", new Object[] {eleName, atName}); } } // scanAttributeValue()
/** * 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 * <p><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