All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.junya.http.json.XML Maven / Gradle / Ivy

package com.junya.http.json;

import com.junya.core.util.ArrayUtil;
import com.junya.core.util.CharUtil;
import com.junya.core.util.StringUtil;
import com.junya.core.util.XmlUtil;

import java.util.Iterator;

/**
 * 提供静态方法在XML和JSONObject之间转换
 * 
 * @author JSON.org
 */
public class XML {

	/** The Character '&'. */
	public static final Character AMP = CharUtil.AMP;

	/** The Character '''. */
	public static final Character APOS = CharUtil.SINGLE_QUOTE;

	/** The Character '!'. */
	public static final Character BANG = '!';

	/** The Character '='. */
	public static final Character EQ = '=';

	/** The Character '>'. */
	public static final Character GT = '>';

	/** The Character '<'. */
	public static final Character LT = '<';

	/** The Character '?'. */
	public static final Character QUEST = '?';

	/** The Character '"'. */
	public static final Character QUOT = CharUtil.DOUBLE_QUOTES;

	/** The Character '/'. */
	public static final Character SLASH = CharUtil.SLASH;

	/**
	 * 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 JSONException JSON异常
	 */
	private static boolean parse(XMLTokener x, JSONObject context, String name, boolean keepStrings) throws JSONException {
		char c;
		int i;
		JSONObject jsonobject;
		String string;
		String tagName;
		Object token;

		// Test for and skip past these forms:
		// 
		// 
		// 
		// 
		// Report errors for these forms:
		// <>
		// <=
		// <<

		token = x.nextToken();

		// ");
					return false;
				}
				x.back();
			} else if (c == '[') {
				token = x.nextToken();
				if ("CDATA".equals(token)) {
					if (x.next() == '[') {
						string = x.nextCDATA();
						if (string.length() > 0) {
							context.accumulate("content", string);
						}
						return false;
					}
				}
				throw x.syntaxError("Expected 'CDATA['");
			}
			i = 1;
			do {
				token = x.nextMeta();
				if (token == null) {
					throw x.syntaxError("Missing '>' after ' 0);
			return false;
		} else if (token == QUEST) {

			// ");
			return false;
		} else if (token == SLASH) {

			// Close tag 
					if (x.nextToken() != GT) {
						throw x.syntaxError("Misshaped tag");
					}
					if (jsonobject.size() > 0) {
						context.accumulate(tagName, jsonobject);
					} else {
						context.accumulate(tagName, "");
					}
					return false;

				} else if (token == GT) {
					// Content, between <...> and 
					for (;;) {
						token = x.nextContent();
						if (token == null) {
							if (tagName != null) {
								throw x.syntaxError("Unclosed tag " + tagName);
							}
							return false;
						} else if (token instanceof String) {
							string = (String) token;
							if (string.length() > 0) {
								jsonobject.accumulate("content", keepStrings ? token : InternalJSONUtil.stringToValue(string));
							}

						} else if (token == LT) {
							// Nested element
							if (parse(x, jsonobject, tagName, keepStrings)) {
								if (jsonobject.size() == 0) {
									context.accumulate(tagName, "");
								} else if (jsonobject.size() == 1 && jsonobject.get("content") != null) {
									context.accumulate(tagName, jsonobject.get("content"));
								} else {
									context.accumulate(tagName, jsonobject);
								}
								return false;
							}
						}
					}
				} else {
					throw x.syntaxError("Misshaped tag");
				}
			}
		}
	}

	/**
	 * 转换XML为JSONObject
	 * 转换过程中一些信息可能会丢失,JSON中无法区分节点和属性,相同的节点将被处理为JSONArray。
	 * Content text may be placed in a "content" member. Comments, prologs, DTDs, and <[ [ ]]> are ignored.
	 * 
	 * @param string The source string.
	 * @return A JSONObject containing the structured data from the XML string.
	 * @throws JSONException Thrown if there is an errors while parsing the string
	 */
	public static JSONObject toJSONObject(String string) throws JSONException {
		return toJSONObject(string, false);
	}

	/**
	 * 转换XML为JSONObject
	 * 转换过程中一些信息可能会丢失,JSON中无法区分节点和属性,相同的节点将被处理为JSONArray。
	 * Content text may be placed in a "content" member. Comments, prologs, DTDs, and <[ [ ]]> are ignored.
	 * All values are converted as strings, for 1, 01, 29.0 will not be coerced to numbers but will instead be the exact value as seen in the XML document.
	 * 
	 * @param string The source string.
	 * @param keepStrings If true, then values will not be coerced into boolean or numeric values and will instead be left as strings
	 * @return A JSONObject containing the structured data from the XML string.
	 * @throws JSONException Thrown if there is an errors while parsing the string
	 */
	public static JSONObject toJSONObject(String string, boolean keepStrings) throws JSONException {
		JSONObject jo = new JSONObject();
		XMLTokener x = new XMLTokener(string);
		while (x.more() && x.skipPast("<")) {
			parse(x, jo, null, keepStrings);
		}
		return jo;
	}

	/**
	 * 转换JSONObject为XML
	 * Convert a JSONObject into a well-formed, element-normal XML string.
	 * 
	 * @param object A JSONObject.
	 * @return A string.
	 * @throws JSONException Thrown if there is an error parsing the string
	 */
	public static String toXml(Object object) throws JSONException {
		return toXml(object, null);
	}

	/**
	 * 转换JSONObject为XML
	 * Convert a JSONObject into a well-formed, element-normal XML string.
	 * 
	 * @param object A JSONObject.
	 * @param tagName The optional name of the enclosing tag.
	 * @return A string.
	 * @throws JSONException Thrown if there is an error parsing the string
	 */
	public static String toXml(Object object, String tagName) throws JSONException {
		if(null == object) {
			return null;
		}
		
		StringBuilder sb = new StringBuilder();
		JSONArray ja;
		JSONObject jo;
		String key;
		Iterator keys;
		Object value;

		if (object instanceof JSONObject) {

			// Emit 
			if (tagName != null) {
				sb.append('<');
				sb.append(tagName);
				sb.append('>');
			}

			// Loop thru the keys.
			jo = (JSONObject) object;
			keys = jo.keySet().iterator();
			while (keys.hasNext()) {
				key = keys.next();
				value = jo.get(key);
				if (value == null) {
					value = StringUtil.EMPTY;
				} else if (ArrayUtil.isArray(value)) {
					value = new JSONArray(value);
				}

				// Emit content in body
				if ("content".equals(key)) {
					if (value instanceof JSONArray) {
						ja = (JSONArray) value;
						int i = 0;
						for (Object val : ja) {
							if (i > 0) {
								sb.append('\n');
							}
							sb.append(XmlUtil.escape(val.toString()));
							i++;
						}
					} else {
						sb.append(XmlUtil.escape(value.toString()));
					}

					// Emit an array of similar keys

				} else if (value instanceof JSONArray) {
					ja = (JSONArray) value;
					for (Object val : ja) {
						if (val instanceof JSONArray) {
							sb.append('<');
							sb.append(key);
							sb.append('>');
							sb.append(toXml(val));
							sb.append("');
						} else {
							sb.append(toXml(val, key));
						}
					}
				} else if ("".equals(value)) {
					sb.append('<');
					sb.append(key);
					sb.append("/>");

					// Emit a new tag 

				} else {
					sb.append(toXml(value, key));
				}
			}
			if (tagName != null) {

				// Emit the  close tag
				sb.append("');
			}
			return sb.toString();

		}

		if (object != null) {
			if (object.getClass().isArray()) {
				object = new JSONArray(object);
			}

			if (object instanceof JSONArray) {
				ja = (JSONArray) object;
				for (Object val : ja) {
					// XML does not have good support for arrays. If an array
					// appears in a place where XML is lacking, synthesize an
					//  element.
					sb.append(toXml(val, tagName == null ? "array" : tagName));
				}
				return sb.toString();
			}
		}

		String string = (object == null) ? StringUtil.NULL : XmlUtil.escape(object.toString());
		return (tagName == null) ?
				"\"" + string + "\"" : (string.length() == 0) ? "<" + tagName + "/>"
				: "<" + tagName + ">" + string + "";

	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy