protected String decodeEntities(String string) {
        StringBuffer buf = new StringBuffer();

        Pattern pattern = Pattern.compile("&#(\\d+);?");
        Matcher matcher = pattern.matcher(string);
        while (matcher.find()) {
            String match = matcher.group(1);
            int decimal = Integer.decode(match).intValue();
            matcher.appendReplacement(buf, chr(decimal));
        }
        matcher.appendTail(buf);
        string = buf.toString();

        buf = new StringBuffer();
        pattern = Pattern.compile("&#x([0-9a-f]+);?");
        matcher = pattern.matcher(string);
        while (matcher.find()) {
            String match = matcher.group(1);
            int decimal = Integer.decode(match).intValue();
            matcher.appendReplacement(buf, chr(decimal));
        }
        matcher.appendTail(buf);
        string = buf.toString();

        buf = new StringBuffer();
        pattern = Pattern.compile("%([0-9a-f]{2});?");
        matcher = pattern.matcher(string);
        while (matcher.find()) {
            String match = matcher.group(1);
            int decimal = Integer.decode(match).intValue();
            matcher.appendReplacement(buf, chr(decimal));
        }
        matcher.appendTail(buf);
        string = buf.toString();

        string = validateEntities(string);
        return string;
    }