【问题标题】:Using JDOM to Parse XML file with external DTD that has not been declared in the XML file使用 JDOM 解析带有未在 XML 文件中声明的外部 DTD 的 XML 文件
【发布时间】:2011-02-11 22:25:09
【问题描述】:

在我的 XML 文件中,我有一些实体,例如 ’

所以我为我的 XML 文档创建了一个 DTD 标记来定义这些实体。下面是用于读取 XML 文件的 Java 代码。

SAXBuilder builder = new SAXBuilder();
URL url = new URL("http://127.0.0.1:8080/sample/subject.xml");        
InputStream stream = url.openStream();
org.jdom.Document document = builder.build(stream);

Element root = document.getRootElement();

Element name = root.getChild("name");
result = name.getText();
System.err.println(result);

如何更改 Java 代码以通过 HTTP 检索 DTD 以使我的 XML 文档的解析没有错误?

xml 文档的简化示例。


<main>
  <name>hello &lsquo; world &rsquo; foo  &amp; bar </name> 
</main>

【问题讨论】:

  • 实体必须先声明后才能使用。如果您正在使用尚未声明的实体引用(在文件中或通过对外部 DTD 的引用),则您的 XML 文件无效。
  • 确实如此。我的问题是在运行时将我的 DTD 的路径注入到 xml 中,因为 dtd 在 xml 文档中没有被引用。 DTD 驻留在可通过 http 访问的远程服务器上。

标签: java xml dtd jdom dtd-parsing


【解决方案1】:

一种方法是阅读文档,然后使用转换器对其进行验证:

import java.net.URL;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

public class ValidateWithExternalDTD {
    private static final String URL = "http://127.0.0.1:8080/sample/subject.xml";
    private static final String DTD = "http://127.0.0.1/YourDTD.dtd";

    public static void main(String args[]) {
        try {
            DocumentBuilderFactory factory=                   DocumentBuilderFactory.newInstance();
            factory.setValidating(true);
            DocumentBuilder builder = factory.newDocumentBuilder();

            // Set the error handler
            builder.setErrorHandler(new org.xml.sax.ErrorHandler() {                
                public void fatalError(SAXParseException spex)
                        throws SAXException {
                    // output error and exit
                    spex.printStackTrace();
                    System.exit(0);
                }

                public void error(SAXParseException spex)
                        throws SAXParseException {
                    // output error and continue
                    spex.printStackTrace();
                }

                public void warning(SAXParseException spex)
                        throws SAXParseException {
                    // output warning and continue
                    spex.printStackTrace();
                }
            });

            // Read the document
            URL url = new URL(ValidateWithExternalDTD.URL);
            Document xmlDocument = builder.parse(url.openStream());
            DOMSource source = new DOMSource(xmlDocument);

            // Use the tranformer to validate the document
            StreamResult result = new StreamResult(System.out);                     
            TransformerFactory tf = TransformerFactory.newInstance();
            Transformer transformer = tf.newTransformer();
            transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, ValidateWithExternalDTD.DTD);
            transformer.transform(source, result);

            // Process your document if everything is OK
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

另一种方法是将 XML 标题替换为 XML 标题加上 DTD 引用

替换这个:

<?xml version = "1.0"?>

用这个:

<?xml version = "1.0"?><!DOCTYPE ...>

当然,您只会替换第一次出现的内容,而不是尝试遍历整个 xml 文档

您必须通过将 true(validate) 传递给其构造函数来实例化 SAXBuilder:

SAXBuilder builder = new SAXBuilder(true);

或致电:

builder.setValidation(true)

【讨论】:

  • XML 大小有多大?我可以有一个示例 XML 吗? XML 文档是否总是包含 XML 标题?
  • 我使用的是 JDOM 而不是 W3C DOM :(
  • xml 文件不会那么大。最大值可能约为 200 行,每行少于 80 个字符。
  • 由于文件不大,请使用我为您提供的第二种解决方案。将 XML 标题替换为 XML 标题,然后是 DTD 声明。
  • 将其作为字符串检索,然后将 XML 标题替换为 XML 标题加上 DTD 声明;之后使用带有 Validation=true 的 JDOM 将其解析为 XML 文档
猜你喜欢
  • 2014-10-06
  • 2016-10-15
  • 1970-01-01
  • 2011-06-12
  • 1970-01-01
  • 2011-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多