我知道这已被多次询问,但我有一个不同的问题来处理它。在我的例子中,应用程序接收到一个作为字符串传递的格式不正确的 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();
如果有人可以分享他们的想法,我将不胜感激。
谢谢
最佳答案
最简单的方法是用相应的 xml 实体替换 xml 保留字符。您可以手动执行此操作:
content.replaceAll("&", "&");
如果您不想在解析之前修改您的字符串,我可以向您推荐另一种使用 SaxParser
的方法,但这种解决方案更加复杂。基本上你必须:
- 写一个
LexicalHandler
在 结合ContentHandler
- 告诉解析器继续它的
fatal error 后执行(
ErrorHandler
是不够的) - 将未声明的实体视为简单实体 正文
更新
根据您的评论,我将添加有关第二种解决方案的一些细节。我写了一个扩展 DefaulHandler
的类(EntityResolver
、DTDHandler
、ContentHandler
和 的默认实现ErrorHandler
) 并实现 LexicalHandler
。我扩展了 ErrorHandler
的 fatalError
方法(我的实现除了抛出异常外什么都不做)和 ContentHandler
的 characters
方法与 LexicalHandler
的 startEntity
方法结合使用。
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 {
}
}
这是我的 main,它解析格式不正确的 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
请记住,这是一个适用于您的输入的示例,也许您必须完成它...例如,如果您正确转义了一些字符,您应该添加一些代码行来处理这种情况等。
希望这对您有所帮助。
关于java - 如何跳过 well-formed for java DOM 解析器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5618262/