2013-10-18 46 views
2

我遇到了Java中XSD驗證庫提供的錯誤消息文本的問題。就我而言,似乎Apache Xerces是在內部使用的。 我覺得Java的錯誤很容易讓人誤解。Java中誤導性的XSD驗證錯誤

我從Java得到的錯誤是:

CVC-複雜type.2.4.b:元素 '根' 的內容不完整。預計會有'{subnode1,subnode2}'之一。

但另一個XML編輯器,2004年XMLSpy的,這樣說:

預計在'強制性內容subnode1 '後':subnode2,subnode3

第二個錯誤似乎是多少這裏更精確,因爲沒有子節點1丟失。但是,子節點2和子節點3都是。

這裏是我的XML文件:

<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="schema.xsd"> 
    <subnode0/> 
    <subnode1/> 
</root> 

這是我使用的XSD:

<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
    <xs:element name="root" type="NodeType"> 
    </xs:element> 

    <xs:complexType name="NodeType"> 
     <xs:sequence> 
      <xs:element name="subnode0" type="subnode0_Type" minOccurs="0" maxOccurs="unbounded"/> 
      <xs:element name="subnode1" type="subnode1_Type" minOccurs="0" maxOccurs="unbounded"/> 
      <xs:element name="subnode2" type="subnode2_Type" minOccurs="1" maxOccurs="1"/> 
      <xs:element name="subnode3" type="subnode3_Type" minOccurs="1" maxOccurs="1"/> 
     </xs:sequence> 
    </xs:complexType> 
    <xs:complexType name="subnode0_Type"> 
    </xs:complexType> 
    <xs:complexType name="subnode1_Type"> 
    </xs:complexType> 
    <xs:complexType name="subnode2_Type"> 
    </xs:complexType> 
    <xs:complexType name="subnode3_Type"> 
    </xs:complexType> 
</xs:schema> 

這裏是我的Java代碼調用驗證API。

public class XsdErrorTextMain { 

    private final static DocumentBuilder documentBuilder; 
    private final static SchemaFactory schemaFactory; 

    static { 
     try { 
      final DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); 
      documentBuilderFactory.setNamespaceAware(true); 
      documentBuilder = documentBuilderFactory.newDocumentBuilder(); 
     } catch (final ParserConfigurationException e) { 
      throw new RuntimeException(e); 
     } 

     schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 
    } 

    public static void main(final String[] args) throws Exception { 
     final Document xmlDocument = readXmlFile("file.xml"); 
     final Schema schema = readXsdFile("schema.xsd"); 

     runXmlValidation(xmlDocument, schema); 
    } 

    private static void runXmlValidation(final Document xmlDocument, final Schema schema) throws SAXException { 
     try { 
      final Validator validator = schema.newValidator(); 
      validator.setErrorHandler(new ErrorHandler() { 

       @Override 
       public void warning(final SAXParseException exception) { 
        return; 
       } 

       @Override 
       public void error(final SAXParseException exception) throws SAXException { 
        displayValidationError(exception); 
       } 

       @Override 
       public void fatalError(final SAXParseException exception) throws SAXException { 
        throw new RuntimeException("A fatal error was raised during the validation", exception); 
       } 
      }); 

      validator.validate(new DOMSource(xmlDocument)); 
     } catch (final IOException e) { 
      throw new RuntimeException(e); 
     } 
    } 

    private static void displayValidationError(final SAXParseException validationError) { 
     System.out.println("Line: " + validationError.getLineNumber()); 
     System.out.println("Column: " + validationError.getColumnNumber()); 
     System.out.println("Message: " + validationError.getMessage()); 
    } 

    private static Document readXmlFile(final String path) throws IOException, SAXException { 
     try (final InputStream xmlInputStream = ClassLoader.getSystemResource(path).openStream()) { 
      return documentBuilder.parse(xmlInputStream); 
     } 
    } 

    private static Schema readXsdFile(final String path) throws IOException, SAXException { 
     final Document xsdDocument = readXmlFile(path); 
     return schemaFactory.newSchema(new DOMSource(xsdDocument)); 
    } 
} 

我在這裏錯過了什麼嗎? 您是否知道可能更準確地計算錯誤消息的其他實現? 任何輸入讚賞。 謝謝!

回答

1

嚴格來說,您稱之爲XMLSpy 2004的信息是誤導性的。鑑於子節點1上的「unbounded」maxOccurs,人們無法確切地說出最後遇到的子節點1後應該發生什麼:應該有另一個或多個子節點1,然後是子節點2和3?

唯一可以肯定的是,subnode1或subnode2之一可能會跟隨,在錯誤發生的點。

而這正是你得到其他消息(的Xerces你說的,順便說一句它匹配標準.NET的)什麼告訴你......

想象一下,有人使用該信息來建立這樣的編輯器驅動用戶完成構建有效XML所需的步驟(例如,Intellisense或圖形編輯器中的某些上下文菜單)。你認爲哪一個更適合引導用戶?我會把Xerces消息稱爲正確的消息,因爲一旦我填充了一個子節點1,XML Spy 2004消息就會不斷提示節點2和3(爲什麼3如果我沒有填充2 ?如果我想繼續添加subnode1s怎麼辦?)

我的觀點是,它可能取決於您對這些消息的期望。我個人的看法是Xerces(以及.NET所表達的)消息是正確的,對於我描述的任務類型。有些人可能會發現它太迭代了,也就是說,只有在你擊中子節點2之後纔會「準備」一個子節點3 ......我想......

但是,想象一下另一種場景,其中你展示的整個節點組被包裹在一個可選的序列中,並且該序列之後是一個強制性的子節點4 ....在這種情況下, '' after 'subnode1': subnode2, subnode3, subnode4。然後,如果我在上面提到的可選序列重複了,該怎麼辦?最後,考慮到XSD模型的性質,可以實現這種「向前看」以給你提供可能性......事情是,選項容易複合到信息變得無用的點上......而什麼是接下來對於現在來說總是一件好事。

+0

這個解釋非常有趣!我現在更好地理解了第一條錯誤消息。 – Axel