【问题标题】:Jsoup converting & to & when I require that info as it is当我需要该信息时,Jsoup 将 & 转换为 &
【发布时间】:2015-10-01 11:05:12
【问题描述】:

在少数情况下,我会传递带有用户执行某些操作的页面 url 的 JSON。该页面 url 将包含我需要的那些查询字符串部分,以便用户在我的应用程序需要时重定向到同一页面。我的 JSON 会是这样的

{
"userId":"123456789",
"pageUrl":"http://exampl.com/designs.jsp?templateId=f348aaf2-45e4-4836-9be4-9a7e63105932&kind=123",
"action":"favourite"
}

但是当我通过Jsoup.clean(json, Whitelist.basic()) 运行这个json 时,我看到&& 替换了。我可以将Jsoup 配置为不单独转义这个字符吗?

【问题讨论】:

  • 您是否尝试过任何其他白名单选项,例如relaxed
  • 即使放松我也看到同样的结果

标签: java jsoup


【解决方案1】:

转义发生在org.jsoup.nodes.Entities。 这是有问题的代码

static void escape(StringBuilder accum, String string,
        Document.OutputSettings out, boolean inAttribute,
        boolean normaliseWhite, boolean stripLeadingWhite) {
    boolean lastWasWhite = false;
    boolean reachedNonWhite = false;
    EscapeMode escapeMode = out.escapeMode();
    CharsetEncoder encoder = out.encoder();
    CoreCharset coreCharset = CoreCharset.access$300(encoder.charset().name());
    Map map = escapeMode.getMap();
    int length = string.length();
    int codePoint;
    for (int offset = 0; offset < length; offset += Character.charCount(codePoint)) {
        codePoint = string.codePointAt(offset);

        if (normaliseWhite) {
            if (StringUtil.isWhitespace(codePoint)) {
                if ((stripLeadingWhite) && (!(reachedNonWhite)))
                    continue;
                if (lastWasWhite)
                    continue;
                accum.append(' ');
                lastWasWhite = true;
                continue;
            }
            lastWasWhite = false;
            reachedNonWhite = true;
        }

        if (codePoint < 65536) {
            char c = (char) codePoint;

            switch (c) {
            case '&':
                accum.append("&amp;");
                break;
            case ' ':
                if (escapeMode != EscapeMode.xhtml)
                    accum.append("&nbsp;");
                else
                    accum.append(c);
                break;
            case '<':
                if (!(inAttribute))
                    accum.append("&lt;");
                else
                    accum.append(c);
                break;
            case '>':
                if (!(inAttribute))
                    accum.append("&gt;");
                else
                    accum.append(c);
                break;
            case '"':
                if (inAttribute)
                    accum.append("&quot;");
                else
                    accum.append(c);
                break;
            default:
                if (canEncode(coreCharset, c, encoder))
                    accum.append(c);
                else if (map.containsKey(Character.valueOf(c)))
                    accum.append('&')
                            .append((String) map.get(Character.valueOf(c)))
                            .append(';');
                else
                    accum.append("&#x")
                            .append(Integer.toHexString(codePoint))
                            .append(';');
            }
        } else {
            String c = new String(Character.toChars(codePoint));
            if (encoder.canEncode(c))
                accum.append(c);
            else
                accum.append("&#x").append(Integer.toHexString(codePoint))
                        .append(';');
        }
    }
}

一个快速的方法来做你需要的是使用这样的东西

String str = "http://exampl.com/designs.jsp?templateId=f348aaf2-45e4-4836-9be4-9a7e63105932&kind=123";
str = Jsoup.clean(str, Whitelist.basic());
System.out.println(str);
str = Parser.unescapeEntities(str, true);
System.out.println(str);

另一种方法是扩展上述类并覆盖导致问题的方法,但由于它仅对包可见(默认可见性),这意味着您必须下载源代码,更改上面的方法,并覆盖类(因此该方法是可见的)。

【讨论】:

  • 感谢您的帮助。作为应用 Jsoup.clean() 后的工作区,我将替换 &使用正则表达式。
  • 我相信这是一种更安全的做法,但如果这解决了您的问题,那么请务必使用它。由于我的回答不能解决您的问题,请发布您的答案并选择它,以便问题可以被视为已关闭。
  • 使用 Parser.unescapeEntities(str, true) 比使用正则表达式替换更安全。
  • 非常感谢@AlkisKalogeris 的回答。它为我节省了很多时间。
【解决方案2】:

作为应用Jsoup.clean() 后的工作区,我使用regex&amp;amp; 替换为&amp;

String url = Jsoup.clean(url, Whitelist.basic()).replaceAll("&amp;", "&");

【讨论】:

猜你喜欢
  • 2023-03-15
  • 1970-01-01
  • 2016-01-20
  • 2014-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-02
相关资源
最近更新 更多