Ken*_*ned 5 java xml eclipse xsd
Java XML Schema 验证 - ResourceResolver 问题
我正在尝试将一个组件构建到一个 Web 应用程序中,该应用程序将根据一组模式验证不同的 XML 文档。
我在 java 包 com.example.xml 中有验证器类,然后我有一个模式 com.example.xml.Schemas 的“包”,它们根据命名空间以及任何包含的模式进行组织,如下所示:
com.example.xml/SchemaValidator.java
com.example.xml.Schemas/2008/07/05/Message.xsd
com.example.xml.Schemas/2008/07/05/Person.xsd
com.example.xml.Schemas/2008/07/05/Address.xsd
com.example.xml.Schemas/2010/09/21/Message.xsd
com.example.xml.Schemas/2010/09/21/Organization.xsd
com.example.xml.Schemas/2010/09/21/Person.xsd
com.example.xml.Schemas/2010/09/21/Address.xsd
Run Code Online (Sandbox Code Playgroud)
所以大多数文档元素都被称为 Message 但在不同的命名空间和不同的内部结构中。通过映射,我可以确定正确架构的位置,然后加载与根元素名称匹配的 XSD - 但为了使解析器能够读取包含的架构,我尝试使用 org.w3c.dom.ls .LSResourceResolver 实现以根据 systemId 获取正确的文件。
public class ResourceResolver implements LSResourceResolver {
private String basePath;
public ResourceResolver( String baseDirectory ){
basePath = baseDirectory;
if( !basePath.endsWith("/")){
basePath += "/";
}
}
@Override
public LSInput resolveResource(String type, String namespaceURI, String publicId, String systemId, String baseURI) {
System.out.println("Resolving: " + type + ", " + namespaceURI + ", " + publicId + ", " + systemId + ", " + baseURI + " (basepath:" + basePath + ")");
String mypath = basePath + systemId;
InputStream resourceAsStream = getClass().getResourceAsStream(mypath);
if( resourceAsStream == null){ System.out.println("Ups! Stream is null"); }
String contents = null;
byte[] bytes = null;
try {
bytes = new byte[resourceAsStream.available()];
resourceAsStream.read(bytes);
contents = new String(bytes, Charset.forName("UTF-8"));
} catch (IOException e) { }
finally{
try { resourceAsStream.close(); }
catch (IOException e) { }
}
Input xmlInput = new Input(resourceAsStream, type, namespaceURI, publicId, systemId, basePath);
xmlInput.setStringData(contents); // avoid problems with inputstream position
return xmlInput;
}
}
Run Code Online (Sandbox Code Playgroud)
我的 ResourceResolver 是这样使用的:
public boolean validate(Document doc, String xsdPath) throws SAXException, IOException, ParserConfigurationException {
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
String rootElmtName = doc.getDocumentElement().getLocalName();
String resourcePath = "/com/example/xml/" + xsdPath ;
InputStream topSchema = getClass().getResourceAsStream(xsdPath + "/" + rootElmtName + ".xsd");
Source schemaSource = new StreamSource(topSchema);
ResourceResolver resolver = new ResourceResolver(resourcePath);
schemaFactory.setResourceResolver(resolver);
Schema schema = schemaFactory.newSchema(schemaSource);
Validator validator = schema.newValidator();
validator.setResourceResolver(resolver);
Source source = new DOMSource(doc);
ValidationErrorHandler handler = new ValidationErrorHandler();
validator.setErrorHandler(handler);
validator.validate(source);
if(handler.hasErrors()){
for( ValidationError e : handler.getErrors()){
log(e);
}
return false;
}
return true;
}
Run Code Online (Sandbox Code Playgroud)
然而,它不起作用!它解析一些架构资源,然后停止我尝试在我的资源解析器中的 Eclipse 中设置断点,并且输入流不为空 - 它指向包含 XSD 的正确文件。因此,Java XML 解析器类中的某些内容必须期待我的解析器的其他行为。
Resolving: http://www.w3.org/2001/XMLSchema, http://com/example/xml/schemas/2005/08/07/, null, Letters.xsd, file:///com/example/xml/Schemas/2005/08/07/Message.xsd (basepath:/com/example/xml/Schemas/2005/08/07/)
Resolving: http://www.w3.org/2001/XMLSchema, http://com/example/xml/schemas/2005/08/07/, null, GeneralElements.xsd, file:///com/example/xml/Schemas/2005/08/07/Message.xsd (basepath:/com/example/xml/Schemas/2005/08/07/)
Resolving: http://www.w3.org/2001/XMLSchema, http://com/example/xml/schemas/2005/08/07/, null, GeneralTypes.xsd, file:///com/example/xml/Schemas/2005/08/07/Message.xsd (basepath:/com/example/xml/Schemas/2005/08/07/)
Exception in thread "main" org.xml.sax.SAXParseException: src-resolve: Cannot resolve the name 'Letters' to a(n) 'group' component.
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:195)
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:131)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:384)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.reportSchemaErr(XSDHandler.java:2537)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.reportSchemaError(XSDHandler.java:2528)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.getGlobalDecl(XSDHandler.java:1472)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDGroupTraverser.traverseLocal(XSDGroupTraverser.java:72)
Run Code Online (Sandbox Code Playgroud)
Message.xsd 的内容有点像这样:
<xs:include schemaLocation="Letters.xsd"/>
<xs:include schemaLocation="GeneralElements.xsd"/>
<xs:include schemaLocation="GeneralTypes.xsd"/>
<xs:element name="Message">
Run Code Online (Sandbox Code Playgroud)
-并且 Letters.xsd 还包含
<xs:include schemaLocation="GeneralElements.xsd"/>
<xs:include schemaLocation="GeneralTypes.xsd"/>
<xs:group name="Letters">
Run Code Online (Sandbox Code Playgroud)
大纲是 ResourceResolver 和 Input 类来自另一个 SO post - 所以我可能误解了一些东西。
这是我创建资源解析器的正确方式,还是我完全错过了什么?
| 归档时间: |
|
| 查看次数: |
2916 次 |
| 最近记录: |