2014-12-28 28 views
0

我想在分析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 

回答

1

您需要配置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

相關問題