【问题标题】:Compare two HTML documents using Jsoup (Java)使用 Jsoup (Java) 比较两个 HTML 文档
【发布时间】:2019-11-06 14:29:34
【问题描述】:

我想比较两个使用 Jsoup 表示为字符串的 HTML 文档,忽略空格中的任何差异。

简化示例:

@Test
public void testCompare() {
  Document doc1 = Jsoup.parse("<html><body><div>Hello</div>\n</body></html>");
  Document doc2 = Jsoup.parse("<html><body><div>Hello</div>\n</body>\n</html>");

  System.out.println("Document 1");
  System.out.println("----------");
  for (Node node : doc1.body().childNodes()) {
    printNode(node);
  }

  System.out.println();

  System.out.println("Document 2");
  System.out.println("----------");
  for (Node node : doc2.body().childNodes()) {
    printNode(node);
  }

  assertTrue("HTML documents are different", doc1.hasSameValue(doc2));
}

private void printNode(Node node) {
  String text = node.getClass().getSimpleName();
  if (node instanceof TextNode) {
    TextNode textNode = (TextNode) node;
    text += ": '" + textNode.getWholeText().replaceAll("\n", "\\\\n") + "'";
  }
  System.out.println(text);
}

这两个文档的唯一区别是第二个文档中body标签之后的新行。

body 标签中生成的子节点不同。第一个文档有一个元素节点和一个文本节点(包含一个新行)。第二个文档包含相同的两个节点,但有一个包含另一个新行的附加文本节点。 这个额外的文本节点可能是文档规范化的结果(将正文标记之外的文本节点移动到正文,请参阅 Document#normalise 的 Javadoc)。 Node#hasSameValue 使用 outerHtml 来处理单个文本节点中的后续空格,但不会跨越两个不同的连续空格。

我怎样才能做到这一点?

如果有更好的替代方案可以达到相同的目标,则该解决方案不得使用 Jsoup。

【问题讨论】:

标签: java html comparison jsoup


【解决方案1】:

如果您将两个 html 都视为字符串,则可以执行以下操作:

Function<String, String> normalizer = (original) ->
    original
        .replaceAll("[\\s+]?\n+[\\s+]?", "") // remove newline chars
        .replaceAll("(>)(\\s+)(<)", "$1$3") // remove white space between tags
        .toLowerCase();
String html1 = normalizer.apply(doc1.html());
String html2 = normalizer.apply(doc2.html());
Assert.assertEquals("Both documents are identical", html1, html2);

但是,请记住,此测试仅检查完全匹配。 如果标签、属性或其他数据的顺序不同,则会失败。

【讨论】:

  • 感谢您的意见。 Node#hasSameValue 也会考虑属性的顺序(因为仅使用 outerHtml 进行比较),因此要么是某种形式的标准化,要么是一种自己比较节点的方式(因此不使用 hasSameValue)无论如何都是必需的。我目前的方法是在节点级别(而不是生成的 HTML)应用规范化:删除所有评论节点和所有不包含文本的节点(TextNode#isBlank)、排序属性、删除某些空属性(类、样式)、排序类属性中的 css 类等等。
【解决方案2】:

我也有类似的要求。我通过以下方式实现了它,

  1. 您可以使用 vimdiff 命令创建一个 shell 脚本来比较两个文件并将并排比较导出为 html 文件
  2. 您可以使用 python difflib 来获取两个 html 文件之间的差异。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-14
    • 2022-01-09
    • 2016-10-21
    • 1970-01-01
    相关资源
    最近更新 更多