【问题标题】:DTD parsing with Stax使用 Stax 进行 DTD 解析
【发布时间】:2013-10-07 14:24:31
【问题描述】:

我想解析声明 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 web site) 检索到 dtd。但我必须更改此文件以删除节点中的所有 cmets,如下所示:

 <!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;)* >

有什么想法吗?

谢谢

【问题讨论】:

    标签: java dtd stax html4


    【解决方案1】:

    HTML 是一种 SGML 语言,因此它具有 SGML DTD。您可以在此处找到有关 SGML 的更多信息:http://validator.w3.org/docs/sgml.html

    SGML 与 XML 有点不同,难怪 XML 解析器无法解析它。

    主要例子是:

    实体声明中的cmets(用双连字符分隔:--这是一个注释--)在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/ 作为解决方案

    【讨论】:

      猜你喜欢
      • 2016-01-13
      • 1970-01-01
      • 1970-01-01
      • 2021-09-13
      • 2010-09-23
      • 2014-09-28
      • 2016-10-30
      • 1970-01-01
      • 2012-05-27
      相关资源
      最近更新 更多