📄 xmlencodingdetector.java
字号:
}
// standard XML declaration
else {
scanXMLDeclOrTextDecl(false);
}
}
}
// Adapted from:
// org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanXMLDeclOrTextDecl
/**
* 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.
*/
private void scanXMLDeclOrTextDecl(boolean scanningTextDecl)
throws IOException, JasperException {
// scan decl
scanXMLDeclOrTextDecl(scanningTextDecl, fStrings);
fMarkupDepth--;
// pseudo-attribute values
String encodingPseudoAttr = fStrings[1];
// set encoding on reader
if (encodingPseudoAttr != null) {
isEncodingSetInProlog = true;
encoding = encodingPseudoAttr;
}
}
// Adapted from:
// org.apache.xerces.impl.XMLScanner.scanXMLDeclOrTextDecl
/**
* 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.
*/
private void scanXMLDeclOrTextDecl(boolean scanningTextDecl,
String[] pseudoAttributeValues)
throws IOException, JasperException {
// 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 = skipSpaces();
while (peekChar() != '?') {
dataFoundForTarget = true;
String name = scanPseudoAttribute(scanningTextDecl, fString);
switch (state) {
case STATE_VERSION: {
if (name == fVersionSymbol) {
if (!sawSpace) {
reportFatalError(scanningTextDecl
? "jsp.error.xml.spaceRequiredBeforeVersionInTextDecl"
: "jsp.error.xml.spaceRequiredBeforeVersionInXMLDecl",
null);
}
version = fString.toString();
state = STATE_ENCODING;
if (!version.equals("1.0")) {
// REVISIT: XML REC says we should throw an error
// in such cases.
// some may object the throwing of fatalError.
err.jspError("jsp.error.xml.versionNotSupported",
version);
}
} else if (name == fEncodingSymbol) {
if (!scanningTextDecl) {
err.jspError("jsp.error.xml.versionInfoRequired");
}
if (!sawSpace) {
reportFatalError(scanningTextDecl
? "jsp.error.xml.spaceRequiredBeforeEncodingInTextDecl"
: "jsp.error.xml.spaceRequiredBeforeEncodingInXMLDecl",
null);
}
encoding = fString.toString();
state = scanningTextDecl ? STATE_DONE : STATE_STANDALONE;
} else {
if (scanningTextDecl) {
err.jspError("jsp.error.xml.encodingDeclRequired");
}
else {
err.jspError("jsp.error.xml.versionInfoRequired");
}
}
break;
}
case STATE_ENCODING: {
if (name == fEncodingSymbol) {
if (!sawSpace) {
reportFatalError(scanningTextDecl
? "jsp.error.xml.spaceRequiredBeforeEncodingInTextDecl"
: "jsp.error.xml.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) {
err.jspError("jsp.error.xml.spaceRequiredBeforeStandalone");
}
standalone = fString.toString();
state = STATE_DONE;
if (!standalone.equals("yes") && !standalone.equals("no")) {
err.jspError("jsp.error.xml.sdDeclInvalid");
}
} else {
err.jspError("jsp.error.xml.encodingDeclRequired");
}
break;
}
case STATE_STANDALONE: {
if (name == fStandaloneSymbol) {
if (!sawSpace) {
err.jspError("jsp.error.xml.spaceRequiredBeforeStandalone");
}
standalone = fString.toString();
state = STATE_DONE;
if (!standalone.equals("yes") && !standalone.equals("no")) {
err.jspError("jsp.error.xml.sdDeclInvalid");
}
} else {
err.jspError("jsp.error.xml.encodingDeclRequired");
}
break;
}
default: {
err.jspError("jsp.error.xml.noMorePseudoAttributes");
}
}
sawSpace = skipSpaces();
}
// REVISIT: should we remove this error reporting?
if (scanningTextDecl && state != STATE_DONE) {
err.jspError("jsp.error.xml.morePseudoAttributes");
}
// 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) {
err.jspError("jsp.error.xml.encodingDeclRequired");
}
} else {
if (!dataFoundForTarget && version == null) {
err.jspError("jsp.error.xml.versionInfoRequired");
}
}
// end
if (!skipChar('?')) {
err.jspError("jsp.error.xml.xmlDeclUnterminated");
}
if (!skipChar('>')) {
err.jspError("jsp.error.xml.xmlDeclUnterminated");
}
// fill in return array
pseudoAttributeValues[0] = version;
pseudoAttributeValues[1] = encoding;
pseudoAttributeValues[2] = standalone;
}
// Adapted from:
// org.apache.xerces.impl.XMLScanner.scanPseudoAttribute
/**
* 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, JasperException {
String name = scanName();
if (name == null) {
err.jspError("jsp.error.xml.pseudoAttrNameExpected");
}
skipSpaces();
if (!skipChar('=')) {
reportFatalError(scanningTextDecl ?
"jsp.error.xml.eqRequiredInTextDecl"
: "jsp.error.xml.eqRequiredInXMLDecl",
name);
}
skipSpaces();
int quote = peekChar();
if (quote != '\'' && quote != '"') {
reportFatalError(scanningTextDecl ?
"jsp.error.xml.quoteRequiredInTextDecl"
: "jsp.error.xml.quoteRequiredInXMLDecl" ,
name);
}
scanChar();
int c = scanLiteral(quote, value);
if (c != quote) {
fStringBuffer2.clear();
do {
fStringBuffer2.append(value);
if (c != -1) {
if (c == '&' || c == '%' || c == '<' || c == ']') {
fStringBuffer2.append((char)scanChar());
}
else if (XMLChar.isHighSurrogate(c)) {
scanSurrogates(fStringBuffer2);
}
else if (XMLChar.isInvalid(c)) {
String key = scanningTextDecl
? "jsp.error.xml.invalidCharInTextDecl"
: "jsp.error.xml.invalidCharInXMLDecl";
reportFatalError(key, Integer.toString(c, 16));
scanChar();
}
}
c = scanLiteral(quote, value);
} while (c != quote);
fStringBuffer2.append(value);
value.setValues(fStringBuffer2);
}
if (!skipChar(quote)) {
reportFatalError(scanningTextDecl ?
"jsp.error.xml.closeQuoteMissingInTextDecl"
: "jsp.error.xml.closeQuoteMissingInXMLDecl",
name);
}
// return
return name;
}
// Adapted from:
// org.apache.xerces.impl.XMLScanner.scanPIData
/**
* 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
*/
private void scanPIData(String target, XMLString data)
throws IOException, JasperException {
// 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') {
err.jspError("jsp.error.xml.reservedPITarget");
}
}
// spaces
if (!skipSpaces()) {
if (skipString("?>")) {
// we found the end, there is no data
data.clear();
return;
}
else {
// if there is data there should be some space
err.jspError("jsp.error.xml.spaceRequiredInPI");
}
}
fStringBuffer.clear();
// data
if (scanData("?>", fStringBuffer)) {
do {
int c = peekChar();
if (c != -1) {
if (XMLChar.isHighSurrogate(c)) {
scanSurrogates(fStringBuffer);
} else if (XMLChar.isInvalid(c)) {
err.jspError("jsp.error.xml.invalidCharInPI",
Integer.toHexString(c));
scanChar();
}
}
} while (scanData("?>", fStringBuffer));
}
data.setValues(fStringBuffer);
}
// Adapted from:
// org.apache.xerces.impl.XMLScanner.scanSurrogates
/**
* Scans surrogates and append them to the specified buffer.
* <p>
* <strong>Note:</strong> This assumes the current char has already been
* identified as a high surrogate.
*
* @param buf The StringBuffer to append the read surrogates to.
* @returns True if it succeeded.
*/
private boolean scanSurrogates(XMLStringBuffer buf)
throws IOException, JasperException {
int high = scanChar();
int low = peekChar();
if (!XMLChar.isLowSurrogate(low)) {
err.jspError("jsp.error.xml.invalidCharInContent",
Integer.toString(high, 16));
return false;
}
scanChar();
// convert surrogates to supplemental character
int c = XMLChar.supplemental((char)high, (char)low);
// supplemental character must be a valid XML character
if (!XMLChar.isValid(c)) {
err.jspError("jsp.error.xml.invalidCharInContent",
Integer.toString(c, 16));
return false;
}
// fill in the buffer
buf.append((char)high);
buf.append((char)low);
return true;
}
// Adapted from:
// org.apache.xerces.impl.XMLScanner.reportFatalError
/**
* Convenience function used in all XML scanners.
*/
private void reportFatalError(String msgId, String arg)
throws JasperException {
err.jspError(msgId, arg);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -