2012-02-01 22 views
5

Làm cách nào để xác thực một tệp XML bằng cách sử dụng XSD trong Java? Chúng tôi không biết trước lược đồ. Tôi muốn có thể nhận được schemaLocation, tải xuống XSD, lưu trữ bộ nhớ cache và sau đó thực hiện xác thực thực tế.Xác nhận hợp lệ một XML dựa vào XSD trong Java/Bắt giữ lược đồ Location

Vấn đề là, với javax.xml.parsers.DocumentBuilder/DocumentBuilderFactory lớp học, tôi dường như không thể giữ được số schemaLocation trước. Bí quyết này là gì? Tôi nên xem xét các lớp học nào?

Có lẽ tôi có thể sử dụng API phù hợp hơn? Toàn bộ vấn đề là chúng ta cần phải xác thực động, mà không cần (nhất thiết) có các XSD cục bộ.

Làm cách nào để có thể giữ URL của schemaLocation được xác định trong tệp XSD?

Tôi biết bạn có thể đặt các tính năng/thuộc tính, nhưng đó là một điều khác. Tôi cần lấy số schemaLocation từ XSD trước.

Vui lòng thông báo!

Trả lời

4

Do bạn đang sử dụng Xerces (hoặc mặc định JDK), bạn đã thử đặt tính năng này thành true trên nhà máy: http://apache.org/xml/features/validation/schema. Có những tính năng khác mà bạn có thể chơi với về schemas: http://xerces.apache.org/xerces2-j/features.html

UPDATE 2 (đối với bộ nhớ đệm):

Thực hiện một org.w3c.dom.ls.LSResourceResolver và thiết lập này trên SchemaFactory sử dụng phương pháp setResourceResolver. Trình phân giải này sẽ lấy giản đồ từ bộ nhớ cache hoặc tìm nạp nó từ bất kỳ vị trí nào đề cập đến.

UPDATE 3:

LSResourceresolver dụ (mà tôi nghĩ rằng sẽ là một điểm khởi đầu tốt đẹp cho bạn):

/** 
* Resolves resources from a base URL 
*/ 
public class URLBasedResourceResolver implements LSResourceResolver { 

private static final Logger log = LoggerFactory 
     .getLogger(URLBasedResourceResolver.class); 

private final URI base; 

private final Map<URI, String> nsmap; 

public URLBasedResourceResolver(URL base, Map<URI, String> nsmap) 
     throws URISyntaxException { 
    super(); 
    this.base = base.toURI(); 
    this.nsmap = nsmap; 
} 

@Override 
public LSInput resolveResource(String type, String namespaceURI, 
     String publicId, String systemId, String baseURI) { 
    if (log.isDebugEnabled()) { 
     String msg = String 
       .format("Resolve: type=%s, ns=%s, publicId=%s, systemId=%s, baseUri=%s.", 
         type, namespaceURI, publicId, systemId, baseURI); 
     log.debug(msg); 
    } 
    if (type.equals(XMLConstants.W3C_XML_SCHEMA_NS_URI)) { 
     if (namespaceURI != null) { 
      try { 
       URI ns = new URI(namespaceURI); 
       if (nsmap.containsKey(ns)) 
        return new MyLSInput(base.resolve(nsmap.get(ns))); 
      } catch (URISyntaxException e) { 
       // ok 
      } 
     } 
    } 
    return null; 
} 

} 

Việc thực hiện MyLSInput thực sự nhàm chán:

class MyLSInput implements LSInput { 

private final URI url; 

public MyLSInput(URI url) { 
    super(); 
    this.url = url; 
} 

@Override 
public Reader getCharacterStream() { 
    return null; 
} 

@Override 
public void setCharacterStream(Reader characterStream) { 

} 

@Override 
public InputStream getByteStream() { 
    return null; 
} 

@Override 
public void setByteStream(InputStream byteStream) { 

} 

@Override 
public String getStringData() { 
    return null; 
} 

@Override 
public void setStringData(String stringData) { 

} 

@Override 
public String getSystemId() { 
    return url.toASCIIString(); 
} 

@Override 
public void setSystemId(String systemId) { 
} 

@Override 
public String getPublicId() { 
    return null; 
} 

@Override 
public void setPublicId(String publicId) { 
} 

@Override 
public String getBaseURI() { 
    return null; 
} 

@Override 
public void setBaseURI(String baseURI) { 

} 

@Override 
public String getEncoding() { 
    return null; 
} 

@Override 
public void setEncoding(String encoding) { 

} 

@Override 
public boolean getCertifiedText() { 
    return false; 
} 

@Override 
public void setCertifiedText(boolean certifiedText) { 

} 

} 
+0

Liên quan đến liên kết đầu tiên - Tôi đang sử dụng xerces: 2.10.0 như một phụ thuộc Maven độc lập bên ngoài JDK. Liên kết thứ hai không hoạt động. Tôi không ngại sử dụng một API khác cùng nhau. – carlspring

+0

@carlspring. Xem cập nhật. –

+0

Vâng, trong khi điều này thực sự là chính xác, tôi vẫn không có vị trí của lược đồ, do đó tôi không thể cache nó và tôi cần phải thực hiện bộ nhớ đệm. Vì vậy, tôi thực sự cần phải giữ một 'schemaLocation' đầu tiên. – carlspring