📄 xmlreader.java
字号:
}
if (c == -1) {
exception(UNEXPECTED_EOF);
}
String attrName = readName();
if (attrName.length() == 0) {
exception("attr name expected");
}
skip();
read('=');
skip();
int delimiter = read();
if (delimiter != '\'' && delimiter != '"') {
if (!relaxed) {
exception(
"<"
+ name
+ ">: invalid delimiter: "
+ (char) delimiter);
}
delimiter = ' ';
}
int i = (attributeCount++) << 1;
attributes = ensureCapacity(attributes, i + 4);
attributes[i++] = attrName;
int p = txtPos;
pushText(delimiter);
attributes[i] = pop(p);
if (delimiter != ' ') {
read(); // skip endquote
}
}
}
/** result: isWhitespace; if the setName parameter is set,
the name of the entity is stored in "name" */
public final boolean pushEntity() throws IOException {
read(); // &
int pos = txtPos;
while (!eof && peek0 != ';') {
push(read());
}
String code = pop(pos);
read();
if (code.length() > 0 && code.charAt(0) == '#') {
int c =
(code.charAt(1) == 'x'
? Integer.parseInt(code.substring(2), 16)
: Integer.parseInt(code.substring(1)));
push(c);
return c <= ' ';
}
String result = (String) entityMap.get(code);
boolean whitespace = true;
if (result == null) {
result = "&" + code + ";";
}
for (int i = 0; i < result.length(); i++) {
char c = result.charAt(i);
if (c > ' ') {
whitespace = false;
}
push(c);
}
return whitespace;
}
/** types:
'<': parse to any token (for nextToken ())
'"': parse to quote
' ': parse to whitespace or '>'
*/
private final boolean pushText(int delimiter) throws IOException {
boolean whitespace = true;
int next = peek0;
while (!eof
&& next != delimiter) { // covers eof, '<', '"'
if (delimiter == ' ') {
if (next <= ' ' || next == '>') {
break;
}
}
if (next == '&') {
if (!pushEntity()) {
whitespace = false;
}
} else {
if (next > ' ') {
whitespace = false;
}
push(read());
}
next = peek0;
}
return whitespace;
}
//--------------- public part starts here... ---------------
public XmlReader(Reader reader) throws IOException {
this.reader = reader;
//peek0 = reader.read();
//peek1 = reader.read();
eof = peek0 == -1;
entityMap = new Hashtable();
entityMap.put("amp", "&");
entityMap.put("apos", "'");
entityMap.put("gt", ">");
entityMap.put("lt", "<");
entityMap.put("quot", "\"");
line = 1;
column = 1;
}
public void defineCharacterEntity(
String entity,
String value) {
entityMap.put(entity, value);
}
public int getDepth() {
return depth;
}
public String getPositionDescription() {
StringBuffer buf =
new StringBuffer(
type < TYPES.length ? TYPES[type] : "Other");
buf.append(" @" + line + ":" + column + ": ");
if (type == START_TAG || type == END_TAG) {
buf.append('<');
if (type == END_TAG) {
buf.append('/');
}
buf.append(name);
buf.append('>');
} else if (isWhitespace) {
buf.append("[whitespace]");
} else {
buf.append(getText());
}
return buf.toString();
}
public int getLineNumber() {
return line;
}
public int getColumnNumber() {
return column;
}
public boolean isWhitespace() {
return isWhitespace;
}
public String getText() {
if (text == null) {
text = pop(0);
}
return text;
}
public String getName() {
return name;
}
public boolean isEmptyElementTag() {
return degenerated;
}
public int getAttributeCount() {
return attributeCount;
}
public String getAttributeName(int index) {
if (index >= attributeCount) {
throw new IndexOutOfBoundsException();
}
return attributes[index << 1];
}
public String getAttributeValue(int index) {
if (index >= attributeCount) {
throw new IndexOutOfBoundsException();
}
return attributes[(index << 1) + 1];
}
public String getAttributeValue(String name) {
for (int i = (attributeCount << 1) - 2;
i >= 0;
i -= 2) {
if (attributes[i].equals(name)) {
return attributes[i + 1];
}
}
return null;
}
public int getType() {
return type;
}
public int next() throws IOException {
if (degenerated) {
type = END_TAG;
degenerated = false;
depth--;
return type;
}
txtPos = 0;
isWhitespace = true;
do {
attributeCount = 0;
name = null;
text = null;
type = peekType();
switch (type) {
case ENTITY_REF:
isWhitespace &= pushEntity();
type = TEXT;
break;
case START_TAG:
parseStartTag();
break;
case END_TAG:
parseEndTag();
break;
case END_DOCUMENT:
break;
case TEXT:
isWhitespace &= pushText('<');
break;
case CDSECT:
parseLegacy(true);
isWhitespace = false;
type = TEXT;
break;
default:
parseLegacy(false);
}
} while (type > TEXT
|| type == TEXT
&& peekType() >= TEXT);
isWhitespace &= type == TEXT;
return type;
}
//-----------------------------------------------------------------------------
// utility methods to mak XML parsing easier ...
/**
* test if the current event is of the given type and if the
* name do match. null will match any namespace
* and any name. If the current event is TEXT with isWhitespace()=
* true, and the required type is not TEXT, next () is called prior
* to the test. If the test is not passed, an exception is
* thrown. The exception text indicates the parser position,
* the expected event and the current event (not meeting the
* requirement.
*
* <p>essentially it does this
* <pre>
* if (getType() == TEXT && type != TEXT && isWhitespace ())
* next ();
*
* if (type != getType
* || (name != null && !name.equals (getName ())
* throw new XmlPullParserException ( "....");
* </pre>
*/
public void require(int type, String name) throws IOException {
if (this.type == TEXT && type != TEXT && isWhitespace()) {
next();
}
if (type != this.type
|| (name != null && !name.equals(getName()))) {
exception("expected: " + TYPES[type] + "/" + name);
}
}
/**
* If the current event is text, the value of getText is
* returned and next() is called. Otherwise, an empty
* String ("") is returned. Useful for reading element
* content without needing to performing an additional
* check if the element is empty.
*
* <p>essentially it does this
* <pre>
* if (getType != TEXT) return ""
* String result = getText ();
* next ();
* return result;
* </pre>
*/
public String readText() throws IOException {
if (type != TEXT) {
return "";
}
String result = getText();
next();
return result;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -