📄 xmlelement.java
字号:
* @param key Description of Parameter
*/
public void removeChild(String key) {
if (this.ignoreCase) {
key = key.toUpperCase();
}
this.attributes.remove(key);
}
/**
* Writes the XML element to a string.
*
* @return Description of the Returned Value
*/
public String toString() {
StringWriter writer = new StringWriter();
this.write(writer);
return writer.toString();
}
/**
* Writes the XML element to a writer.
*
* @param writer Description of Parameter
*/
public void write(Writer writer) {
this.write(writer, 0);
}
/**
* Writes the XML element to a writer.
*
* @param writer Description of Parameter
* @param indent Description of Parameter
*/
public void write(Writer writer,
int indent) {
PrintWriter out = new PrintWriter(writer);
for (int i = 0; i < indent; i++) {
out.print(' ');
}
if (this.tagName == null) {
this.writeEncoded(out, this.contents);
return;
}
out.print('<');
out.print(this.tagName);
if (!this.attributes.isEmpty()) {
Enumeration enum = this.attributes.keys();
while (enum.hasMoreElements()) {
out.print(' ');
String key = (String) (enum.nextElement());
String value = (String) (this.attributes.get(key));
out.print(key);
out.print("=\"");
this.writeEncoded(out, value);
out.print('"');
}
}
if ((this.contents != null) && (this.contents.length() > 0)) {
if (this.skipLeadingWhitespace) {
out.println('>');
for (int i = 0; i < indent + 4; i++) {
out.print(' ');
}
out.println(this.contents);
for (int i = 0; i < indent; i++) {
out.print(' ');
}
}
else {
out.print('>');
this.writeEncoded(out, this.contents);
}
out.print("</");
out.print(this.tagName);
out.println('>');
}
else if (this.children.isEmpty()) {
out.println("/>");
}
else {
out.println('>');
Enumeration enum = this.enumerateChildren();
while (enum.hasMoreElements()) {
XMLElement child = (XMLElement) (enum.nextElement());
child.write(writer, indent + 4);
}
for (int i = 0; i < indent; i++) {
out.print(' ');
}
out.print("</");
out.print(this.tagName);
out.println('>');
}
}
/**
* !!! Searches the content for child objects. If such objects exist, the
* content is reduced to <CODE>null</CODE>.
*
* @param input Description of Parameter
* @param contentOffset Description of Parameter
* @param contentSize Description of Parameter
* @param contentLineNr Description of Parameter
* @exception XMLParseException Description of Exception
* @see nanoxml.XMLElement#parseCharArray
*/
protected void scanChildren(char[] input,
int contentOffset,
int contentSize,
int contentLineNr)
throws XMLParseException {
int end = contentOffset + contentSize;
int offset = contentOffset;
int lineNr[] = new int[1];
lineNr[0] = contentLineNr;
while (offset < end) {
try {
offset = this.skipWhitespace(input, offset, end, lineNr);
} catch (XMLParseException e) {
return;
}
if ((input[offset] != '<')
|| ((input[offset + 1] == '!') && (input[offset + 2] == '['))) {
return;
}
XMLElement child = this.createAnotherElement();
offset = child.parseCharArray(input, offset, end, lineNr);
this.children.addElement(child);
}
}
/**
* Creates a new XML element.
*
* @return Description of the Returned Value
*/
protected XMLElement createAnotherElement() {
return new XMLElement(this.conversionTable,
this.skipLeadingWhitespace,
false,
this.ignoreCase);
}
/**
* Skips a tag that don't contain any useful data: <?...?>, <!...>
* and comments.
*
* @param input Description of Parameter
* @param offset Description of Parameter
* @param end Description of Parameter
* @param lineNr Description of Parameter
* @return the position after the tag
*/
protected int skipBogusTag(char[] input,
int offset,
int end,
int[] lineNr) {
int level = 1;
while (offset < end) {
char ch = input[offset++];
switch (ch) {
case '\r':
if ((offset < end) && (input[offset] == '\n')) {
offset++;
}
lineNr[0]++;
break;
case '\n':
lineNr[0]++;
break;
case '<':
level++;
break;
case '>':
level--;
if (level == 0) {
return offset;
}
break;
default:
}
}
throw this.unexpectedEndOfData(lineNr[0]);
}
/**
* Converts &...; sequences to "normal" chars.
*
* @param s Description of Parameter
* @param lineNr Description of Parameter
* @return Description of the Returned Value
*/
protected String decodeString(String s,
int lineNr) {
StringBuffer result = new StringBuffer(s.length());
int index = 0;
while (index < s.length()) {
int index2 = (s + '&').indexOf('&', index);
int index3 = (s + "<![CDATA[").indexOf("<![CDATA[", index);
if (index2 <= index3) {
result.append(s.substring(index, index2));
if (index2 == s.length()) {
break;
}
index = s.indexOf(';', index2);
if (index < 0) {
result.append(s.substring(index2));
break;
}
String key = s.substring(index2 + 1, index);
if (key.charAt(0) == '#') {
if (key.charAt(1) == 'x') {
result.append((char) (
Integer.parseInt(key.substring(2),
16)));
}
else {
result.append((char) (
Integer.parseInt(key.substring(1),
10)));
}
}
else {
result.append(this.conversionTable
.getProperty(key, "&" + key + ';'));
}
}
else {
int index4 = (s + "]]>").indexOf("]]>", index3 + 9);
result.append(s.substring(index, index3));
result.append(s.substring(index3 + 9, index4));
index = index4 + 2;
}
index++;
}
return result.toString();
}
/**
* Writes a string encoded to a writer.
*
* @param out Description of Parameter
* @param str Description of Parameter
*/
protected void writeEncoded(PrintWriter out,
String str) {
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
switch (ch) {
case '<':
out.write("<");
break;
case '>':
out.write(">");
break;
case '&':
out.write("&");
break;
case '"':
out.write(""");
break;
case '\'':
out.write("'");
break;
case '\r':
case '\n':
out.write(ch);
break;
default:
if (((int) ch < 32) || ((int) ch > 126)) {
out.write("&#x");
out.write(Integer.toString((int) ch, 16));
out.write(';');
}
else {
out.write(ch);
}
}
}
}
/**
* Checks whether a character may be part of an identifier.
*
* @param ch Description of Parameter
* @return The IdentifierChar value
*/
private boolean isIdentifierChar(char ch) {
return (((ch >= 'A') && (ch <= 'Z')) || ((ch >= 'a') && (ch <= 'z'))
|| ((ch >= '0') && (ch <= '9')) || (".-_:".indexOf(ch) >= 0));
}
/**
* Parses an XML definition starting at <I>offset</I> .
*
* @param input Description of Parameter
* @param offset Description of Parameter
* @param end Description of Parameter
* @param currentLineNr Description of Parameter
* @return the offset of the array following the
* XML data (<= end)
* @exception XMLParseException Description of Exception
*/
private int parseCharArray(char[] input,
int offset,
int end,
int[] currentLineNr)
throws XMLParseException {
this.lineNr = currentLineNr[0];
this.tagName = null;
this.contents = null;
this.attributes = new Properties();
this.children = new Vector();
try {
offset = this.skipWhitespace(input, offset, end, currentLineNr);
} catch (XMLParseException e) {
return offset;
}
offset = this.skipPreamble(input, offset, end, currentLineNr);
offset = this.scanTagName(input, offset, end, currentLineNr);
this.lineNr = currentLineNr[0];
offset = this.scanAttributes(input, offset, end, currentLineNr);
int[] contentOffset = new int[1];
int[] contentSize = new int[1];
int contentLineNr = currentLineNr[0];
offset = this.scanContent(input, offset, end,
contentOffset, contentSize, currentLineNr);
if (contentSize[0] > 0) {
this.scanChildren(input, contentOffset[0], contentSize[0],
contentLineNr);
if (this.children.size() > 0) {
this.contents = null;
}
else {
this.processContents(input, contentOffset[0],
contentSize[0], contentLineNr);
for (int i = 0; i < contentSize[0]; i++) {
if (input[contentOffset[0] + i] > ' ') {
return offset;
}
}
this.contents = null;
}
}
return offset;
}
/**
* Decodes the entities in the contents and, if skipLeadingWhitespace is
* <CODE>true</CODE>, removes extraneous whitespaces after newlines and
* convert those newlines into spaces.
*
* @param input Description of Parameter
* @param contentOffset Description of Parameter
* @param contentSize Description of Parameter
* @param contentLineNr Description of Parameter
* @exception XMLParseException Description of Exception
* @see nanoxml.XMLElement#decodeString
*/
private void processContents(char[] input,
int contentOffset,
int contentSize,
int contentLineNr)
throws XMLParseException {
int[] lineNr = new int[1];
lineNr[0] = contentLineNr;
if (!this.skipLeadingWhitespace) {
String str = new String(input, contentOffset, contentSize);
this.contents = this.decodeString(str, lineNr[0]);
return;
}
StringBuffer result = new StringBuffer(contentSize);
int end = contentSize + contentOffset;
for (int i = contentOffset; i < end; i++) {
char ch = input[i];
// The end of the contents is always a < character, so there's
// no danger for bounds violation
while ((ch == '\r') || (ch == '\n')) {
lineNr[0]++;
result.append(ch);
i++;
ch = input[i];
if (ch != '\n') {
result.append(ch);
}
do {
i++;
ch = input[i];
} while ((ch == ' ') || (ch == '\t'));
}
if (i < end) {
result.append(ch);
}
}
this.contents = this.decodeString(result.toString(), lineNr[0]);
}
/**
* Scans the attributes of the object.
*
* @param input Description of Parameter
* @param offset Description of Parameter
* @param end Description of Parameter
* @param lineNr Description of Parameter
* @return the offset in the string following
* the attributes, so that input[offset] in { '/', '>' }
* @exception XMLParseException Description of Exception
* @see nanoxml.XMLElement#scanOneAttribute
*/
private int scanAttributes(char[] input,
int offset,
int end,
int[] lineNr)
throws XMLParseException {
// String key;
// String value;
for (; ; ) {
offset = this.skipWhitespace(input, offset, end, lineNr);
char ch = input[offset];
if ((ch == '/') || (ch == '>')) {
break;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -