2

所以我有大量的 XML 文件。多年来,它们一直在制造麻烦,因为编写它们的人是手工编写的,因此自然会出现错误。现在是我们验证它们并就尝试使用这些 XML 文件时出现的问题提供反馈的时候了。

我正在使用 SAX 解析器并获取错误列表。

下面是我的代码

  BookValidationErrorHandler errorHandler = new BookValidationErrorHandler();

        SAXParserFactory factory = SAXParserFactory.newInstance();
        factory.setValidating(true);
        factory.setNamespaceAware(true);

        SchemaFactory schemaFactory = 
            SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");

        factory.setSchema(schemaFactory.newSchema(
            new Source[] {new StreamSource("test.xsd")}));


        javax.xml.parsers.SAXParser parser = factory.newSAXParser();
        org.xml.sax.XMLReader reader = parser.getXMLReader();

        reader.setErrorHandler(errorHandler);
        reader.parse(new InputSource("bad.xml"));

前几个错误总是:

行号:2:文档无效:未找到语法。行号:2:文档根元素“credits”,必须匹配 DOCTYPE 根“null”。

我们不可能去编辑这数千个需要检查的 XML 文件。

有什么我可以很容易地添加到源的前面来防止这种情况发生吗?有没有办法告诉解析器忽略这些与 DTD 相关的错误?甚至不确定语法一个是什么意思。我有点明白第二个是什么意思。

4

3 回答 3

8

设置setValidating(true)请求 DTD 验证,如果不存在 DTD,则会导致失败。如果您只需要模式验证而不需要 DTD 验证,请使用setValidating(false). 来自Javadoc 的setValidating()

要使用现代模式语言(如 W3C XML Schema 或 RELAX NG)而不是 DTD,您可以将解析器配置为非验证解析器,方法是将setValidating(boolean)方法保留为 false,然后使用该setSchema(Schema)方法将模式关联到解析器。

于 2011-03-04T08:59:02.130 回答
0

在这些讲台上,我遇到了同样的问题;我发现这个线程正在寻找解决方案。我的解决方案是使用 EntityResolver。似乎设置架构是不够的......至少不适合我。这是一个 EntityResolver 示例:

public class CustomResolver implements EntityResolver {
    @Override
    public InputSource resolveEntity(String publicId, String systemId) 
            throws SAXException, IOException {

        if (systemId.equals("http://namespace1.example.com/ex1")) {
            return new InputSource("xsd_for_namespace1_path"));
        } else if (systemId.equals("http://namespace2.example.com/ex2")) {
            return new InputSource("xsd_for_namespace2_path"));
        } else if (systemId.equals("http://namespace3.example.com/ex3")) {
            return new InputSource("xsd_for_namespace3_path")); 
        }

        return null;
    }
}

我也禁用了 setValidating() 属性。这是我的解析器配置:

SAXParserFactory saxpf = SAXParserFactory.newInstance();
saxpf.setNamespaceAware(true);
saxpf.setSchema(getSchema());
saxpf.setValidating(false);
SAXParser saxParser = saxpf.newSAXParser();
saxParser.getParser().setEntityResolver(new XSDResolver());

方法 getSchema() 像您在代码中一样实例化一个 Schema,但具有更多源。

我希望它可以帮助发现同样错误的人。

于 2011-04-20T08:22:55.287 回答
0

您仍然可以使用验证解析器,并且不需要在解析器中预设模式,如果您使用的是符合 JAXP 的解析器并且您按照 Oracle 文档正确配置它:

SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setNamespaceAware(true);
spf.setValidating(true);
SAXParser saxParser = spf.newSAXParser();
// Important step next:  Tell the parser which XML schema-definition language to expect:
saxParser.setProperty("http://java.sun.com/xml/jaxp/properties/schemaLanguage", "http://www.w3.org/2001/XMLSchema");
// Now when we parse a file without a DTD, we no longer get an error 
// (as long as an XSD schema is defined in the file):
saxParser.parse(source, handler);
于 2015-01-21T17:24:09.653 回答