問題描述
如何在 Java 中使用 XSD 驗證 XML 文件?我們事先并不知道模式.我希望能夠獲取 schemaLocation
、下載 XSD、緩存它,然后執行實際驗證.
How can one validate an XML file using an XSD in Java? We don't know the schema in advance. I would like to be able to get the schemaLocation
, download the XSD, cache it and then perform the actual validation.
問題是,使用 javax.xml.parsers.DocumentBuilder
/DocumentBuilderFactory
類我似乎無法獲得 schemaLocation
提前.這有什么訣竅?我應該研究哪些課程?
The problem is, that with javax.xml.parsers.DocumentBuilder
/DocumentBuilderFactory
classes I can't seem to be able to get a hold of the schemaLocation
in advance. What's the trick for this? Which classes should I look into?
也許我可以使用更合適的 API?整個問題是我們需要動態驗證,而不是(必須)在本地擁有 XSD.
Perhaps there's a more suitable API I can use? The whole problem is that we need to validate dynamically, without (necessarily) having the XSDs locally.
如何獲取 XSD 文件中定義的 schemaLocation
的 URL?
How could one get a hold of the URL of schemaLocation
defined in the XSD file?
我知道您可以設置功能/屬性,但那是另一回事.我需要先從 XSD 中獲取 schemaLocation
.
I know you can set features/attributes, but that's a different thing. I need to get the schemaLocation
from the XSD first.
請指教!
推薦答案
鑒于您使用的是 Xerces(或 JDK 默認),您是否嘗試過在出廠時將此功能設置為 true:http://apache.org/xml/features/validation/schema.您還可以使用有關架構的其他功能:http://xerces.apache.org/xerces2-j/features.html
Given that you are using Xerces (or JDK default), have you tried setting this feature to true on the factory: http://apache.org/xml/features/validation/schema. There are other features that you can play with regarding schemas: http://xerces.apache.org/xerces2-j/features.html
更新 2(用于緩存):
UPDATE 2 (for caching):
實現一個 org.w3c.dom.ls.LSResourceResolver
并使用 setResourceResolver
方法在 SchemaFactory
上設置它.這個解析器要么從緩存中獲取架構,要么從位置所指的任何地方獲取它.
Implement a org.w3c.dom.ls.LSResourceResolver
and set this on the SchemaFactory
using the setResourceResolver
method. This resolver would either get the schema from cache or fetch it from wherever the location refers to.
更新 3:
LSResourceresolver 示例(我認為這對您來說是一個很好的起點):
LSResourceresolver example (which I think will be a good starting point for you):
/**
* 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;
}
}
MyLSInput 的實現真的很無聊:
The implementation of MyLSInput is really boring:
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) {
}
}
這篇關于在 Java 中針對 XSD 驗證 XML/獲取 schemaLocation的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!