2016-09-27 39 views
0

我正在解析和验证(xsd)长XML(始终格式良好)的文件,报告了所有验证问题具有持续验证的Java XMLReader:未定义的行为

我的解析器报告并继续应用错误,但有一个奇怪的例外:当由几​​个节点(子节点)组成的节点(父节点)在任何子节点上验证失败时,正确解析所有子节点,但验证停止,直到下一个父节点开始

考虑简单XSD:

<?xml version="1.0" encoding="UTF-8" ?> 
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 

<xsd:element name="customerDataFile"> 
    <xsd:complexType> 
    <xsd:sequence> 
    <xsd:element ref="customerList"/> 
    </xsd:sequence> 
    </xsd:complexType> 
</xsd:element> 

<xsd:element name="customerList"> 
    <xsd:complexType> 
    <xsd:sequence> 
    <xsd:element ref="customerData" minOccurs="1" maxOccurs="unbounded"/> 
    </xsd:sequence> 
    </xsd:complexType> 
</xsd:element> 

<xsd:element name="customerData"> 
    <xsd:complexType> 
    <xsd:sequence> 
    <xsd:element ref="NameField1"/> 
    <xsd:element ref="NameField2"/> 
    </xsd:sequence> 
    </xsd:complexType> 
</xsd:element> 

<xsd:element type="name_field" name="NameField1"/> 
<xsd:element type="name_field" name="NameField2"/> 

<xsd:simpleType name="name_field"> 
    <xsd:restriction base="xsd:string"> 
    <xsd:maxLength value="45"/> 
    </xsd:restriction> 
</xsd:simpleType> 

</xsd:schema> 

和这5个例子:

<?xml version="1.0" encoding="UTF-8"?> 
<customerDataFile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:noNamespaceSchemaLocation="customerDataFile.xsd"> 
<customerList> 
    <customerData> 
    <NameField1>Somecompany</NameField1> 
    <NameField2>Somefirstname</NameField2> 
    </customerData> 
    <customerData> 
    <NameField1>Somecompany</NameField1> 
    <NameField2>Somefirstname</NameField2> 
    </customerData> 
</customerList> 
</customerDataFile> 

<?xml version="1.0" encoding="UTF-8"?> 
<customerDataFile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:noNamespaceSchemaLocation="customerDataFile.xsd"> 
<customerList> 
    <customerData> 
    <Unknown1>Somecompany</Unknown1> 
    <NameField2>Somefirstname</NameField2> 
    </customerData> 
    <customerData> 
    <Unknown1>Somecompany</Unknown1> 
    <NameField2>Somefirstname</NameField2> 
    </customerData> 
</customerList> 
</customerDataFile> 

<?xml version="1.0" encoding="UTF-8"?> 
<customerDataFile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:noNamespaceSchemaLocation="customerDataFile.xsd"> 
<customerList> 
    <customerData> 
    <NameField1>Somecompany</NameField1> 
    <Unknown2>Somefirstname</Unknown2> 
    </customerData> 
    <customerData> 
    <NameField1>Somecompany</NameField1> 
    <Unknown2>Somefirstname</Unknown2> 
    </customerData> 
</customerList> 
</customerDataFile> 

<?xml version="1.0" encoding="UTF-8"?> 
<customerDataFile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:noNamespaceSchemaLocation="customerDataFile.xsd"> 
<customerList> 
    <customerData> 
    <Unknown1>Somecompany</Unknown1> 
    <Unknown2>Somefirstname</Unknown2> 
    </customerData> 
    <customerData> 
    <Unknown1>Somecompany</Unknown1> 
    <Unknown2>Somefirstname</Unknown2> 
    </customerData> 
</customerList> 
</customerDataFile> 

<?xml version="1.0" encoding="UTF-8"?> 
<customerDataFile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:noNamespaceSchemaLocation="customerDataFile.xsd"> 
<customerList> 
    <customerData> 
    <Unknown2>Somefirstname</Unknown2> 
    </customerData> 
    <customerData> 
    <Unknown1>Somecompany</Unknown1> 
    </customerData> 
</customerList> 
</customerDataFile> 

即输出如下:

  1. 没有错误 - 正确
  2. 2错误(一次每customerData) - 正确
  3. 2个错误(每秒customerData) - 正确
  4. 2个错误(每customerData只有一个) - 不正确
  5. 2个错误(即使缺少的元素是严重) - 不正确

这是荒谬的;我找不到任何类似的参考(它看起来像一个主要问题)。

相关的代码是:

public void process(String schemaLocation, String xmlLocation) { 

Source source = new StreamSource(new File(schemaLocation)); 
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 
Schema schema = schemaFactory.newSchema(source); 

SAXParserFactory spf = SAXParserFactory.newInstance(); 
spf.setSchema(schema); 
spf.setNamespaceAware(true); 
SAXParser saxParser = spf.newSAXParser(); 
CustomerHandler handler = new CustomerHandler(); 
CustomerErrorHandler errorHandler = new CustomerErrorHandler(); 

InputStream inputStream = new FileInputStream(new File(xmlLocation)); 
Reader reader = new InputStreamReader(inputStream, "UTF-8"); 
InputSource is = new InputSource(reader); 
is.setEncoding("UTF-8"); 
saxParser.setContentHandler(handler); 
saxParser.setErrorHandler(errorHandler); 
saxParser.parse(is); } 

其中CustomerErrorHandler简单

public class CustomerErrorHandler implements ErrorHandler { 

@Override 
public void error(SAXParseException arg0) throws SAXException { 
    System.out.println(arg0.getMessage()); 
} 

@Override 
public void fatalError(SAXParseException arg0) throws SAXException { 
    System.out.println(arg0.getMessage()); 
} 

@Override 
public void warning(SAXParseException arg0) throws SAXException { 
    System.out.println(arg0.getMessage()); 
    } 

} 

有没有人对为什么会发生这种情况,什么我做错了任何指针,以及最重要的是,如何如果这种方法不起作用,是否可以正确地对XML文档进行完整验证?

+0

您使用Xerces的解析器是哪一种? Validatior行为是解析器特有的,特别是在错误和扩展功能方面。 – Ironluca

+0

是的,Xerces 2是默认的。 –

回答

0

这是不是一个真正的答案,这更是一个漫长评论:

将继续在错误的功能是扩展功能,而不是真正的标准。确切的实现在Xerces代码库中确实可用,但可能不容易理解。最小的情况是,从上面的测试中可以看出,在元素上遇到验证错误时,Xerces会忽略验证错误(尽管我确信它会检测格式错误,您可以尝试)直到元素结束为止(如那里在验证这个元素时没有意义,它对于模式是无效的),实际上是跳过整个元素并进入下一个元素并开始验证。这可能是一种行为,因为错误继续不是一个标准,我猜这个实现是在'最好的情况下'的基础上完成的,如果某件事不能被验证,就忽略它并尝试验证下一个元素。

+0

经过调查,我会接受这个答案。 虽然在文档中没有明确说明这一点,但通过挖掘代码,我发现验证器确实不会尝试在与验证异常相同的级别上执行任何操作;由于这个特定的异常发生在complexElement(不是它的子节点)中,所以complexElement的其余部分未被验证。 –

+0

您或许可以提出对Xerces包含在文档中的行为的观察。 – Ironluca