📄 xml.java
字号:
package org.json;
import java.util.Iterator;
import java.text.ParseException;
/**
* This provides static methods to convert an XML text into a JSONObject,
* and to covert a JSONObject into an XML text.
* <p>
* Public Domain 2002 JSON.org
* @author JSON.org
* @version 0.2
*/
public class XML {
private XML() {}
/** The Character '&'. */
public static final Character AMP = new Character('&');
/** The Character '''. */
public static final Character APOS = new Character('\'');
/** The Character '!'. */
public static final Character BANG = new Character('!');
/** The Character '='. */
public static final Character EQ = new Character('=');
/** The Character '>'. */
public static final Character GT = new Character('>');
/** The Character '<'. */
public static final Character LT = new Character('<');
/** The Character '?'. */
public static final Character QUEST = new Character('?');
/** The Character '"'. */
public static final Character QUOT = new Character('"');
/** The Character '/'. */
public static final Character SLASH = new Character('/');
/**
* Replace special characters with XML escapes:
* <pre>
* & is replaced by &amp;
* < is replaced by &lt;
* > is replaced by &gt;
* " is replaced by &quot;
* </pre>
* @param string the string to escape
* @return the escaped string
*/
public static String escape(String string) {
return string
.replaceAll("&", "&")
.replaceAll("<", "<")
.replaceAll(">", ">")
.replaceAll("\"", """);
}
/**
* Scan the content following the named tag, attaching it to the context.
* @param x The XMLTokener containing the source string.
* @param context The JSONObject that will include the new material.
* @param name The tag name.
* @return true if the close tag is processed.
* @throws ParseException
*/
private static boolean parse(XMLTokener x, JSONObject context,
String name) throws ParseException {
char c;
int i;
String n;
JSONObject o;
String s;
Object t;
// Test for and skip past these forms:
// <!-- ... -->
// <! ... >
// <![ ... ]]>
// <? ... ?>
// Report errors for these forms:
// <>
// <=
// <<
t = x.nextToken();
// <!
if (t == BANG) {
c = x.next();
if (c == '-') {
if (x.next() == '-') {
x.skipPast("-->");
return false;
}
x.back();
} else if (c == '[') {
x.skipPast("]]>");
return false;
}
i = 1;
do {
t = x.nextMeta();
if (t == null) {
throw x.syntaxError("Missing '>' after '<!'.");
} else if (t == LT) {
i += 1;
} else if (t == GT) {
i -= 1;
}
} while (i > 0);
return false;
} else if (t == QUEST) {
// <?
x.skipPast("?>");
return false;
} else if (t == SLASH) {
// Close tag </
if (name == null || !x.nextToken().equals(name)) {
throw x.syntaxError("Mismatched close tag");
}
if (x.nextToken() != GT) {
throw x.syntaxError("Misshaped close tag");
}
return true;
} else if (t instanceof Character) {
throw x.syntaxError("Misshaped tag");
// Open tag <
} else {
n = (String)t;
t = null;
o = new JSONObject();
while (true) {
if (t == null) {
t = x.nextToken();
}
// attribute = value
if (t instanceof String) {
s = (String)t;
t = x.nextToken();
if (t == EQ) {
t = x.nextToken();
if (!(t instanceof String)) {
throw x.syntaxError("Missing value");
}
o.accumulate(s, t);
t = null;
} else {
o.accumulate(s, Boolean.TRUE);
}
// Empty tag <.../>
} else if (t == SLASH) {
if (x.nextToken() != GT) {
throw x.syntaxError("Misshaped tag");
}
if (o.length() == 0) {
context.accumulate(n, Boolean.TRUE);
} else {
context.accumulate(n, o);
}
return false;
// Content, between <...> and </...>
} else if (t == GT) {
while (true) {
t = x.nextContent();
if (t == null) {
if (name != null) {
throw x.syntaxError("Unclosed tag " + name);
}
return false;
} else if (t instanceof String) {
s = (String)t;
if (s.length() > 0) {
o.accumulate("content", s);
}
// Nested element
} else if (t == LT) {
if (parse(x, o, n)) {
if (o.length() == 0) {
context.accumulate(n, Boolean.TRUE);
} else if (o.length() == 1 &&
o.opt("content") != null) {
context.accumulate(n, o.opt("content"));
} else {
context.accumulate(n, o);
}
return false;
}
}
}
} else {
throw x.syntaxError("Misshaped tag");
}
}
}
}
/**
* Convert a well-formed (but not necessarily valid) XML string into a
* JSONObject. Some information may be lost in this transformation
* because JSON is a data format and XML is a document format. XML uses
* elements, attributes, and content text, while JSON uses unordered
* collections of name/value pairs and arrays of values. JSON does not
* does not like to distinguish between elements and attributes.
* Sequences of similar elements are represented as JSONArrays. Content
* text may be placed in a "content" member. Comments, prologs, DTDs, and
* <code><[ [ ]]></code> are ignored.
* @param string The source string.
* @return A JSONObject containing the structured data from the XML string.
* @throws ParseException
*/
public static JSONObject toJSONObject(String string) throws ParseException {
JSONObject o = new JSONObject();
XMLTokener x = new XMLTokener(string);
while (x.more()) {
x.skipPast("<");
parse(x, o, null);
}
return o;
}
/**
* Convert a JSONObject into a well-formed XML string.
* @param o A JSONObject.
* @return A string.
*/
public static String toString(Object o) {
return toString(o, null);
}
/**
* Convert a JSONObject into a well-formed XML string.
* @param o A JSONObject.
* @param tagName The optional name of the enclosing tag.
* @return A string.
*/
public static String toString(Object o, String tagName) {
StringBuffer a = null; // attributes, inside the <...>
StringBuffer b = new StringBuffer(); // body, between <...> and </...>
int i;
JSONArray ja;
JSONObject jo;
String k;
Iterator keys;
int len;
String s;
Object v;
if (o instanceof JSONObject) {
// Emit <tagName
if (tagName != null) {
a = new StringBuffer();
a.append('<');
a.append(tagName);
}
// Loop thru the keys. Some keys will produce attribute material, others
// body material.
jo = (JSONObject)o;
keys = jo.keys();
while (keys.hasNext()) {
k = keys.next().toString();
v = jo.get(k);
if (v instanceof String) {
s = (String)v;
} else {
s = null;
}
// Emit a new tag <k... in body
if (tagName == null || v instanceof JSONObject ||
(s != null && k != "content" && (s.length() > 60 ||
(s.indexOf('"') >= 0 && s.indexOf('\'') >= 0)))) {
b.append(toString(v, k));
// Emit content in body
} else if (k.equals("content")) {
b.append(escape(v.toString()));
// Emit an array of similar keys in body
} else if (v instanceof JSONArray) {
ja = (JSONArray)v;
len = ja.length();
for (i = 0; i < len; i += 1) {
b.append(toString(ja.get(i), k));
}
// Emit an attribute
} else {
a.append(' ');
a.append(k);
a.append('=');
a.append(toString(v));
}
}
if (tagName != null) {
// Close an empty element
if (b.length() == 0) {
a.append("/>");
} else {
// Close the start tag and emit the body and the close tag
a.append('>');
a.append(b);
a.append("</");
a.append(tagName);
a.append('>');
}
return a.toString();
}
return b.toString();
// XML does not have good support for arrays. If an array appears in a place
// where XML is lacking, synthesize an <array> element.
} else if (o instanceof JSONArray) {
ja = (JSONArray)o;
len = ja.length();
for (i = 0; i < len; ++i) {
b.append(toString(
ja.opt(i), (tagName == null) ? "array" : tagName));
}
return b.toString();
} else {
s = (o == null) ? "null" : escape(o.toString());
return (tagName == null) ?
"\"" + s + "\"" :
"<" + tagName + ">" + s + "</" + tagName + ">";
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -