- 浏览: 122530 次
- 性别:
- 来自: 北京
最新评论
-
jamesatcaas:
您好,这篇文章很有参考意义。我照着样例做了,但报告错误,如下: ...
XML validation for multiple schemas 验证使用多个XSD schema的XML文件 -
Welcome鹏友:
为什么用你的代码,我输出的结果是这样的:
<?xml v ...
JAXB:使用annotation绑定XML(xmlns) -
jarip:
不错,很有参考价值,赞一个!!!
XML validation for multiple schemas 验证使用多个XSD schema的XML文件 -
ultime:
[b][/b][i][/i][u][/u][/color][s ...
10个线程同步处理1000行消息 -
qachenzude:
buxing~~~
HtmlParser EncodingChangeException: character mismatch
很多情况下我们为了优化XSD文件的可读性和可维护性,以及复用等问题的时候我们需要将schema文件拆分成多个,本文将着重关注于使用多个schema文件验证单一XML文件的问题(注: XML validation for multiple schemas)
下面将通过以下几个步骤演示如何使用多个schema(XSD)文件验证单一XML文件
1. 创建需要被验证的XML文件
2. 根据XML反向创建XSD文件
3. 使用多个schema验证XML文件
4. 运行测试
现在将逐步展开演示:
1. 创建需要被验证的XML文件
<?xml version="1.0" encoding="utf-8" ?> <employees xmlns:admin="http://www.company.com/management/employees/admin"> <admin:employee> <admin:userId>johnsmith@company.com</admin:userId> <admin:password>abc123_</admin:password> <admin:name>John Smith</admin:name> <admin:age>24</admin:age> <admin:gender>Male</admin:gender> </admin:employee> <admin:employee> <admin:userId>christinechen@company.com</admin:userId> <admin:password>123456</admin:password> <admin:name>Christine Chen</admin:name> <admin:age>27</admin:age> <admin:gender>Female</admin:gender> </admin:employee> </employees>
2. 根据XML反向创建XSD文件
注:本文是反向生成的XSD文件,当然您可能是已经有XSD文件,那就可以直接跳过第二步了。
通过观察employees.xml的格式我们可以反向的创建出employees.xsd文件,但是为了快捷起见,我们可以选择使用转换工具(XML to XSD)来完成这项工作,这里我将使用trang:http://www.thaiopensource.com/relaxng/trang.html
首先下载最新版的trang.jar文件,然后将employees.xml和trang.jar放在同一个目录下,运行如下命令行:
java -jar trang.jar employees.xml employees.xsd
运行之后将会在当前目录下生成两个XSD文件:employees.xsd, admin.xsd, 如下:
employees.xsd
<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" xmlns:admin="http://www.company.com/management/employees/admin"> <xs:import namespace="http://www.company.com/management/employees/admin" schemaLocation="admin.xsd"/> <xs:element name="employees"> <xs:complexType> <xs:sequence> <xs:element maxOccurs="unbounded" ref="admin:employee"/> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>
admin.xsd
<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://www.company.com/management/employees/admin" xmlns:admin="http://www.company.com/management/employees/admin"> <xs:import schemaLocation="employees.xsd"/> <xs:element name="employee"> <xs:complexType> <xs:sequence> <xs:element ref="admin:userId"/> <xs:element ref="admin:password"/> <xs:element ref="admin:name"/> <xs:element ref="admin:age"/> <xs:element ref="admin:gender"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="userId" type="xs:string"/> <xs:element name="password" type="xs:NMTOKEN"/> <xs:element name="name" type="xs:string"/> <xs:element name="age" type="xs:integer"/> <xs:element name="gender" type="xs:NCName"/> </xs:schema>
当然你也可以自己手动的去书写XSD文件。
3. 使用多个schema验证XML文件
如果想验证使用单一shema的XML,应该不会遇到太多问题,示例如下:
public static boolean validateSingleSchema(File xml, File xsd) { boolean legal = false; try { SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); Schema schema = sf.newSchema(xsd); Validator validator = schema.newValidator(); validator.validate(new StreamSource(xml)); legal = true; } catch (Exception e) { legal = false; log.error(e.getMessage()); } return legal; }
但是当使用多个schema验证的时候会导致无法加载classpath外部的使用<xs:import>/<xs:include>加载的XSD文件,导致如下error message:
org.xml.sax.SAXParseException: src-resolve: Cannot resolve the name 'admin:employee' to a(n) 'element declaration' component.
为了解决这个问题我们需要使用LSResourceResolver, SchemaFactory在解析shcema的时候可以使用LSResourceResolver加载外部资源。
代码如下:
package com.javaeye.terrencexu.jaxb; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; import java.io.Reader; import java.net.URI; import java.net.URISyntaxException; import org.apache.log4j.Logger; import org.w3c.dom.ls.LSInput; import org.w3c.dom.ls.LSResourceResolver; /** * * Implement LSResourceResolver to customize resource resolution when parsing schemas. * <p> * SchemaFactory uses a LSResourceResolver when it needs to locate external resources * while parsing schemas, although exactly what constitutes "locating external resources" * is up to each schema language. * </p> * <p> * For example, for W3C XML Schema, this includes files <include>d or <import>ed, * and DTD referenced from schema files, etc. *</p> * */ class SchemaResourceResolver implements LSResourceResolver { private static final Logger log = Logger.getLogger(SchemaResourceResolver.class); /** * * Allow the application to resolve external resources. * * <p> * The LSParser will call this method before opening any external resource, including * the external DTD subset, external entities referenced within the DTD, and external * entities referenced within the document element (however, the top-level document * entity is not passed to this method). The application may then request that the * LSParser resolve the external resource itself, that it use an alternative URI, * or that it use an entirely different input source. * </p> * * <p> * Application writers can use this method to redirect external system identifiers to * secure and/or local URI, to look up public identifiers in a catalogue, or to read * an entity from a database or other input source (including, for example, a dialog box). * </p> */ public LSInput resolveResource(String type, String namespaceURI, String publicId, String systemId, String baseURI) { log.info("\n>> Resolving " + "\n" + "TYPE: " + type + "\n" + "NAMESPACE_URI: " + namespaceURI + "\n" + "PUBLIC_ID: " + publicId + "\n" + "SYSTEM_ID: " + systemId + "\n" + "BASE_URI: " + baseURI + "\n"); String schemaLocation = baseURI.substring(0, baseURI.lastIndexOf("/") + 1); if(systemId.indexOf("http://") < 0) { systemId = schemaLocation + systemId; } LSInput lsInput = new LSInputImpl(); URI uri = null; try { uri = new URI(systemId); } catch (URISyntaxException e) { e.printStackTrace(); } File file = new File(uri); FileInputStream is = null; try { is = new FileInputStream(file); } catch (FileNotFoundException e) { e.printStackTrace(); } lsInput.setSystemId(systemId); lsInput.setByteStream(is); return lsInput; } /** * * Represents an input source for data * */ class LSInputImpl implements LSInput { private String publicId; private String systemId; private String baseURI; private InputStream byteStream; private Reader charStream; private String stringData; private String encoding; private boolean certifiedText; public LSInputImpl() {} public LSInputImpl(String publicId, String systemId, InputStream byteStream) { this.publicId = publicId; this.systemId = systemId; this.byteStream = byteStream; } public String getBaseURI() { return baseURI; } public InputStream getByteStream() { return byteStream; } public boolean getCertifiedText() { return certifiedText; } public Reader getCharacterStream() { return charStream; } public String getEncoding() { return encoding; } public String getPublicId() { return publicId; } public String getStringData() { return stringData; } public String getSystemId() { return systemId; } public void setBaseURI(String baseURI) { this.baseURI = baseURI; } public void setByteStream(InputStream byteStream) { this.byteStream = byteStream; } public void setCertifiedText(boolean certifiedText) { this.certifiedText = certifiedText; } public void setCharacterStream(Reader characterStream) { this.charStream = characterStream; } public void setEncoding(String encoding) { this.encoding = encoding; } public void setPublicId(String publicId) { this.publicId = publicId; } public void setStringData(String stringData) { this.stringData = stringData; } public void setSystemId(String systemId) { this.systemId = systemId; } } }
最后要做的事情就是创建一个validator去封装XML验证的逻辑代码, 如下:
package com.javaeye.terrencexu.jaxb; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.StringWriter; import java.util.List; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.Source; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamSource; import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; import javax.xml.validation.Validator; import org.apache.log4j.Logger; import org.xml.sax.SAXException; public final class XMLParser { private static final Logger log = Logger.getLogger(XMLParser.class); private XMLParser() {} public static boolean validateWithSingleSchema(File xml, File xsd) { boolean legal = false; try { SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); Schema schema = sf.newSchema(xsd); Validator validator = schema.newValidator(); validator.validate(new StreamSource(xml)); legal = true; } catch (Exception e) { legal = false; log.error(e.getMessage()); } return legal; } public static boolean validateWithMultiSchemas(InputStream xml, List<File> schemas) { boolean legal = false; try { Schema schema = createSchema(schemas); Validator validator = schema.newValidator(); validator.validate(new StreamSource(xml)); legal = true; } catch(Exception e) { legal = false; log.error(e.getMessage()); } return legal; } /** * Create Schema object from the schemas file. * * @param schemas * @return * @throws ParserConfigurationException * @throws SAXException * @throws IOException */ private static Schema createSchema(List<File> schemas) throws ParserConfigurationException, SAXException, IOException { SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); SchemaResourceResolver resourceResolver = new SchemaResourceResolver(); sf.setResourceResolver(resourceResolver); Source[] sources = new Source[schemas.size()]; DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); docFactory.setValidating(false); docFactory.setNamespaceAware(true); DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); for(int i = 0; i < schemas.size(); i ++) { org.w3c.dom.Document doc = docBuilder.parse(schemas.get(i)); DOMSource stream = new DOMSource(doc, schemas.get(i).getAbsolutePath()); sources[i] = stream; } return sf.newSchema(sources); } }
4. 运行测试
public static void testValidate() throws SAXException, FileNotFoundException { InputStream xml = new FileInputStream(new File("C:\\eclipse\\workspace1\\JavaStudy\\test\\employees.xml")); List<File> schemas = new ArrayList<File>(); schemas.add(new File("C:\\eclipse\\workspace1\\JavaStudy\\test\\employees.xsd")); schemas.add(new File("C:\\eclipse\\workspace1\\JavaStudy\\test\\admin.xsd")); XMLParser.validateWithMultiSchemas(xml, schemas); }
注:如果两个schema文件在同一个目录下,那么可以只传递一个主schema文件(employees.xsd)即可, SchemaResourceResolver会帮我们加载admin.xsd
评论
XML文件: E:\test2\employees.xsd 通过XSD文件:E:\test2\admin.xml检验失败。
原因: s4s-elt-schema-ns: 元素 'employees' 的名称空间必须来自方案名称空间 'http://www.w3.org/2001/XMLSchema'。
org.xml.sax.SAXParseException; s4s-elt-schema-ns: 元素 'employees' 的名称空间必须来自方案名称空间 'http://www.w3.org/2001/XMLSchema'。
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:198)
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:134)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:437)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:347)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.reportSchemaErr(XSDHandler.java:4166)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.reportSchemaError(XSDHandler.java:4145)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSAttributeChecker.reportSchemaError(XSAttributeChecker.java:1568)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSAttributeChecker.checkAttributes(XSAttributeChecker.java:994)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSAttributeChecker.checkAttributes(XSAttributeChecker.java:962)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDocumentInfo.<init>(XSDocumentInfo.java:106)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.constructTrees(XSDHandler.java:782)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.parseSchema(XSDHandler.java:620)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.loadSchema(XMLSchemaLoader.java:616)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.loadGrammar(XMLSchemaLoader.java:574)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.loadGrammar(XMLSchemaLoader.java:540)
at com.sun.org.apache.xerces.internal.jaxp.validation.XMLSchemaFactory.newSchema(XMLSchemaFactory.java:252)
at nstl.xml.schema.validator.XMLValidatorWithMultiSchemas.createSchema(XMLValidatorWithMultiSchemas.java:319)
at nstl.xml.schema.validator.XMLValidatorWithMultiSchemas.validateWithMultiSchemas(XMLValidatorWithMultiSchemas.java:60)
at nstl.xml.schema.validator.XMLValidatorWithMultiSchemas.main(XMLValidatorWithMultiSchemas.java:49)
发表评论
-
Dom4J: Vistor模式替换XML中的正则表达式
2010-07-26 12:50 2570今天介绍一个如何通过Dom4J的Visitor模式替换XML文 ... -
在Java中如何读取UTF-8格式的XML文件 - How to read UTF-8 XML file in Java
2010-07-06 17:28 5415在使用JAXB unmarshal XML的时候碰到了一个异常 ... -
JAXB: 通过schema验证XML文件
2010-07-01 18:21 4213接上文 JAXB:使用annotation绑定XML(xmln ... -
JAXB:使用annotation绑定XML(xmlns)
2010-06-29 22:23 15364在java开发中使用XML几乎是每个程序员都会碰到的,目前可供 ...
相关推荐
Java XML Validation API是Java平台中用于验证XML文档的重要工具,它是Java API for XML Processing (JAXP)的一部分。XML(eXtensible Markup Language)是一种用于标记数据的标准格式,广泛应用于数据交换、配置...
在Java中,XML Schema(XSD)用于定义和验证XML文档的结构和数据类型,确保文档遵循特定的规范。XML Schema文档使用XML语法定义了一系列规则,这些规则描述了有效XML文档应该具有的元素、属性、数据类型以及它们之间...
在Java中,XML Schema的验证可以使用javax.xml.validation包,提供了独立于模式语言的验证服务接口。该包提供了三个类来验证文档:SchemaFactory、Schema和Validator。 在实际应用中,XML Schema可以用于: 1. ...
XML Schema,简称XSD,是一种用于定义XML文档结构和数据类型的规范。`XmlSchema-1.4.6.jar` 是一个包含Java绑定的XML Schema API的库,它为处理XML Schema文档提供了支持。在开发Web服务客户端时,尤其是与基于SOAP...
"xmlschema-1.4.5.jar.zip"是一个包含XML Schema相关实现的Java类库,主要用于处理和验证XML文档是否符合特定的XSD规范。 在Java环境中,`xmlschema-1.4.5.jar`是一个关键组件,它提供了一系列API供开发者使用,...
为了确保XML文档遵循特定的结构和规则,我们可以使用XML Schema Definition (XSD) 文件来定义和验证XML文档的结构。本篇文章将深入探讨如何使用Java中的SAXParser和SAXParserFactory类来验证XML文件是否符合指定的...
1. **创建XSD文件**:定义一个XSD文件,其中包含了XML文档必须遵循的规则。这包括元素、属性、数据类型、顺序和约束等。 2. **配置Castor校验**:在Castor中,可以开启XSD校验。在`mapping.xml`文件中,添加`...
通过`newSchema()`方法,你可以加载一个XSD文件,然后将其与待验证的XML文件关联。 4. **创建DocumentBuilder**: 使用`DocumentBuilderFactory`创建的`DocumentBuilder`,我们可以将其与之前创建的`Schema`关联,...
XML(eXtensible Markup Language)是一种用于标记数据的语言,广泛应用于软件开发、数据交换、配置文件等多个领域。在VC++(Visual C++)环境中,处理XML文档通常涉及到读取、解析、验证和生成XML数据。本文将深入...
在Struts2框架中,`validation.xml`是用于定义数据校验规则的重要配置文件,它允许开发者对Action类中的字段进行各种格式的验证,确保数据的完整性和正确性。通过`validation.xml`,我们可以实现对日期、字符、数字...
除了 DTD,XML 还可以使用 XSD(XML Schema Definition)进行更复杂的结构验证。XSD 提供了更强大的类型系统,包括数据类型和复杂结构的定义。在 Java 中,你可以使用 `javax.xml.validation` 包中的工具来验证 XSD...
标题中的“xsd通过java验证科学计数法”指的是使用XML Schema Definition (XSD) 文件来校验XML文档中科学计数法的正确性,并通过Java编程语言实现这一过程。XSD是XML的一种标准,用于定义XML文档的结构和数据类型,...
在实际应用中,XML Schema通常以`.xsd`文件形式存在,该文件包含了对XML文档结构的完整描述。要验证XML文档是否符合Schema,可以使用XML解析器或编程语言库进行操作。例如,在Java中,可以使用`javax.xml.validation...
通过使用`XMLSchema`类,我们可以加载XSD文件,然后使用`validate`方法来验证XML文档。例如: ```python from xmlschema import XMLSchema schema = XMLSchema('path_to_schema.xsd') document = 'path_to_xml.xml...
之前做一个开发项目,要校验xml报文合法性,根据Schema使用javax.xml.validation.Validator倒是能验证XML,但是要求是顺序一致才行,一直没找到合适的排序,就自己写了一个排序代码,根据xsd规范文件给xml排序,有...
3. 验证XML:使用XML解析器或验证工具(如`xmllint`、`xmlstarlet`、Java的`javax.xml.validation`库等)将XML文档与XSD文件进行比对,检查是否符合规范。 在博客链接中提到的“sxd文件”可能是指某种特定的工具或...
本文将深入探讨XML的解析方法,包括增删改查操作以及XML Schema(XSD)验证,同时提供一个动态部署的例子。 首先,XML解析是处理XML文档的关键步骤。解析器可以分为DOM(Document Object Model)和SAX(Simple API ...
Java还提供了处理XML Schema(XSD)的能力,可以验证XML文档是否符合特定的模式。`javax.xml.validation`包包含了所需的工具,如`SchemaFactory`和`Validator`。 在实际应用中,选择合适的解析器取决于XML文件的...
### 如何验证XML文档符合Schematron规则 #### Schematron模式概述 Schematron是一种简单而强大的结构化模式语言,用于对XML文档中的模式进行断言。它几乎完全依赖于XPath查询模式来定义规则和检查。Schematron验证...
如果一个Action有多个别名或方法,则可以为每个别名或方法创建单独的验证文件,如`<ActionClassName>-<aliasName>-validation.xml`,这里的`<aliasName>`通常对应于struts.xml中的action name或者特定的方法名。...