XML轉化為json工具類
阿新 • • 發佈:2018-12-28
用法如下:
String xmlStr = "xxxxxxxx";
JSONObject jSONObject = new XmlToJson.Builder(xmlStr).build().toJson();
String msg = jSONObject.getJSONObject("msg")
Utils.print(msg);
Xml轉換json原始碼:
import android.support.annotation.NonNull; import android.support.annotation.Nullable; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserFactory; import java.io.IOException; import java.io.InputStream; import java.io.StringReader; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.regex.Matcher; public class XmlToJson { private static final String DEFAULT_CONTENT_NAME = "content"; private static final String DEFAULT_ENCODING = "utf-8"; private static final String DEFAULT_INDENTATION = " "; private String mIndentationPattern = DEFAULT_INDENTATION; // default values when a Tag is empty private static final String DEFAULT_EMPTY_STRING = ""; private static final int DEFAULT_EMPTY_INTEGER = 0; private static final long DEFAULT_EMPTY_LONG = 0; private static final double DEFAULT_EMPTY_DOUBLE = 0; private static final boolean DEFAULT_EMPTY_BOOLEAN = false; /** * 建立一個xmltojsons物件 */ public static class Builder { private StringReader mStringSource; private InputStream mInputStreamSource; private String mInputEncoding = DEFAULT_ENCODING; private HashSet<String> mForceListPaths = new HashSet<>(); private HashMap<String, String> mAttributeNameReplacements = new HashMap<>(); private HashMap<String, String> mContentNameReplacements = new HashMap<>(); private HashMap<String, Class> mForceClassForPath = new HashMap<>(); // Integer, Long, Double, Boolean private HashSet<String> mSkippedAttributes = new HashSet<>(); private HashSet<String> mSkippedTags = new HashSet<>(); public Builder(@NonNull String xmlSource) { mStringSource = new StringReader(xmlSource); } public Builder(@NonNull InputStream inputStreamSource, @Nullable String inputEncoding) { mInputStreamSource = inputStreamSource; mInputEncoding = (inputEncoding != null) ? inputEncoding : DEFAULT_ENCODING; } public Builder forceList(@NonNull String path) { mForceListPaths.add(path); return this; } public Builder setAttributeName(@NonNull String attributePath, @NonNull String replacementName) { mAttributeNameReplacements.put(attributePath, replacementName); return this; } public Builder setContentName(@NonNull String contentPath, @NonNull String replacementName) { mContentNameReplacements.put(contentPath, replacementName); return this; } public Builder forceIntegerForPath(@NonNull String path) { mForceClassForPath.put(path, Integer.class); return this; } public Builder forceLongForPath(@NonNull String path) { mForceClassForPath.put(path, Long.class); return this; } public Builder forceDoubleForPath(@NonNull String path) { mForceClassForPath.put(path, Double.class); return this; } public Builder forceBooleanForPath(@NonNull String path) { mForceClassForPath.put(path, Boolean.class); return this; } public Builder skipTag(@NonNull String path) { mSkippedTags.add(path); return this; } public Builder skipAttribute(@NonNull String path) { mSkippedAttributes.add(path); return this; } public XmlToJson build() { return new XmlToJson(this); } } private StringReader mStringSource; private InputStream mInputStreamSource; private String mInputEncoding; private HashSet<String> mForceListPaths; private HashMap<String, String> mAttributeNameReplacements; private HashMap<String, String> mContentNameReplacements; private HashMap<String, Class> mForceClassForPath; private HashSet<String> mSkippedAttributes = new HashSet<>(); private HashSet<String> mSkippedTags = new HashSet<>(); private JSONObject mJsonObject; // Used for caching the result private XmlToJson(Builder builder) { mStringSource = builder.mStringSource; mInputStreamSource = builder.mInputStreamSource; mInputEncoding = builder.mInputEncoding; mForceListPaths = builder.mForceListPaths; mAttributeNameReplacements = builder.mAttributeNameReplacements; mContentNameReplacements = builder.mContentNameReplacements; mForceClassForPath = builder.mForceClassForPath; mSkippedAttributes = builder.mSkippedAttributes; mSkippedTags = builder.mSkippedTags; mJsonObject = convertToJSONObject(); // Build now so that the InputStream can be closed just after } /** * @return the JSONObject built from the XML */ public @Nullable JSONObject toJson() { return mJsonObject; } private @Nullable JSONObject convertToJSONObject() { try { Tag parentTag = new Tag("", "xml"); XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); factory.setNamespaceAware(false); // tags with namespace are taken as-is ("namespace:tagname") XmlPullParser xpp = factory.newPullParser(); setInput(xpp); int eventType = xpp.getEventType(); while (eventType != XmlPullParser.START_DOCUMENT) { eventType = xpp.next(); } readTags(parentTag, xpp); unsetInput(); return convertTagToJson(parentTag, false); } catch (Exception e) { Utils.print(e); return null; } } private void setInput(XmlPullParser xpp) { if (mStringSource != null) { try { xpp.setInput(mStringSource); } catch (XmlPullParserException e) { Utils.print(e); } } else { try { xpp.setInput(mInputStreamSource, mInputEncoding); } catch (XmlPullParserException e) { Utils.print(e); } } } private void unsetInput() { if (mStringSource != null) { mStringSource.close(); } // else the InputStream has been given by the user, it is not our role to close it } private void readTags(Tag parent, XmlPullParser xpp) { try { int eventType; do { eventType = xpp.next(); if (eventType == XmlPullParser.START_TAG) { String tagName = xpp.getName(); String path = parent.getPath() + "/" + tagName; boolean skipTag = mSkippedTags.contains(path); Tag child = new Tag(path, tagName); if (!skipTag) { parent.addChild(child); } // Attributes are taken into account as key/values in the child int attrCount = xpp.getAttributeCount(); for (int i = 0; i < attrCount; ++i) { String attrName = xpp.getAttributeName(i); String attrValue = xpp.getAttributeValue(i); String attrPath = parent.getPath() + "/" + child.getName() + "/" + attrName; // Skip Attributes if (mSkippedAttributes.contains(attrPath)) { continue; } attrName = getAttributeNameReplacement(attrPath, attrName); Tag attribute = new Tag(attrPath, attrName); attribute.setContent(attrValue); child.addChild(attribute); } readTags(child, xpp); } else if (eventType == XmlPullParser.TEXT) { String text = xpp.getText(); parent.setContent(text); } else if (eventType == XmlPullParser.END_TAG) { return; } else if (eventType == XmlPullParser.END_DOCUMENT) { return; } else { Utils.print("unknown xml eventType " + eventType); } } while (eventType != XmlPullParser.END_DOCUMENT); } catch (XmlPullParserException | IOException | NullPointerException e) { Utils.print(e); } } private JSONObject convertTagToJson(Tag tag, boolean isListElement) { JSONObject json = new JSONObject(); // Content is injected as a key/value if (tag.getContent() != null) { String path = tag.getPath(); String name = getContentNameReplacement(path, DEFAULT_CONTENT_NAME); putContent(path, json, name, tag.getContent()); } try { HashMap<String, ArrayList<Tag>> groups = tag.getGroupedElements(); // groups by tag names so that we can detect lists or single elements for (ArrayList<Tag> group : groups.values()) { if (group.size() == 1) { // element, or list of 1 Tag child = group.get(0); if (isForcedList(child)) { // list of 1 JSONArray list = new JSONArray(); list.put(convertTagToJson(child, true)); String childrenNames = child.getName(); json.put(childrenNames, list); } else { // stand alone element if (child.hasChildren()) { JSONObject jsonChild = convertTagToJson(child, false); json.put(child.getName(), jsonChild); } else { String path = child.getPath(); putContent(path, json, child.getName(), child.getContent()); } } } else { // list JSONArray list = new JSONArray(); for (Tag child : group) { list.put(convertTagToJson(child, true)); } String childrenNames = group.get(0).getName(); json.put(childrenNames, list); } } return json; } catch (JSONException e) { Utils.print(e); } return null; } private void putContent(String path, JSONObject json, String tag, String content) { try { // checks if the user wants to force a class (Int, Double... for a given path) Class forcedClass = mForceClassForPath.get(path); if (forcedClass == null) { // default behaviour, put it as a String if (content == null) { content = DEFAULT_EMPTY_STRING; } json.put(tag, content); } else { if (forcedClass == Integer.class) { try { Integer number = Integer.parseInt(content); json.put(tag, number); } catch (NumberFormatException exception) { json.put(tag, DEFAULT_EMPTY_INTEGER); } } else if (forcedClass == Long.class) { try { Long number = Long.parseLong(content); json.put(tag, number); } catch (NumberFormatException exception) { json.put(tag, DEFAULT_EMPTY_LONG); } } else if (forcedClass == Double.class) { try { Double number = Double.parseDouble(content); json.put(tag, number); } catch (NumberFormatException exception) { json.put(tag, DEFAULT_EMPTY_DOUBLE); } } else if (forcedClass == Boolean.class) { if (content == null) { json.put(tag, DEFAULT_EMPTY_BOOLEAN); } else if (content.equalsIgnoreCase("true")) { json.put(tag, true); } else if (content.equalsIgnoreCase("false")) { json.put(tag, false); } else { json.put(tag, DEFAULT_EMPTY_BOOLEAN); } } } } catch (JSONException exception) { // keep continue in case of error } } private boolean isForcedList(Tag tag) { String path = tag.getPath(); return mForceListPaths.contains(path); } private String getAttributeNameReplacement(String path, String defaultValue) { String result = mAttributeNameReplacements.get(path); if (result != null) { return result; } return defaultValue; } private String getContentNameReplacement(String path, String defaultValue) { String result = mContentNameReplacements.get(path); if (result != null) { return result; } return defaultValue; } @Override public String toString() { if (mJsonObject != null) { return mJsonObject.toString(); } return null; } public String toFormattedString(@Nullable String indentationPattern) { if (indentationPattern == null) { mIndentationPattern = DEFAULT_INDENTATION; } else { mIndentationPattern = indentationPattern; } return toFormattedString(); } public String toFormattedString() { if (mJsonObject != null) { String indent = ""; StringBuilder builder = new StringBuilder(); builder.append("{\n"); format(mJsonObject, builder, indent); builder.append("}\n"); return builder.toString(); } return null; } private void format(JSONObject jsonObject, StringBuilder builder, String indent) { Iterator<String> keys = jsonObject.keys(); while (keys.hasNext()) { String key = keys.next(); builder.append(indent); builder.append(mIndentationPattern); builder.append("\""); builder.append(key); builder.append("\": "); Object value = jsonObject.opt(key); if (value instanceof JSONObject) { JSONObject child = (JSONObject) value; builder.append(indent); builder.append("{\n"); format(child, builder, indent + mIndentationPattern); builder.append(indent); builder.append(mIndentationPattern); builder.append("}"); } else if (value instanceof JSONArray) { JSONArray array = (JSONArray) value; formatArray(array, builder, indent + mIndentationPattern); } else { formatValue(value, builder); } if (keys.hasNext()) { builder.append(",\n"); } else { builder.append("\n"); } } } private void formatArray(JSONArray array, StringBuilder builder, String indent) { builder.append("[\n"); for (int i = 0; i < array.length(); ++i) { Object element = array.opt(i); if (element instanceof JSONObject) { JSONObject child = (JSONObject) element; builder.append(indent); builder.append(mIndentationPattern); builder.append("{\n"); format(child, builder, indent + mIndentationPattern); builder.append(indent); builder.append(mIndentationPattern); builder.append("}"); } else if (element instanceof JSONArray) { JSONArray child = (JSONArray) element; formatArray(child, builder, indent + mIndentationPattern); } else { formatValue(element, builder); } if (i < array.length() - 1) { builder.append(","); } builder.append("\n"); } builder.append(indent); builder.append("]"); } private void formatValue(Object value, StringBuilder builder) { if (value instanceof String) { String string = (String) value; // Escape special characters string = string.replaceAll("\\\\", "\\\\\\\\"); // escape backslash string = string.replaceAll("\"", Matcher.quoteReplacement("\\\"")); // escape double quotes string = string.replaceAll("/", "\\\\/"); // escape slash string = string.replaceAll("\n", "\\\\n").replaceAll("\t", "\\\\t"); // escape \n and \t string = string.replaceAll("\r", "\\\\r"); // escape \r builder.append("\""); builder.append(string); builder.append("\""); } else if (value instanceof Long) { Long longValue = (Long) value; builder.append(longValue); } else if (value instanceof Integer) { Integer intValue = (Integer) value; builder.append(intValue); } else if (value instanceof Boolean) { Boolean bool = (Boolean) value; builder.append(bool); } else if (value instanceof Double) { Double db = (Double) value; builder.append(db); } else { builder.append(value.toString()); } } }