如何跳过格式良好的java DOM解析器

时间:2011-04-11 07:42:42

标签: java dom saxparser domparser

我知道这里已多次询问过这个问题,但我遇到了一个不同的问题。在我的例子中,应用程序接收一个以字符串形式传递的格式不正确的dom结构。这是一个示例:

<div class='video yt'><div class='yt_url'>http://www.youtube.com/watch?v=U_QLu_Twd0g&feature=abcde_gdata</div></div>

如您所见,内容格式不正确。现在,如果我尝试使用普通的SAX或DOM解析进行解析,它将抛出一个被理解的异常。

org.xml.sax.SAXParseException:对实体“feature”的引用必须以';'结尾分隔符。

根据要求,我需要阅读本文档,添加一些额外的div标签并将内容作为字符串发回。这通过使用DOM解析器很有效,因为我可以通过输入结构读取并在其所需位置添加其他标记。

我尝试使用像JTidy这样的工具进行预处理然后解析,但这会导致将文档转换为完全成熟的html,这是我不想要的。这是一个示例代码:


StringWriter writer = new StringWriter();
Tidy tidy = new Tidy(); // obtain a new Tidy instance
tidy.setXHTML(true);
tidy.parse(new ByteArrayInputStream(content.getBytes()), writer);
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(new ByteArrayInputStream(writer.toString().getBytes()));
// Traverse thru the content and add new tags
....
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
StreamResult result = new StreamResult(new StringWriter());
DOMSource source = new DOMSource(doc);
transformer.transform(source, result);

这会将输入完全转换为格式正确的html文档。然后很难手动删除html标签。我尝试的另一个选项是使用SAX2DOM,它也创建了一个HTML文档。这是一个示例代码。


ByteArrayInputStream is = new ByteArrayInputStream(content.getBytes());     
Parser p = new Parser();
p.setFeature(IContentExtractionConstant.SAX_NAMESPACE,true);
SAX2DOM sax2dom = new SAX2DOM();
p.setContentHandler(sax2dom);
p.parse(new InputSource(is));
Document doc = (Document)sax2dom.getDOM();

如果有人可以分享他们的想法,我将不胜感激。

由于

1 个答案:

答案 0 :(得分:1)

最简单的方法是用相应的xml实体替换xml保留字符。您可以手动执行此操作:

content.replaceAll("&", "&amp;");

如果您不想在解析之前修改字符串,我可以使用SaxParser以另一种方式建议您,但此解决方案更复杂。基本上你必须:

  1. 写一个LexicalHandlerContentHandler
  2. 组合
  3. 告诉解析器继续它 致命错误后执行( ErrorHandler是不够的)
  4. 将未声明的实体视为简单 文本
  5. <强>更新
    根据你的评论,我将添加关于第二个解决方案的一些细节。我写了一个扩展DefaulHandler(默认实现EntityResolverDTDHandlerContentHandlerErrorHandler)并实现LexicalHandler的课程。我已经扩展ErrorHandler的{​​{1}}方法(我的实现什么都不做,而不是抛出异常)和fatalError的{​​{1}}方法,它与{{1}结合使用} ContentHandler的方法。

    characters

    这是我的主要解析你的xml没有很好的形成。 startEntity非常重要,因为没有它,解析器会抛出LexicalHandler,尽管public class MyHandler extends DefaultHandler implements LexicalHandler { private String currentEntity = null; @Override public void fatalError(SAXParseException e) throws SAXException { } @Override public void characters(char[] ch, int start, int length) throws SAXException { String content = new String(ch, start, length); if (currentEntity != null) { content = "&" + currentEntity + content; currentEntity = null; } System.out.print(content); } @Override public void startEntity(String name) throws SAXException { currentEntity = name; } @Override public void endEntity(String name) throws SAXException { } @Override public void startDTD(String name, String publicId, String systemId) throws SAXException { } @Override public void endDTD() throws SAXException { } @Override public void startCDATA() throws SAXException { } @Override public void endCDATA() throws SAXException { } @Override public void comment(char[] ch, int start, int length) throws SAXException { } } 为空实现。

    setFeature

    这个主要打印出div元素的内容,其中包含错误:

    SaxParseException

    请记住,这是一个适用于您的输入的示例,也许您必须完成它...例如,如果您有一些字符正确转义,您应该添加一些代码行来处理这种情况等。

    希望这有帮助。