根据Java中的XSD验证XML /获取模式位置
问题描述:
如何在Java中使用XSD验证XML文件?我们事先不知道这个模式。我希望能够获得schemaLocation
,下载XSD,缓存它,然后执行实际验证。根据Java中的XSD验证XML /获取模式位置
问题是,与javax.xml.parsers.DocumentBuilder
/DocumentBuilderFactory
类我似乎无法提前获得schemaLocation
持有。这有什么诀窍?我应该考虑哪些课程?
也许有更适合我的API可以使用?整个问题是,我们需要动态验证,没有(必然)在本地拥有XSD。
如何获取在XSD文件中定义的schemaLocation
的URL?
我知道你可以设置特征/属性,但这是不同的事情。我需要先从XSD获取schemaLocation
。
请指教!
答
鉴于您使用的是Xerces(或JDK默认设置),您是否尝试在工厂上将此功能设置为true:http://apache.org/xml/features/validation/schema。还有其他的功能,你可以提供关于模式玩法:http://xerces.apache.org/xerces2-j/features.html
更新2(缓存):
实现一个org.w3c.dom.ls.LSResourceResolver
和使用setResourceResolver
方法来设置这个就SchemaFactory
。该解析器将从缓存中获取架构或从位置引用的任何位置获取架构。
更新3:
LSResourceResolver的例子(我想这将是你一个很好的起点):
/**
* 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的实现是很无聊:
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) {
}
}
关于第一个链接 - 我使用xerces:2.10.0作为JDK之外的独立Maven依赖项。第二个链接不起作用。 我不介意一起使用另一个API。 – carlspring 2012-02-01 14:07:21
@carlspring。查看更新。 – 2012-02-01 14:52:57
是的,虽然这确实是正确的,我仍然没有模式的位置,因此我无法缓存它,我需要实现缓存。因此,我真的需要先掌握'schemaLocation'。 – carlspring 2012-02-01 15:13:47