Java Validator在失败时锁定文件 - 我做错了什么?

时间:2011-11-17 16:02:22

标签: java xml validation

我正在尝试针对Java中的模式验证XML文件,问题是如果文件验证失败,则文件将被锁定,直到应用程序终止。如果输入文件有效,则文件不会被锁定,一切都很好。

我正在使用javax.xml.validation.Validatorvalidate()方法。这似乎很简单,并且在验证通过时很好。我只能假设我在错误处理中遗漏了一些东西,但Validator的API似乎没有提供任何有用的东西。任何人都可以阐明我在这里做错了吗?

我已将所有这些简化为下面的独立课程。如果您在扫描仪启动时运行此操作,请检查输入文件,您可以看到它现在已被锁定。如果需要,我可以提供输入和结构文件。

谢谢,

菲尔


import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.net.URI;
import java.util.Scanner;

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;

public class ValidationTest {

    public static void validate(URI xmlLocation, URI schemaLocation) throws Exception {

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

        Source schemaSource = new StreamSource(schemaLocation.toString());
        Schema schema = schemaFactory.newSchema(schemaSource);

        Validator schemaValidator = schema.newValidator();

        StreamSource source = new StreamSource(xmlLocation.getPath());
        schemaValidator.validate( source );
    }


    public static void main(String[] args) throws Exception {
        File srcFile = new File("c:/aaa/MySrc-Broken.xml");
        File schema = new File("c:/aaa/MyStructureDefinition.xsd");

        try {
            ValidationTest.validate(srcFile.toURI(), schema.toURI());
        } catch(Exception e) {
            System.err.println(e);
        }

        // Use a Scanner to pause the thread, so that I can 
        // go and check the file's permissions.
        Scanner scan = new Scanner(System.in);
        scan.nextLine();
    }
}


更新

我有一个黑客提供(坏)解决方案。我将自定义errorHandler添加到schemaValidator。此errorHandler仅将任何错误存储在成员变量中。这意味着验证器将始终成功,从而释放输入文件上的所有锁。但是,然后我必须检查错误处理程序以查看是否有任何错误,然后如果有错误则抛出错误。这不是很好,但确实让我解决了这个问题。

3 个答案:

答案 0 :(得分:3)

请注意,不允许使用StreamSource实例。 (http://docs.oracle.com/javase/1.5.0/docs/api/javax/xml/validation/Validator.html

URL xmlFileURL = xmlFileToCheck.toURI().toURL();
InputStream inputStream = xmlFileURL.openStream();
InputSource is = new InputSource(inputStream);
SAXSource saxSource = new SAXSource(is);

xmlValidator.validate(saxSource);

inputStream.close(); // this is probably important...

答案 1 :(得分:1)

捕获validate()调用中引发的异常,关闭链接到文件的StreamSource对象以释放文件资源,然后将异常抛出到调用方法。

编辑:您可能需要显式检索InputStream以关闭底层文件句柄 - 似乎StreamSource没有定义关闭底层流的显式方法。检查是否得到source.getInputStream()返回的InputStream对象 - 如果是这样,关闭它应该释放文件的任何底层句柄。

答案 2 :(得分:0)

验证程序无法关闭Source。这个可能you are not supposed to use a StreamSource with the validate() method.的唯一原因(但可能还有其他原因,因此您可能需要重新考虑您的方法。)

应用程序需要负责关闭流。为确保发生这种情况,您可以使用finally块。

public static void validate(URI xmlLocation, URI schemaLocation) 
  throws Exception 
{
  SchemaFactory schemaFactory = 
    SchemaFactory.newInstance( "http://www.w3.org/2001/XMLSchema" );
  InputStream sIn = schemaLocation.toURL().openStream();
  try {
    Source schemaSource = new StreamSource(sIn, schemaLocation.toString());
    Schema schema = schemaFactory.newSchema(schemaSource);
    Validator schemaValidator = schema.newValidator();
    InputStream xIn = xmlLocation.toURL().openStream();
    try {
      StreamSource source = new StreamSource(xIn, xmlLocation.toString());
      schemaValidator.validate( source );
    } finally {
      xIn.close();
    }
  } finally {
    sIn.close();
  }
}