解析时调用的SAX错误()处理程序方法,但不会抛出异常 - 为什么?

问题描述:

我想在分析XML文件时验证它。与Validator.validate()独立验证表示没问题,解析时不会抛出异常,但调用解析处理程序的[覆盖] error()方法。为什么?有一些状态需要初始化吗?如果我故意使XML文件不正确,那么独立验证将失败,如果我注释掉验证,解析也会失败 - 这两个都带有SAXParseException,并且出现了我预期的错误。解析时调用的SAX错误()处理程序方法,但不会抛出异常 - 为什么?

[代码下面从实际的东西剪辑下来,有很多的println的来说明问题]

short.xsd:

<?xml version="1.0" encoding="UTF-8" ?> 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
      targetNamespace="http://www.myapp.com/sample" 
      xmlns:smp="http://www.myapp.com/sample" 
      elementFormDefault="qualified" 
      attributeFormDefault="unqualified"> 
    <xs:element name="Sample" type="xs:string"/> 
</xs:schema> 

short.xml:

<?xml version="1.0"?> 
<Sample 
    xmlns="http://www.myapp.com/sample" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://www.myapp.com/sample shortxsd.xsd" 
> 
    hello 
</Sample> 

来源:

import javax.xml.XMLConstants; 
import javax.xml.parsers.ParserConfigurationException; 
import javax.xml.parsers.SAXParser; 
import javax.xml.parsers.SAXParserFactory; 
import javax.xml.transform.Source; 
import javax.xml.transform.stream.StreamSource; 
import javax.xml.validation.Schema; 
import javax.xml.validation.SchemaFactory; 
import javax.xml.validation.Validator; 
import org.xml.sax.SAXException; 
import org.xml.sax.SAXParseException; 
import org.xml.sax.helpers.DefaultHandler; 

public static void main(String... args) 
     throws IOException 
    { 
    String xsdFileName = "shortxsd.xsd"; 
    URL xsdURL = Thread.currentThread().getContextClassLoader().getResource(xsdFileName); 
    String xsdPath = xsdURL.getPath(); 
    System.out.println("xsdFileName: " + xsdFileName); 
    System.out.println("xsdURL: " + xsdURL); 
    System.out.println("xsdPath: " + xsdPath); 

    String xmlFileName = "shortxml.xml"; 
    URL xmlURL = Thread.currentThread().getContextClassLoader().getResource(xmlFileName); 
    String xmlPath = xmlURL.getPath(); 
    System.out.println("xmlFileName: " + xmlFileName); 
    System.out.println("xmlURL: " + xmlURL); 
    System.out.println("xmlPath: " + xmlPath); 

    /* Schema creation: */ 
    SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 
    Schema schema = null; 
    try { 
     schema = schemaFactory.newSchema(new File(xsdURL.getFile())); 
    } 
    catch (SAXException ex) { 
     System.out.println("Schema creation exception: " + ex); 
     return; 
    } 
    System.out.println("+ Schema creation OK"); 

    /* Stand-alone Validation: */ 
    Validator validator = schema.newValidator(); 
    Source xmlFile = new StreamSource(xmlURL.openStream()); 
    try { 
     validator.validate(xmlFile); 
    } 
    catch (SAXException ex) { 
     System.out.println("Validation exception: " + ex); 
     return; 
    } 
    System.out.println("+ Stand-alone Validation OK"); 

    /* Parsing with validation: */ 
    SAXParserFactory parserFactory = SAXParserFactory.newInstance(); 
    parserFactory.setSchema(schema); 
    SAXParser saxParser = null; 
    try { 
     saxParser = parserFactory.newSAXParser(); 
    } 
    catch (ParserConfigurationException | 
      SAXException ex) { 
     System.out.println("Parser creation exception: " + ex); 
     return; 
    } 
    System.out.println("+ Parser creation OK"); 

    try (InputStream xmlInput = xmlURL.openStream()) { 
     saxParser.parse(xmlInput, new DefaultHandler() 
        { 
        @Override 
        public void error(SAXParseException e) 
        { 
         System.out.println("# Error: " + e); 
        } 
     }); 
    } 
    catch (SAXException ex) { 
     System.out.println("Parsing exception: " + ex); 
     return; 
    } 
    System.out.println("+ Parsing OK"); 
    } 

输出:

xsdFileName: shortxsd.xsd 
xsdURL: file:/.../target/classes/shortxsd.xsd 
xsdPath: /.../target/classes/shortxsd.xsd 
xmlFileName: shortxml.xml 
xmlURL: file:/.../target/classes/shortxml.xml 
xmlPath: /.../target/classes/shortxml.xml 
+ Schema creation OK 
+ Stand-alone Validation OK 
+ Parser creation OK 
# Error: org.xml.sax.SAXParseException; lineNumber: 6; columnNumber: 2; cvc-elt.1: Cannot find the declaration of element 'Sample'. 
+ Parsing OK 

您需要配置SAX解析器是名称空间感知。

如果您从XML文档中删除xmlns="..."属性,并从XML模式中删除xmlns:smp="..."targetNamespace="..."属性,则代码不会生成任何错误消息。所以这个问题必须与名称空间有关。

为了使SAX解析器命名空间感知,在出厂时设置的选项:

/* Parsing with validation: */ 
    SAXParserFactory parserFactory = SAXParserFactory.newInstance(); 
    parserFactory.setNamespaceAware(true); // add this line 
    parserFactory.setSchema(schema); 

我做了这个改变了代码,并在最后打印了四次OK消息。

+0

这样做的窍门!我很困惑为什么独立验证不需要类似的配置;我想独立的Validator实现可以自行确定。无论如何,问题都解决了。非常感谢。 – CraftWeaver