[英]DTD parsing with Stax
我想解析聲明HTML 4.01 Doctype的xml文件。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
[...]
</html>
我使用Stax和XMLResolver加載本地dtd
XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
xmlInputFactory.setXMLResolver(new LocalXmlResolver());
xmlOutputFactory = XMLOutputFactory.newInstance();
xmlOutputFactory.createXMLEventWriter(...)
private static final Map<String, String> DTDS = new HashMap<String, String>(){{
// XHTML 1.0 DTDs
put("-//W3C//DTD XHTML 1.0 Strict//EN", "xhtml1-strict.dtd");
put("-//W3C//DTD XHTML 1.0 Transitional//EN", "xhtml1-transitional.dtd");
put("-//W3C//DTD XHTML 1.0 Frameset//EN", "xhtml1-frameset.dtd");
put("-//W3C//DTD HTML 4.01//EN", "strict.dtd");
put("-//W3C//DTD HTML 4.01 Transitional//EN", "loose.dtd");
put("-//W3C//DTD HTML 4.01 Frameset//EN", "frameset.dtd");
}};
private static final class LocalXmlResolver implements XMLResolver {
@Override
public Object resolveEntity(String publicID, String systemID, String baseURI, String namespace) throws XMLStreamException {
Object result = null;
String path = XHTML_DTD_PATH + DTDS.get(publicID);
if (StringUtils.isNotBlank(path)) {
result = getClass().getClassLoader().getResourceAsStream(path);
}
return result;
}
}
我從( w3c網站 )檢索了dtd。 但是我不得不更改此文件以刪除節點中的所有注釋,如下所示:
<!ENTITY % ContentType "CDATA"
-- media type, as per [RFC2045]
-->
<!ENTITY % ContentType "CDATA">
但是即使進行了這些修改,我仍然會遇到此錯誤:
javax.xml.stream.XMLStreamException: ParseError at [row,col]:[184,11]
Message: The element type is required in the element type declaration.
[...]
Caused by: javax.xml.stream.XMLStreamException: ParseError at [row,col]:[184,11]
Message: The element type is required in the element type declaration.
at com.sun.org.apache.xerces.internal.impl.XMLStreamReaderImpl.next(XMLStreamReaderImpl.java:598)
at com.sun.xml.internal.stream.XMLEventReaderImpl.nextEvent(XMLEventReaderImpl.java:83)
在dtd文件中,第184行為:
<!ELEMENT (%fontstyle;|%phrase;) - - (%inline;)* >
任何想法 ?
謝謝
HTML是一種SGML語言,因此具有SGML DTD。 您可以在此處找到有關SGML的更多信息: http : //validator.w3.org/docs/sgml.html
SGML與XML有所不同,因此,難怪XML解析器無法解析它。
主要示例是:
SGML DTD中允許實體聲明內的注釋(以雙連字符分隔:-這是一個注釋-),而XML DTD則不允許。
有關更多差異,請遵循http://www.w3.org/TR/NOTE-sgml-xml-971215#null
但是,您無法通過創建自己的XMLResolver來禁用特定DTD的DTD解析
xmlInput = XMLInputFactory.newInstance();
xmlInput.setXMLResolver(new XMLResolver() {
@Override
public Object resolveEntity(String publicID, String systemID, String baseURI, String namespace) throws XMLStreamException {
...
// Disable dtd validation
if ("The public id you except".equals(publicId)) {
return IOUtils.toInputStream("");
}
...
}
});
對於html解析器,請考慮使用http://jtidy.sourceforge.net/或http://jsoup.org/作為解決方案
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.