2011-11-17 28 views
5

Tôi đang cố gắng xác nhận hợp lệ tệp XML dựa vào lược đồ trong Java và vấn đề là nếu xác thực tệp không thành công, thì tệp sẽ bị khóa cho đến khi ứng dụng chấm dứt. Nếu tệp đầu vào hợp lệ thì tệp không bị khóa và mọi thứ đều ổn.Trình xác thực Java khóa tệp khi không thành công - tôi đang làm gì sai?

Tôi đang sử dụng phương thức javax.xml.validation.Validatorvalidate(). Điều này có vẻ đơn giản, đủ và là tốt khi xác nhận đi. Tôi chỉ có thể giả định rằng tôi đang thiếu một cái gì đó trong xử lý lỗi của tôi, nhưng API cho Validator dường như không cung cấp bất cứ thứ gì có ích. Có ai có thể làm sáng tỏ những gì tôi đang làm sai ở đây không?

Tôi đã đơn giản hóa tất cả điều này thành một lớp độc lập bên dưới. Nếu bạn chạy điều này thì tại thời điểm khi máy quét bắt đầu, hãy kiểm tra tệp đầu vào và bạn có thể thấy rằng nó đang bị khóa. Tôi có thể cung cấp một tập tin đầu vào và cấu trúc nếu bạn cần nó.

Cảm ơn,

Phil

 

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(); 
    } 
} 

 

Cập nhật:

Tôi có một chút của một hack mà cung cấp một (xấu) giải pháp. Tôi thêm một errorHandler tùy chỉnh vào schemaValidator. ErrorHandler này chỉ lưu trữ bất kỳ lỗi nào trong một biến thành viên. Điều này có nghĩa là trình duyệt tính hợp lệ sẽ luôn thành công và do đó giải phóng tất cả các khóa trên tệp đầu vào. Tuy nhiên sau đó tôi phải kiểm tra xử lý lỗi để xem nếu có bất kỳ lỗi nào và sau đó ném một lỗi nếu có. Đây không phải là tuyệt vời nhưng làm cho tôi tròn vấn đề này.

Trả lời

1

bắt ngoại lệ được nêu trong lệnh validate(), đóng đối tượng StreamSource được liên kết với tệp của bạn để giải phóng tài nguyên tệp và sau đó ném ngoại lệ lên theo phương thức gọi của bạn.

chỉnh sửa: bạn có thể cần truy xuất InputStream một cách rõ ràng để đóng trình xử lý tệp cơ bản - có vẻ như StreamSource không xác định cách rõ ràng để đóng luồng cơ bản. Kiểm tra xem bạn có nhận được đối tượng InputStream được trả về bởi source.getInputStream() - nếu vậy, việc đóng này sẽ giải phóng bất kỳ xử lý cơ bản nào cho tệp của bạn.

+1

Điều này có vẻ như là một giải pháp cho một lỗi - vâng? –

+0

Hoặc đó là nguyên nhân gây ra bởi OP sử dụng các lớp không chính xác. Tôi đã không sử dụng StreamSources cá nhân nên không có thêm lời khuyên để cung cấp - nhưng một tập tin bị khóa tương đương với một tập tin chưa được phát hành, và ứng cử viên duy nhất tôi thấy ở trên là đối tượng StreamSource. – mcfinnigan

+1

Nó có vẻ giống như một lỗi ... "nếu xác nhận của tập tin không thành công, sau đó tập tin sẽ bị khóa cho đến khi ứng dụng chấm dứt. Nếu tập tin đầu vào là hợp lệ thì tập tin không bị khóa và mọi thứ đều ổn." IMHO tập tin phải luôn luôn bị khóa hoặc phát hành độc lập với kết quả.Vui lòng sửa quan niệm của tôi nếu tôi sai – Pitelk

3

Lưu ý rằng trường hợp StreamSource không được phép. (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... 
+0

Không có giới hạn nào trong JDK mới nhất, vẫn còn lỗi này. Bạn phải khởi tạo một FileInputStream và đóng nó trong trình xử lý ngoại lệ. :( –

+0

Điều này đã giúp. – puspen

0

Các validator không có cách nào để đóng một Source. Điều này có thể là lý do duy nhất you are not supposed to use a StreamSource with the validate() method. (Nhưng có thể có những người khác, vì vậy bạn có thể muốn xem xét lại cách tiếp cận của mình.)

Ứng dụng sẽ cần phải chịu trách nhiệm đóng các luồng. Để chắc chắn điều này xảy ra, bạn có thể sử dụng khối 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(); 
    } 
} 
Các vấn đề liên quan