【问题标题】:How to tell whether an XML document validates against a DTD or XSD?如何判断 XML 文档是针对 DTD 还是 XSD 进行验证?
【发布时间】:2010-10-04 12:38:10
【问题描述】:

在 Java 中,我可以使用 javax.xml.validation.Validator 针对 XSD 模式验证 XML 文档,或者通过使用 org.xml.sax.XMLReader 简单地解析文档来针对 DTD 验证 XML 文档。

我需要的是一种以编程方式确定文档本身是否针对 DTD(即它包含 <!DOCTYPE ...> 语句)或 XSD 进行验证的方法。理想情况下,我需要在不将整个 XML 文档加载到内存的情况下执行此操作。有人可以帮忙吗?

(或者,如果在 Java 中有一种单一方法来验证 XML 文档,该方法适用于 XSD 和 DTD - 并允许自定义资源解析 - 那会更好!)

非常感谢,

一个

【问题讨论】:

  • 我不太确定我是否理解这个问题。您是想查明文档是否真正有效,还是只想知道它使用的是 DTD 还是 XSD?还是完全不同的东西?
  • 第二个 - 我知道如何针对 XSD 验证文档,以及如何针对 DTD 进行验证,但我需要确定使用哪种方法,即文档是使用 DTD 还是 XSD。感谢您的回复。
  • @Alan,这真的是个好主意吗?不要求 XML 文档包含模式引用或 DTD 声明,事实上,大多数 XML 文档不包含此类信息。如果您处理的是纯 XML,是否由您决定如何验证它?
  • @Kevin,总的来说你是对的,但这是一种特殊情况,XML 来自有限数量的来源,并且文档总是指定它们符合的模式。不过,展望未来,我将不得不处理可能未指定其模式的 XML。要记住的事情;谢谢。

标签: java xml validation xsd dtd


【解决方案1】:

查看javax.xml.validation 的包说明。它包含有关验证 XSD 和 DTD 的信息和示例

【讨论】:

    【解决方案2】:

    你能用字符串比较吗?

    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 做了类似的事情。感谢您的帮助。
    • @mmyers。这种方法对 XML 的字符集做了很多假设,并提供了其他失败的机会——例如,注释掉的 doctype。
    • @McDowell:是的。你有更好的办法吗?
    【解决方案3】:

    您能否发布一个代码示例,说明如何针对给定的 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.");
        }
    

    【讨论】:

      【解决方案4】:

      没有确定如何验证任意 XML 文档的 100% 万无一失的过程。

      例如,这个版本 2.4 web application deployment descriptor 指定一个 W3 schema 来验证文档:

      <?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 parser 对此有好处 - 因为它是一种拉机制,您可以只读取文件的开头,然后退出对第一个元素的解析。

      Link to more of the same and sample code and whatnot.

      【讨论】:

        猜你喜欢
        • 2019-10-25
        • 2011-01-30
        • 1970-01-01
        • 2011-06-14
        • 1970-01-01
        • 2020-03-04
        • 2013-10-30
        • 1970-01-01
        • 2011-10-01
        相关资源
        最近更新 更多