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

org.json.XMLTokener Maven / Gradle / Ivy

There is a newer version: 2024.9.17689.20240905T073330Z-240800
Show newest version
package org.json;

import java.util.HashMap;

/**
 * The XMLTokener extends the JSONTokener to provide additional methods
 * for the parsing of XML texts.
 * @author JSON.org
 * @version 2009-02-11
 * @deprecated Use javax.json or other other json libraries instead
 */
@Deprecated
public class XMLTokener extends JSONTokener {

    public static final HashMap entity = new HashMap<>(8);

    static {
        entity.put("amp", XML.AMP);
        entity.put("apos", XML.APOS);
        entity.put("gt", XML.GT);
        entity.put("lt", XML.LT);
        entity.put("quot", XML.QUOT);
    }

    /**
     * Construct an XMLTokener from a string.
     * @param s A source string.
     */
    public XMLTokener(String s) {
        super(s);
    }

    /**
     * Get the text in the CDATA block.
     * @return The string up to the ]]>.
     * @throws JSONException If the ]]> is not found.
     */
    public String nextCDATA() throws JSONException {
        StringBuffer sb = new StringBuffer();
        int i;
        do {
            char c = next();
            if (end()) {
                throw syntaxError("Unclosed CDATA");
            }
            sb.append(c);
            i = sb.length() - 3;
        } while ((i < 0) || (sb.charAt(i) != ']') || (sb.charAt(i + 1) != ']') || (sb.charAt(i + 2) != '>'));
        sb.setLength(i);
        return sb.toString();
    }

    /**
     * Get the next XML outer token, trimming whitespace. There are two kinds
     * of tokens: the '<' character which begins a markup tag, and the content
     * text between markup tags.
     *
     * @return  A string, or a '<' Character, or null if there is no more
     * source text.
     * @throws JSONException
     */
    public Object nextContent() throws JSONException {
        char c;
        do {
            c = next();
        } while (Character.isWhitespace(c));
        if (c == 0) {
            return null;
        }
        if (c == '<') {
            return XML.LT;
        }
        StringBuffer sb = new StringBuffer();
        for (;;) {
            if ((c == '<') || (c == 0)) {
                back();
                return sb.toString().trim();
            }
            if (c == '&') {
                sb.append(nextEntity(c));
            } else {
                sb.append(c);
            }
            c = next();
        }
    }

    /**
     * Return the next entity. These entities are translated to Characters:
     *     &  '  >  <  ".
     * @param ampersand An ampersand character.
     * @return  A Character or an entity String if the entity is not recognized.
     * @throws JSONException If missing ';' in XML entity.
     */
    public Object nextEntity(char ampersand) throws JSONException {
        StringBuffer sb = new StringBuffer();
        char c;
        do {
            c = next();
            if (!Character.isLetterOrDigit(c) && c != '#')
                break;
            sb.append(Character.toLowerCase(c));
        } while (true);
        if (c != ';') {
            throw syntaxError((new StringBuilder()).append("Missing ';' in XML entity: &").append(sb).toString());
        } else {
            String string = sb.toString();
            Object object = entity.get(string);
            return object == null
                    ? (new StringBuilder()).append(ampersand).append(string).append(";").toString()
                    : object;
        }
    }

    /**
     * Returns the next XML meta token. This is used for skipping over 
     * and  structures.
     * @return Syntax characters (< > / = ! ?) are returned as
     *  Character, and strings and names are returned as Boolean. We don't care
     *  what the values actually are.
     * @throws JSONException If a string is not properly closed or if the XML
     *  is badly structured.
     */
    public Object nextMeta() throws JSONException {
        char c;
        do {
            c = next();
        } while (Character.isWhitespace(c));
        switch (c) {
            case '\000' :
                throw syntaxError("Misshaped meta tag");
            case '<' :
                return XML.LT;
            case '>' :
                return XML.GT;
            case '/' :
                return XML.SLASH;
            case '=' :
                return XML.EQ;
            case '!' :
                return XML.BANG;
            case '?' :
                return XML.QUEST;
            case '"' :
            case '\'' :
                char q = c;
                do {
                    c = next();
                    if (c == 0) {
                        throw syntaxError("Unterminated string");
                    }
                } while (c != q);
                return Boolean.TRUE;
        }
        for (;;) {
            c = next();
            if (Character.isWhitespace(c)) {
                return Boolean.TRUE;
            }
            switch (c) {
                case '\000' :
                case '!' :
                case '"' :
                case '\'' :
                case '/' :
                case '<' :
                case '=' :
                case '>' :
                case '?' :
                    back();
                    return Boolean.TRUE;
            }
        }
    }

    /**
     * Get the next XML Token. These tokens are found inside of angle
     * brackets. It may be one of these characters: / > = ! ? or it
     * may be a string wrapped in single quotes or double quotes, or it may be a
     * name.
     * @return a String or a Character.
     * @throws JSONException If the XML is not well formed.
     */
    public Object nextToken() throws JSONException {
        char c;
        do {
            c = next();
        } while (Character.isWhitespace(c));
        switch (c) {
            case '\000' :
                throw syntaxError("Misshaped element");
            case '<' :
                throw syntaxError("Misplaced '<'");
            case '>' :
                return XML.GT;
            case '/' :
                return XML.SLASH;
            case '=' :
                return XML.EQ;
            case '!' :
                return XML.BANG;
            case '?' :
                return XML.QUEST;
            case '"' :
            case '\'' :
                char q = c;
                StringBuffer sb = new StringBuffer();
                for (;;) {
                    c = next();
                    if (c == 0) {
                        throw syntaxError("Unterminated string");
                    }
                    if (c == q) {
                        return sb.toString();
                    }
                    if (c == '&') {
                        sb.append(nextEntity(c));
                    } else {
                        sb.append(c);
                    }
                }
        }
        StringBuffer sb = new StringBuffer();
        for (;;) {
            sb.append(c);
            c = next();
            if (Character.isWhitespace(c)) {
                return sb.toString();
            }
            switch (c) {
                case '\000' :
                    return sb.toString();
                case '!' :
                case '/' :
                case '=' :
                case '>' :
                case '?' :
                case '[' :
                case ']' :
                    back();
                    return sb.toString();
                case '"' :
                case '\'' :
                case '<' :
                    throw syntaxError("Bad character in a name");
            }
        }
    }

    /**
     * Skip characters until past the requested string.
     * If it is not found, we are left at the end of the source with a result of false.
     * @param to A string to skip past.
     */
    public boolean skipPast(String to) throws JSONException {
        int offset = 0;
        int length = to.length();
        char[] circle = new char[length];
        for (int i = 0; i < length; i++) {
            char c = next();
            if (c == 0) {
                return false;
            }
            circle[i] = c;
        }
        for (;;) {
            int j = offset;
            boolean b = true;
            for (int i = 0; i < length; i++) {
                if (circle[j] != to.charAt(i)) {
                    b = false;
                    break;
                }
                j++;
                if (j >= length) {
                    j -= length;
                }
            }
            if (b) {
                return true;
            }
            char c = next();
            if (c == 0) {
                return false;
            }
            circle[offset] = c;
            offset++;
            if (offset >= length) {
                offset -= length;
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy