【问题标题】:Karate HTML parsing throwing SaxException when document begins with lower-case <!doctype当文档以小写 <!doctype 开头时,空手道 HTML 解析抛出 SaxException
【发布时间】:2019-11-03 12:42:48
【问题描述】:

我正在尝试运行在 URL 上调用 GET 的空手道测试,但我发现当网站以小写形式返回其 &lt;!doctype 声明时(在“正常”HTML 中完全可以接受),我认为空手道XML 解析器抛出致命错误和警告。在我看来,空手道使用 XML 解析器,所以严格来说,这可能是正确的行为,因为小写 doctype 会中断。但是,对于有效的 HTML,我找不到解决此问题的方法。我玩过不同的标题等,但似乎无法超越这一点。

我已经包含了一个小测试,幸运的是 google.com 也返回了小写声明:

示例测试

Given url 'http://www.google.com'
When method GET
Then status 200

错误

[Fatal Error] :1:3: The markup in the document preceding the root element must be well-formed.
15:19:45.267 [main] WARN com.intuit.karate.FileUtils - parsing failed: org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 3; The markup in the document preceding the root element must be well-formed.

<!doctype html><html .... blah

我下载了空手道源码,发现报的警告:

FileUtils.java

public static String toPrettyString(String raw) {
    raw = StringUtils.trimToEmpty(raw);
    try {
        if (Script.isJson(raw)) {
            return JsonUtils.toPrettyJsonString(JsonUtils.toJsonDoc(raw));
        } else if (Script.isXml(raw)) {
            return XmlUtils.toString(XmlUtils.toXmlDoc(raw), true);
        }
    } catch (Exception e) {
        logger.warn("parsing failed: {}", e.getMessage());
    }
    return raw;
}

通过检查返回文档的第一个字符,检查似乎是在 JSON 或 XML 之间:

Script.java

public static final boolean isXml(String text) {
    return text.startsWith("<");
}

XmlUtils.java

然后我认为 builder.parse 失败了,因为它不是有效的 XHTML,因为下面的注释暗示 &lt;!doctype 将在递归调用中被删除。

public static Document toXmlDoc(String xml) {
    ...

    Document doc = builder.parse(is);
    if (dtdEntityResolver.dtdPresent) { // DOCTYPE present
        // the XML was not parsed, but I think it hangs at the root as a text node
        // so conversion to string and back has the effect of discarding the DOCTYPE !
        return toXmlDoc(toString(doc, false));

是否可以将此流程转移到有效的 HTML 中?

【问题讨论】:

    标签: java html xhtml sax karate


    【解决方案1】:

    如果您查看日志,Karate 还会告诉您它已将完整响应(将在 response 变量中可用)保留为字符串 - 即使它未能将其“类型转换”为 XML。顺便说一句,您甚至在responseBytes 中有一个字节数组。所以现在你可以做任何你想做的事情,例如,理论上你可以找到一个“宽松”的 HTML 解析器并获得一个 DOM 树或其他东西。

    Given url 'http://www.google.com'
    When method GET
    Then status 200
    * print response
    

    一些提示,您可以尝试在 response 上进行字符串替换,然后尝试将其类型转换为 XML,请参阅:https://github.com/intuit/karate#type-conversion

    或者你可能只是想把一些数据刮出来,一些正常的正则表达式匹配可能会做,参考这些:

    https://stackoverflow.com/a/53682733/143475

    https://stackoverflow.com/a/50372295/143475

    【讨论】:

    • 谢谢彼得,这是最有帮助的。我使用了字符串替换,它为我整理好了!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-07
    • 1970-01-01
    • 2015-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多