2

我知道这已被多次询问,但我有一个不同的问题来处理它。在我的例子中,应用程序接收到一个非格式良好的 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:对实体“功能”的引用必须以“;”结尾 分隔符。

根据要求,我需要阅读此文档,添加一些额外的 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();

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

谢谢

4

1 回答 1

1

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

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

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

  1. 写一个LexicalHandler结合ContentHandler
  2. 告诉解析器在致命错误后继续执行(这 ErrorHandler还不够)
  3. 将未声明的实体视为简单文本

更新
根据您的评论,我将添加有关第二个解决方案的一些详细信息。我编写了一个类,它扩展DefaulHandler(默认实现EntityResolverDTDHandler和)ContentHandlerErrorHandler实现LexicalHandler. 我扩展了ErrorHandler'fatalError方法(我的实现什么都不做,而不是抛出异常)和ContentHandler'characters方法,它startEntityLexicalHandler.

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 {
    }
}

这是我解析你的 xml 格式不正确的主要内容。非常重要setFeature,因为没有它,SaxParseException尽管实现为ErrorHandler空,解析器仍会抛出异常。

public static void main(String[] args) throws ParserConfigurationException,
        SAXException, IOException {
    String xml = "<div class='video yt'><div class='yt_url'>http://www.youtube.com/watch?v=U_QLu_Twd0g&feature=abcde_gdata</div></div>";
    SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
    XMLReader xmlReader = saxParser.getXMLReader();
    MyHandler myHandler = new MyHandler();
    xmlReader.setContentHandler(myHandler);
    xmlReader.setErrorHandler(myHandler);
    xmlReader.setProperty("http://xml.org/sax/properties/lexical-handler",
            myHandler);
    xmlReader.setFeature(
            "http://apache.org/xml/features/continue-after-fatal-error",
            true);
    xmlReader.parse(new InputSource(new StringReader(xml)));
}

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

http://www.youtube.com/watch?v=U_QLu_Twd0g&feature=abcde_gdata

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

希望这可以帮助。

于 2011-04-11T12:42:43.843 回答