如何判断XML文档是否符合DTD或XSD的验证要求?

4
在Java中,我可以使用javax.xml.validation.Validator针对XSD模式验证XML文档,或者通过简单地使用org.xml.sax.XMLReader解析文档来针对DTD进行验证。
但是我需要的是一种以编程方式确定文档本身是否针对DTD(即它包含一个语句)或XSD进行验证的方法。理想情况下,我需要在不将整个XML文档加载到内存中的情况下完成此操作。请问有人能帮忙吗?
(或者,如果有一种在Java中验证XML文档的单一方法,适用于XSD和DTD,并允许自定义解析资源,那将更好!)
非常感谢,
A

我不太确定我理解这个问题。你是想找出文档是否真实有效,还是只想知道它使用了DTD还是XSD?或者完全是其他的事情? - Michael Myers
第二个问题 - 我知道如何使用XSD验证文档,也知道如何使用DTD验证文档,但我需要确定使用哪种方法,即文档是使用DTD还是XSD。感谢您的回复。 - A-G
@Alan,那真的是个好主意吗?没有要求XML文档包括模式引用或DTD声明,实际上,大多数XML文档都不包括这样的信息。如果你正在处理纯XML,那么如何验证它不就取决于你自己吗? - Kevin
@Kevin,你的观点总体上是正确的,但这是一个特殊情况,XML来自有限的来源,并且文档始终指定符合的模式。然而,未来我将不得不处理可能没有指定其模式的XML。这是需要记在心中的事情,谢谢。 - A-G
4个回答

1

1

确定如何验证任意XML文档并没有100%的绝对可靠的过程。

例如,此版本2.4 Web应用程序部署描述符 指定了一个W3模式来验证文档:

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
    xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

然而,这是表达同样意思的一种同样有效的方式:
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
    xmlns="http://java.sun.com/xml/ns/j2ee">

RELAX NG 似乎没有提供任何在文档中指示你使用它的机制。验证机制由文档消费者决定,而不是生产者。如果我没有错的话,这正是从 DTD 切换到更现代化的验证机制的一个推动力之一。

在我看来,最好的方法是根据您正在处理的文档类型来定制机制检测器,并读取头信息并适当地解释它。StAX 解析器 对于此非常有效 - 因为它是一种拉动机制,所以您只需读取文件的开头,然后在第一个元素上停止解析。

链接到更多类似内容和示例代码等等。


0

你能否只使用字符串比较?

public enum Type {
    XSD,
    DTD,
    UNKNOWN
};

public Type findType(File f) throws FileNotFoundException, IOException {
    BufferedReader reader = null;
    try {
        reader = new BufferedReader(new FileReader(f));
        String line;
        // may want to cut this loop off after a certain number of lines
        while ((line = reader.readLine()) != null) {
            line = line.toLowerCase();
            if (line.contains("<!doctype"))
                return Type.DTD;
            else if (line.contains("xsi:schemaLocation"))
                return Type.XSD;
        }
    } finally {
        if (reader != null) {
            try {
                reader.close();
            } catch (IOException ex) {}
        }
    }
    return Type.UNKNOWN;
}

不错的想法!最终,我使用了StAX XMLStreamReader做了类似的事情。感谢您的帮助。 - A-G
@mmyers。该方法对XML的字符集进行了许多假设,并提供了其他失败的机会 - 例如,注释掉的doctype。 - McDowell
@McDowell:是的。你有更好的方法吗? - Michael Myers

0

你能否提供一个代码示例,展示如何使用给定的DTD验证XML。对于模式来说似乎很容易,但我正在努力找到如何使用DTD进行验证。

非常感谢,

丹尼斯。

好的,我找到了:

    XMLReader reader = XMLReaderFactory.createXMLReader();

    // try to activate validation
    try {
          // Turn on validation
          reader.setFeature("http://xml.org/sax/features/validation", true);
          // Ensure namespace processing is on (the default)
          reader.setFeature("http://xml.org/sax/features/namespaces", true);
    } catch (SAXException e) {
        System.err.println("Cannot activate validation.");
    }

    try {
        reader.parse("testFiasRequest.xml");
    } catch (IOException e) {
        System.err.println("I/O exception reading XML document");
    } catch (SAXException e) {
        System.err.println("XML exception reading document.");
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接