是否有任何Java HTML解析器,其中生成的节点保留原始文本的索引?

时间:2011-09-03 23:12:35

标签: java html xml parsing xpath

我想将HTML文档作为XML查询(例如使用XPath),因此我需要通过某种形式的HTML清理器传递HTML。

但我还想根据查询结果修改原始源字符串。

是否有一个Java HTML解析器保留了原始源字符串的索引,所以我可以找到一个节点并修改原始字符串的正确部分?

干杯。

7 个答案:

答案 0 :(得分:2)

听起来杰里科几乎就是你想要的。它是一个强大的HTML解析器,专门用于对源文档进行非侵入式修改。

虽然它没有附带DOM,SAX或StAX接口,但它具有与那些标准类似的自定义API,您应该可以相当容易地调整您的方法,或者在您之间编写适配器正在使用和杰里科。例如,您可以使用Jaxen对Jericho文档执行XPath查询 - 请参阅this blog entry作为示例。

杰里科拥有begin和每个元素的结束属性,甚至对于元素的部分内容,如标记名称甚至是属性名称,因此您可以使用该信息自行编辑文档,但杰里科真正闪耀的地方是OutputDocument类,它允许您直接通过使用与您的查询匹配的Jericho元素调用适当的方法来指定替换,而不必在它们上显式调用getBegin()和getEnd()并将其传递给某些替换方法。

答案 1 :(得分:1)

我们使用jericho html parser进行解析,使用htmlcleaner进行实际清理。

我们修复了服务器应用程序(内存管理,日志记录)中jericho的行为问题。 (原始开发人员认为我们的问题不够重要,无法放入主代码分支)。 Our fork is on github. 我们还制作了fixes to htmlcleaner

答案 2 :(得分:0)

我不知道“保留原始文本的索引”部分,但Jericho是一个非常好的HTML解析器库。

以下是如何从html中删除每个范围的示例:

public static String removeSpans(String html) {
    Source source = new Source(html);
    source.fullSequentialParse();
    OutputDocument outputDocument = new OutputDocument(source);
    List<Tag> tags = source.getAllTags();
    for (Tag tag : tags) {
        String tagname = tag.getName().toLowerCase();
        if (tagname.equals("span")) {
            //remove the <span>
            outputDocument.remove(tag);
        }
    }
    return outputDocument.toString();
}

答案 3 :(得分:0)

我猜你可以使用HTML Parser

您可以使用Page中的getStartPosition()getEndPosition()获取原始Node的索引。

答案 4 :(得分:0)

正如其他人所建议的那样,您可能想要渲染DOM。这基本上只是意味着构建节点树,它不会改变文档源,除非你使用像jTidy这样的HTML清理器。然后,您可以轻松访问该文档,并可以根据需要进行修改。我建议DOM4J,它也有很好的api和xpath支持。

重新编写“索引”要求,在遍历/查询文档期间,您可以在列表中缓存或映射您希望稍后修改文本的任何元素或节点。

答案 5 :(得分:0)

这很棒

http://jtidy.sourceforge.net/

实施例

Tidy tidy = new Tidy(); // obtain a new Tidy instance
tidy.setXHTML(boolean xhtml); // set desired config options using tidy setters 
...                           // (equivalent to command line options)

tidy.parse(inputStream, System.out);

对于抓取DOM,我建议使用JDOM,它比简单的XML更快。

http://www.jdom.org/

DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.newDocument();
Element root = doc.createElement("root");
Text text = doc.createText("This is the root");
root.appendChild(text);
doc.appendChild(root);

就实现而言,我会创建一个新文档,并从源添加节点。

答案 6 :(得分:0)

您可以使用ANTLR尝试HTML grammar

您可以采用(至少)2种方法 - 尝试将其用作实际的HTML解析器,然后将索引放入您感兴趣的原始字符串中。

或者,它还内置了对源文本进行就地转换的支持,您可以在其中定义要对文本执行的转换作为语法的一部分。