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

org.json.JSONML Maven / Gradle / Ivy

package org.json;

/*
Public Domain.
*/

/**
 * This provides static methods to convert an XML text into a JSONArray or
 * JSONObject, and to covert a JSONArray or JSONObject into an XML text using
 * the JsonML transform.
 *
 * @author JSON.org
 * @version 2016-01-30
 */
public class JSONML {
    /**
     * Parse XML values and store them in a JSONArray.
     * @param x       The XMLTokener containing the source string.
     * @param arrayForm true if array form, false if object form.
     * @param ja      The JSONArray that is containing the current tag or null
     *     if we are at the outermost level.
     * @param keepStrings	Don't type-convert text nodes and attribute values
     * @return A JSONArray if the value is the outermost tag, otherwise null.
     * @throws JSONException if a parsing error occurs
     */
    private static Object parse(
        XMLTokener x,
        boolean    arrayForm,
        JSONArray  ja,
        boolean keepStrings,
        int currentNestingDepth
    ) throws JSONException {
        return parse(x,arrayForm, ja,
            keepStrings ? JSONMLParserConfiguration.KEEP_STRINGS : JSONMLParserConfiguration.ORIGINAL,
            currentNestingDepth);
    }

    /**
     * Parse XML values and store them in a JSONArray.
     * @param x       The XMLTokener containing the source string.
     * @param arrayForm true if array form, false if object form.
     * @param ja      The JSONArray that is containing the current tag or null
     *     if we are at the outermost level.
     * @param config  The parser configuration:
     *     JSONMLParserConfiguration.ORIGINAL is the default behaviour;
     *     JSONMLParserConfiguration.KEEP_STRINGS means Don't type-convert text nodes and attribute values.
     * @return A JSONArray if the value is the outermost tag, otherwise null.
     * @throws JSONException if a parsing error occurs
     */
    private static Object parse(
        XMLTokener x,
        boolean    arrayForm,
        JSONArray  ja,
        JSONMLParserConfiguration config,
        int currentNestingDepth
    ) throws JSONException {
        String     attribute;
        char       c;
        String     closeTag = null;
        int        i;
        JSONArray  newja = null;
        JSONObject newjo = null;
        Object     token;
        String     tagName = null;

// Test for and skip past these forms:
//      
//      
//      
//      

        while (true) {
            if (!x.more()) {
                throw x.syntaxError("Bad XML");
            }
            token = x.nextContent();
            if (token == XML.LT) {
                token = x.nextToken();
                if (token instanceof Character) {
                    if (token == XML.SLASH) {

// Close tag ");
                            } else {
                                x.back();
                            }
                        } else if (c == '[') {
                            token = x.nextToken();
                            if (token.equals("CDATA") && x.next() == '[') {
                                if (ja != null) {
                                    ja.put(x.nextCDATA());
                                }
                            } else {
                                throw x.syntaxError("Expected 'CDATA['");
                            }
                        } else {
                            i = 1;
                            do {
                                token = x.nextMeta();
                                if (token == null) {
                                    throw x.syntaxError("Missing '>' after ' 0);
                        }
                    } else if (token == XML.QUEST) {

// ");
                    } else {
                        throw x.syntaxError("Misshaped tag");
                    }

// Open tag <

                } else {
                    if (!(token instanceof String)) {
                        throw x.syntaxError("Bad tagName '" + token + "'.");
                    }
                    tagName = (String)token;
                    newja = new JSONArray();
                    newjo = new JSONObject();
                    if (arrayForm) {
                        newja.put(tagName);
                        if (ja != null) {
                            ja.put(newja);
                        }
                    } else {
                        newjo.put("tagName", tagName);
                        if (ja != null) {
                            ja.put(newjo);
                        }
                    }
                    token = null;
                    for (;;) {
                        if (token == null) {
                            token = x.nextToken();
                        }
                        if (token == null) {
                            throw x.syntaxError("Misshaped tag");
                        }
                        if (!(token instanceof String)) {
                            break;
                        }

// attribute = value

                        attribute = (String)token;
                        if (!arrayForm && ("tagName".equals(attribute) || "childNode".equals(attribute))) {
                            throw x.syntaxError("Reserved attribute.");
                        }
                        token = x.nextToken();
                        if (token == XML.EQ) {
                            token = x.nextToken();
                            if (!(token instanceof String)) {
                                throw x.syntaxError("Missing value");
                            }
                            newjo.accumulate(attribute, config.isKeepStrings() ? ((String)token) :XML.stringToValue((String)token));
                            token = null;
                        } else {
                            newjo.accumulate(attribute, "");
                        }
                    }
                    if (arrayForm && newjo.length() > 0) {
                        newja.put(newjo);
                    }

// Empty tag <.../>

                    if (token == XML.SLASH) {
                        if (x.nextToken() != XML.GT) {
                            throw x.syntaxError("Misshaped tag");
                        }
                        if (ja == null) {
                            if (arrayForm) {
                                return newja;
                            }
                            return newjo;
                        }

// Content, between <...> and 

                    } else {
                        if (token != XML.GT) {
                            throw x.syntaxError("Misshaped tag");
                        }

                        if (currentNestingDepth == config.getMaxNestingDepth()) {
                            throw x.syntaxError("Maximum nesting depth of " + config.getMaxNestingDepth() + " reached");
                        }

                        closeTag = (String)parse(x, arrayForm, newja, config, currentNestingDepth + 1);
                        if (closeTag != null) {
                            if (!closeTag.equals(tagName)) {
                                throw x.syntaxError("Mismatched '" + tagName +
                                        "' and '" + closeTag + "'");
                            }
                            tagName = null;
                            if (!arrayForm && newja.length() > 0) {
                                newjo.put("childNodes", newja);
                            }
                            if (ja == null) {
                                if (arrayForm) {
                                    return newja;
                                }
                                return newjo;
                            }
                        }
                    }
                }
            } else {
                if (ja != null) {
                    ja.put(token instanceof String
                        ? (config.isKeepStrings() ? XML.unescape((String)token) : XML.stringToValue((String)token))
                        : token);
                }
            }
        }
    }


    /**
     * Convert a well-formed (but not necessarily valid) XML string into a
     * JSONArray using the JsonML transform. Each XML tag is represented as
     * a JSONArray in which the first element is the tag name. If the tag has
     * attributes, then the second element will be JSONObject containing the
     * name/value pairs. If the tag contains children, then strings and
     * JSONArrays will represent the child tags.
     * Comments, prologs, DTDs, and 
{@code <[ [ ]]>}
are ignored. * @param string The source string. * @return A JSONArray containing the structured data from the XML string. * @throws JSONException Thrown on error converting to a JSONArray */ public static JSONArray toJSONArray(String string) throws JSONException { return (JSONArray)parse(new XMLTokener(string), true, null, JSONMLParserConfiguration.ORIGINAL, 0); } /** * Convert a well-formed (but not necessarily valid) XML string into a * JSONArray using the JsonML transform. Each XML tag is represented as * a JSONArray in which the first element is the tag name. If the tag has * attributes, then the second element will be JSONObject containing the * name/value pairs. If the tag contains children, then strings and * JSONArrays will represent the child tags. * As opposed to toJSONArray this method does not attempt to convert * any text node or attribute value to any type * but just leaves it as a string. * Comments, prologs, DTDs, and
{@code <[ [ ]]>}
are ignored. * @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 JSONArray containing the structured data from the XML string. * @throws JSONException Thrown on error converting to a JSONArray */ public static JSONArray toJSONArray(String string, boolean keepStrings) throws JSONException { return (JSONArray)parse(new XMLTokener(string), true, null, keepStrings, 0); } /** * Convert a well-formed (but not necessarily valid) XML string into a * JSONArray using the JsonML transform. Each XML tag is represented as * a JSONArray in which the first element is the tag name. If the tag has * attributes, then the second element will be JSONObject containing the * name/value pairs. If the tag contains children, then strings and * JSONArrays will represent the child tags. * As opposed to toJSONArray this method does not attempt to convert * any text node or attribute value to any type * but just leaves it as a string. * Comments, prologs, DTDs, and
{@code <[ [ ]]>}
are ignored. * @param string The source string. * @param config The parser configuration: * JSONMLParserConfiguration.ORIGINAL is the default behaviour; * JSONMLParserConfiguration.KEEP_STRINGS means values will not be coerced into boolean * or numeric values and will instead be left as strings * @return A JSONArray containing the structured data from the XML string. * @throws JSONException Thrown on error converting to a JSONArray */ public static JSONArray toJSONArray(String string, JSONMLParserConfiguration config) throws JSONException { return (JSONArray)parse(new XMLTokener(string), true, null, config, 0); } /** * Convert a well-formed (but not necessarily valid) XML string into a * JSONArray using the JsonML transform. Each XML tag is represented as * a JSONArray in which the first element is the tag name. If the tag has * attributes, then the second element will be JSONObject containing the * name/value pairs. If the tag contains children, then strings and * JSONArrays will represent the child content and tags. * As opposed to toJSONArray this method does not attempt to convert * any text node or attribute value to any type * but just leaves it as a string. * Comments, prologs, DTDs, and
{@code <[ [ ]]>}
are ignored. * @param x An XMLTokener. * @param config The parser configuration: * JSONMLParserConfiguration.ORIGINAL is the default behaviour; * JSONMLParserConfiguration.KEEP_STRINGS means values will not be coerced into boolean * or numeric values and will instead be left as strings * @return A JSONArray containing the structured data from the XML string. * @throws JSONException Thrown on error converting to a JSONArray */ public static JSONArray toJSONArray(XMLTokener x, JSONMLParserConfiguration config) throws JSONException { return (JSONArray)parse(x, true, null, config, 0); } /** * Convert a well-formed (but not necessarily valid) XML string into a * JSONArray using the JsonML transform. Each XML tag is represented as * a JSONArray in which the first element is the tag name. If the tag has * attributes, then the second element will be JSONObject containing the * name/value pairs. If the tag contains children, then strings and * JSONArrays will represent the child content and tags. * As opposed to toJSONArray this method does not attempt to convert * any text node or attribute value to any type * but just leaves it as a string. * Comments, prologs, DTDs, and
{@code <[ [ ]]>}
are ignored. * @param x An XMLTokener. * @param keepStrings If true, then values will not be coerced into boolean * or numeric values and will instead be left as strings * @return A JSONArray containing the structured data from the XML string. * @throws JSONException Thrown on error converting to a JSONArray */ public static JSONArray toJSONArray(XMLTokener x, boolean keepStrings) throws JSONException { return (JSONArray)parse(x, true, null, keepStrings, 0); } /** * Convert a well-formed (but not necessarily valid) XML string into a * JSONArray using the JsonML transform. Each XML tag is represented as * a JSONArray in which the first element is the tag name. If the tag has * attributes, then the second element will be JSONObject containing the * name/value pairs. If the tag contains children, then strings and * JSONArrays will represent the child content and tags. * Comments, prologs, DTDs, and
{@code <[ [ ]]>}
are ignored. * @param x An XMLTokener. * @return A JSONArray containing the structured data from the XML string. * @throws JSONException Thrown on error converting to a JSONArray */ public static JSONArray toJSONArray(XMLTokener x) throws JSONException { return (JSONArray)parse(x, true, null, false, 0); } /** * Convert a well-formed (but not necessarily valid) XML string into a * JSONObject using the JsonML transform. Each XML tag is represented as * a JSONObject with a "tagName" property. If the tag has attributes, then * the attributes will be in the JSONObject as properties. If the tag * contains children, the object will have a "childNodes" property which * will be an array of strings and JsonML JSONObjects. * Comments, prologs, DTDs, and
{@code <[ [ ]]>}
are ignored. * @param string The XML source text. * @return A JSONObject containing the structured data from the XML string. * @throws JSONException Thrown on error converting to a JSONObject */ public static JSONObject toJSONObject(String string) throws JSONException { return (JSONObject)parse(new XMLTokener(string), false, null, false, 0); } /** * Convert a well-formed (but not necessarily valid) XML string into a * JSONObject using the JsonML transform. Each XML tag is represented as * a JSONObject with a "tagName" property. If the tag has attributes, then * the attributes will be in the JSONObject as properties. If the tag * contains children, the object will have a "childNodes" property which * will be an array of strings and JsonML JSONObjects. * Comments, prologs, DTDs, and
{@code <[ [ ]]>}
are ignored. * @param string The XML source text. * @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 on error converting to a JSONObject */ public static JSONObject toJSONObject(String string, boolean keepStrings) throws JSONException { return (JSONObject)parse(new XMLTokener(string), false, null, keepStrings, 0); } /** * Convert a well-formed (but not necessarily valid) XML string into a * JSONObject using the JsonML transform. Each XML tag is represented as * a JSONObject with a "tagName" property. If the tag has attributes, then * the attributes will be in the JSONObject as properties. If the tag * contains children, the object will have a "childNodes" property which * will be an array of strings and JsonML JSONObjects. * Comments, prologs, DTDs, and
{@code <[ [ ]]>}
are ignored. * @param string The XML source text. * @param config The parser configuration: * JSONMLParserConfiguration.ORIGINAL is the default behaviour; * JSONMLParserConfiguration.KEEP_STRINGS means 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 on error converting to a JSONObject */ public static JSONObject toJSONObject(String string, JSONMLParserConfiguration config) throws JSONException { return (JSONObject)parse(new XMLTokener(string), false, null, config, 0); } /** * Convert a well-formed (but not necessarily valid) XML string into a * JSONObject using the JsonML transform. Each XML tag is represented as * a JSONObject with a "tagName" property. If the tag has attributes, then * the attributes will be in the JSONObject as properties. If the tag * contains children, the object will have a "childNodes" property which * will be an array of strings and JsonML JSONObjects. * Comments, prologs, DTDs, and
{@code <[ [ ]]>}
are ignored. * @param x An XMLTokener of the XML source text. * @return A JSONObject containing the structured data from the XML string. * @throws JSONException Thrown on error converting to a JSONObject */ public static JSONObject toJSONObject(XMLTokener x) throws JSONException { return (JSONObject)parse(x, false, null, false, 0); } /** * Convert a well-formed (but not necessarily valid) XML string into a * JSONObject using the JsonML transform. Each XML tag is represented as * a JSONObject with a "tagName" property. If the tag has attributes, then * the attributes will be in the JSONObject as properties. If the tag * contains children, the object will have a "childNodes" property which * will be an array of strings and JsonML JSONObjects. * Comments, prologs, DTDs, and
{@code <[ [ ]]>}
are ignored. * @param x An XMLTokener of the XML source text. * @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 on error converting to a JSONObject */ public static JSONObject toJSONObject(XMLTokener x, boolean keepStrings) throws JSONException { return (JSONObject)parse(x, false, null, keepStrings, 0); } /** * Convert a well-formed (but not necessarily valid) XML string into a * JSONObject using the JsonML transform. Each XML tag is represented as * a JSONObject with a "tagName" property. If the tag has attributes, then * the attributes will be in the JSONObject as properties. If the tag * contains children, the object will have a "childNodes" property which * will be an array of strings and JsonML JSONObjects. * Comments, prologs, DTDs, and
{@code <[ [ ]]>}
are ignored. * @param x An XMLTokener of the XML source text. * @param config The parser configuration: * JSONMLParserConfiguration.ORIGINAL is the default behaviour; * JSONMLParserConfiguration.KEEP_STRINGS means 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 on error converting to a JSONObject */ public static JSONObject toJSONObject(XMLTokener x, JSONMLParserConfiguration config) throws JSONException { return (JSONObject)parse(x, false, null, config, 0); } /** * Reverse the JSONML transformation, making an XML text from a JSONArray. * @param ja A JSONArray. * @return An XML string. * @throws JSONException Thrown on error converting to a string */ public static String toString(JSONArray ja) throws JSONException { int i; JSONObject jo; int length; Object object; StringBuilder sb = new StringBuilder(); String tagName; // Emit = length) { sb.append('/'); sb.append('>'); } else { sb.append('>'); do { object = ja.get(i); i += 1; if (object != null) { if (object instanceof String) { sb.append(XML.escape(object.toString())); } else if (object instanceof JSONObject) { sb.append(toString((JSONObject)object)); } else if (object instanceof JSONArray) { sb.append(toString((JSONArray)object)); } else { sb.append(object.toString()); } } } while (i < length); sb.append('<'); sb.append('/'); sb.append(tagName); sb.append('>'); } return sb.toString(); } /** * Reverse the JSONML transformation, making an XML text from a JSONObject. * The JSONObject must contain a "tagName" property. If it has children, * then it must have a "childNodes" property containing an array of objects. * The other properties are attributes with string values. * @param jo A JSONObject. * @return An XML string. * @throws JSONException Thrown on error converting to a string */ public static String toString(JSONObject jo) throws JSONException { StringBuilder sb = new StringBuilder(); int i; JSONArray ja; int length; Object object; String tagName; Object value; //Emit '); } else { sb.append('>'); length = ja.length(); for (i = 0; i < length; i += 1) { object = ja.get(i); if (object != null) { if (object instanceof String) { sb.append(XML.escape(object.toString())); } else if (object instanceof JSONObject) { sb.append(toString((JSONObject)object)); } else if (object instanceof JSONArray) { sb.append(toString((JSONArray)object)); } else { sb.append(object.toString()); } } } sb.append('<'); sb.append('/'); sb.append(tagName); sb.append('>'); } return sb.toString(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy