如何使用导入另一个模式文件的模式文件验证 XML?
•浏览 1
How do I validate an XML with a schema file that imports another schema file?
我想根据这个模式(在 zip 里面)验证 XML 文件;它导入另外两个 XSD 文件。
<import namespace="http://www.w3.org/2000/09/xmldsig#"
schemaLocation="xmldsig-core-schema.xsd"/>
<import namespace="http://www.w3.org/2001/04/xmlenc#"
schemaLocation="xenc-schema.xsd"/>
Src-resolve: Cannot Resolve The Name 'xenc:EncryptedData' To A(n) 'element Declaration' Component.jaxbContext = JAXBContext.newInstance(type.getRequestType().getPackage().getName());
Unmarshaller um = jaxbContext.createUnmarshaller();
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = sf.newSchema(new StreamSource(this.getClass().getResourceAsStream("/xsd/" + type.getXsdName())));
um.setSchema(schema);
root = um.unmarshal(new StreamSource(new ByteArrayInputStream(xmlData)), type.getRequestType());
SchemaFactory schemaFactory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
Schema compiledSchema = schemaFactory.newSchema(new SOTests().getClass()
.getClassLoader().getResource("generalInvoiceRequest_430.xsd"));
Validator validator = compiledSchema.newValidator();
try {
validator.validate(new StreamSource("D:\\\\...\\\\dentist_ersred_TG_430.xml"));
System.out.println("Valid.");
}
catch (SAXException ex) {
System.out.print("Not valid because..." + ex.getMessage());
}
Valid.Not valid because...cvc-complex-type.2.4.a: Invalid content was found starting with element 'wrong'. One of '{"http://www.forum-datenaustausch.ch/invoice":processing}' is expected.
这两个文件也可以在这里找到:
- http://www.forum-datenaustausch.ch/xmldsig-core-schema.zip
- http://www.forum-datenaustausch.ch/xenc-schema.zip。
验证时,我收到此错误:
<import namespace="http://www.w3.org/2000/09/xmldsig#"
schemaLocation="xmldsig-core-schema.xsd"/>
<import namespace="http://www.w3.org/2001/04/xmlenc#"
schemaLocation="xenc-schema.xsd"/>
Src-resolve: Cannot Resolve The Name 'xenc:EncryptedData' To A(n) 'element Declaration' Component.jaxbContext = JAXBContext.newInstance(type.getRequestType().getPackage().getName());
Unmarshaller um = jaxbContext.createUnmarshaller();
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = sf.newSchema(new StreamSource(this.getClass().getResourceAsStream("/xsd/" + type.getXsdName())));
um.setSchema(schema);
root = um.unmarshal(new StreamSource(new ByteArrayInputStream(xmlData)), type.getRequestType());
SchemaFactory schemaFactory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
Schema compiledSchema = schemaFactory.newSchema(new SOTests().getClass()
.getClassLoader().getResource("generalInvoiceRequest_430.xsd"));
Validator validator = compiledSchema.newValidator();
try {
validator.validate(new StreamSource("D:\\\\...\\\\dentist_ersred_TG_430.xml"));
System.out.println("Valid.");
}
catch (SAXException ex) {
System.out.print("Not valid because..." + ex.getMessage());
}
Valid.Not valid because...cvc-complex-type.2.4.a: Invalid content was found starting with element 'wrong'. One of '{"http://www.forum-datenaustausch.ch/invoice":processing}' is expected.
我的验证/解组代码如下所示(使用 moxy 作为 JAXB 提供程序):
<import namespace="http://www.w3.org/2000/09/xmldsig#"
schemaLocation="xmldsig-core-schema.xsd"/>
<import namespace="http://www.w3.org/2001/04/xmlenc#"
schemaLocation="xenc-schema.xsd"/>
Src-resolve: Cannot Resolve The Name 'xenc:EncryptedData' To A(n) 'element Declaration' Component.jaxbContext = JAXBContext.newInstance(type.getRequestType().getPackage().getName());
Unmarshaller um = jaxbContext.createUnmarshaller();
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = sf.newSchema(new StreamSource(this.getClass().getResourceAsStream("/xsd/" + type.getXsdName())));
um.setSchema(schema);
root = um.unmarshal(new StreamSource(new ByteArrayInputStream(xmlData)), type.getRequestType());
SchemaFactory schemaFactory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
Schema compiledSchema = schemaFactory.newSchema(new SOTests().getClass()
.getClassLoader().getResource("generalInvoiceRequest_430.xsd"));
Validator validator = compiledSchema.newValidator();
try {
validator.validate(new StreamSource("D:\\\\...\\\\dentist_ersred_TG_430.xml"));
System.out.println("Valid.");
}
catch (SAXException ex) {
System.out.print("Not valid because..." + ex.getMessage());
}
Valid.Not valid because...cvc-complex-type.2.4.a: Invalid content was found starting with element 'wrong'. One of '{"http://www.forum-datenaustausch.ch/invoice":processing}' is expected.
在你问类型做什么之前:我编写了可以从 http://www.forum-datenaustausch.ch/ 导入所有类型发票的代码。但是 4.3 及更高版本使用两个附加的模式文件。如何验证 XML 文件?
看看这篇文章接受的答案。根据我在您的帖子中看到的一点点,并且据我所记得,您加载 XSD 的方式的问题与按照您的方式进行操作的事实有关,工厂没有得到base uri,因此它不能应用其智能来解析对其他两个 XSD 的引用。我必须假设您的其他两个 XSD 也作为资源打包在同一个 jar 中,在同一个目录中。
我不得不承认我对错误消息很感兴趣,这似乎暗示它加载的模式是有效的,所以它可能是一个 XML 问题;如果上述方法对您没有帮助,那么您也应该考虑发布有问题的 XML...
更新:根据我的评论,它按描述工作。请参阅下面的代码片段:
<import namespace="http://www.w3.org/2000/09/xmldsig#"
schemaLocation="xmldsig-core-schema.xsd"/>
<import namespace="http://www.w3.org/2001/04/xmlenc#"
schemaLocation="xenc-schema.xsd"/>
Src-resolve: Cannot Resolve The Name 'xenc:EncryptedData' To A(n) 'element Declaration' Component.jaxbContext = JAXBContext.newInstance(type.getRequestType().getPackage().getName());
Unmarshaller um = jaxbContext.createUnmarshaller();
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = sf.newSchema(new StreamSource(this.getClass().getResourceAsStream("/xsd/" + type.getXsdName())));
um.setSchema(schema);
root = um.unmarshal(new StreamSource(new ByteArrayInputStream(xmlData)), type.getRequestType());
SchemaFactory schemaFactory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
Schema compiledSchema = schemaFactory.newSchema(new SOTests().getClass()
.getClassLoader().getResource("generalInvoiceRequest_430.xsd"));
Validator validator = compiledSchema.newValidator();
try {
validator.validate(new StreamSource("D:\\\\...\\\\dentist_ersred_TG_430.xml"));
System.out.println("Valid.");
}
catch (SAXException ex) {
System.out.print("Not valid because..." + ex.getMessage());
}
Valid.Not valid because...cvc-complex-type.2.4.a: Invalid content was found starting with element 'wrong'. One of '{"http://www.forum-datenaustausch.ch/invoice":processing}' is expected.
您不需要加载比第一个 XSD 更多的内容,也不应该加载,因为所有导入都提供了架构位置的提示。
XSD 文件都在生成的 jar 中的同一目录中,它们必须是,因为用于导入的相对 URI 指示相同的父级。
带有从这里下载的文件之一的程序输出:
<import namespace="http://www.w3.org/2000/09/xmldsig#"
schemaLocation="xmldsig-core-schema.xsd"/>
<import namespace="http://www.w3.org/2001/04/xmlenc#"
schemaLocation="xenc-schema.xsd"/>
Src-resolve: Cannot Resolve The Name 'xenc:EncryptedData' To A(n) 'element Declaration' Component.jaxbContext = JAXBContext.newInstance(type.getRequestType().getPackage().getName());
Unmarshaller um = jaxbContext.createUnmarshaller();
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = sf.newSchema(new StreamSource(this.getClass().getResourceAsStream("/xsd/" + type.getXsdName())));
um.setSchema(schema);
root = um.unmarshal(new StreamSource(new ByteArrayInputStream(xmlData)), type.getRequestType());
SchemaFactory schemaFactory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
Schema compiledSchema = schemaFactory.newSchema(new SOTests().getClass()
.getClassLoader().getResource("generalInvoiceRequest_430.xsd"));
Validator validator = compiledSchema.newValidator();
try {
validator.validate(new StreamSource("D:\\\\...\\\\dentist_ersred_TG_430.xml"));
System.out.println("Valid.");
}
catch (SAXException ex) {
System.out.print("Not valid because..." + ex.getMessage());
}
Valid.Not valid because...cvc-complex-type.2.4.a: Invalid content was found starting with element 'wrong'. One of '{"http://www.forum-datenaustausch.ch/invoice":processing}' is expected.
并引入无效内容后:
<import namespace="http://www.w3.org/2000/09/xmldsig#"
schemaLocation="xmldsig-core-schema.xsd"/>
<import namespace="http://www.w3.org/2001/04/xmlenc#"
schemaLocation="xenc-schema.xsd"/>
Src-resolve: Cannot Resolve The Name 'xenc:EncryptedData' To A(n) 'element Declaration' Component.jaxbContext = JAXBContext.newInstance(type.getRequestType().getPackage().getName());
Unmarshaller um = jaxbContext.createUnmarshaller();
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = sf.newSchema(new StreamSource(this.getClass().getResourceAsStream("/xsd/" + type.getXsdName())));
um.setSchema(schema);
root = um.unmarshal(new StreamSource(new ByteArrayInputStream(xmlData)), type.getRequestType());
SchemaFactory schemaFactory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
Schema compiledSchema = schemaFactory.newSchema(new SOTests().getClass()
.getClassLoader().getResource("generalInvoiceRequest_430.xsd"));
Validator validator = compiledSchema.newValidator();
try {
validator.validate(new StreamSource("D:\\\\...\\\\dentist_ersred_TG_430.xml"));
System.out.println("Valid.");
}
catch (SAXException ex) {
System.out.print("Not valid because..." + ex.getMessage());
}
Valid.Not valid because...cvc-complex-type.2.4.a: Invalid content was found starting with element 'wrong'. One of '{"http://www.forum-datenaustausch.ch/invoice":processing}' is expected.
我对阅读本文的人的建议:
- 使用 getResource() 获取 URL;正如我在上面所说的,StreamResource 没有基本 URI,因此不能取消引用根据您的 xsd:import schemaLocation 属性的相对引用。
- 当明确提供时,让架构/工厂为您加载。
- 确保提供时,相对引用与 jar 文件中的文件夹结构相匹配。
这里有类似的问题。我尝试将 GeneralInvoice 导入集成软件。
- Parser 不喜欢导入模式开头的 DOCTYPE 标记。解决方案:删除 DOCTYPE 部分。
- 解析器不喜欢 anyAttribute、anyURI 等。解决方案:将 anyURI 更改为字符串并通过添加注释来删除其他内容。
- 必须先导入 xenc 和 xwldsig xsd\\,然后在第二步中导入 GeneralInvoice。
希望对你有帮助