4

我正在尝试在客户端和服务器端解析和清理降价。

  • 在客户端,我使用PageDown作为降价编辑器。这正是 StackOverflow 使用的,它带有一个漂亮的预览框。这个预览框向您展示了经过清理的 html,因此它会删除<div>标签等内容。

  • 在服务器端,我使用PegDownJSoup来解析和清理降价。

但是,我发现两者的输出不同的情况。例如:

输入降价: how are <div>tags</div> treated?

PageDown 输出: <p>how are tags treated?</p>

PegDown/JSoup 输出:

<p>how are </p>tags treated?
<p></p>

我没有对 JSoup 做任何花哨的事情。这是我的代码:

public class Main {

    public static void main(String... args){

        PegDownProcessor pdp = new PegDownProcessor();

        String markdown = "how are <div>tags</div> treated?";

        String html = pdp.markdownToHtml(markdown);

        Whitelist whitelist = Whitelist.relaxed().removeTags("div");

        html = Jsoup.clean(html, whitelist);
        System.out.println(html);

        System.out.println("Done.");
    }
}

我理解为什么会发生这种情况,我对两个不同的系统产生两个不同的输出并不感到惊讶。我的问题是:如何设置 JSoup 以便它简单地删除<div>标签而不是添加额外的<p>标签?

我的最终目标是让服务器端解析/清理生成与客户端解析/清理相当相似的结果。如果有更好的方法可以做到这一点,我愿意接受建议。我真的不在乎两者的输出是否完全相同,但是像额外<p>标签这样的东西会被用户注意到,所以我试图消除这一主要区别。

额外的问题:是否有 PageDown 可以输出的 html 标签和属性的列表?

编辑:我也尝试过使用OWASP sanitizer,但我得到了非常相似的结果:<div>标签被删除,但<p>标签以上述方式“固定”,这导致与 PageDown 的 sanitizer 不同的 html。

4

1 回答 1

2

如何设置 JSoup 以便它简单地删除 <div> 标签而不是添加额外的 <p> 标签?

HTML 5 规范拒绝在div元素内使用p元素。Jsoup 尊重这些规范,这就是为什么最终的 html 字符串中有两个p元素。

为了更好地理解为什么会发生这种情况,让我们Jsoup#clean分三个步骤来看看它是如何工作的:

  1. 解析脏 html
  2. 调整生成的树以符合 HTML 5 规范
  3. 删除被拒绝的标签

在步骤 2 中,第一个<p>标签在开始之前关闭div。在同一步骤中,第二个p也得到了它的开始标签。由于 Jsoup 不知道这一段的合法内容从哪里开始,因此它将第二段的内容限制在严格的数量(即什么都没有)。

第 1 步和第 2 步中的操作创建了一个满足 HTML 5 规范的新 HTML 代码。在第 3 步中,div现在可以将其移除。

我的最终目标是让服务器端解析/清理生成与客户端解析/清理相当相似的结果。

为避免出现此处发现的其他情况,您应该在客户端和服务器端使用相同的系统。由于 Pagedown 是用 Javascript 编写的,因此您可以尝试在服务器端 Javascript 引擎中运行它。

仅举几例:

  • Nashorn(内置 Java 8)
  • 犀牛
  • V8

示例代码

这是一个说明 Nashorn 使用的示例:

调用者.java

ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
engine.eval(new FileReader("script.js"));

Invocable invocable = (Invocable) engine;

Object result = invocable.invokeFunction("myFunction", "fooValue");

System.out.println(result);
System.out.println(result.getClass());

脚本.js

function myFunction(foo) {
   // ...
}

也可以看看

于 2016-03-21T10:33:59.927 回答