我正在生成一些需要符合给我的xsd文件的xml文件.什么是验证它们符合要求的最佳方法?
Java运行时库支持验证.上次我检查过这是封面上的Apache Xerces解析器.您应该使用javax.xml.validation.Validator.
import javax.xml.XMLConstants; import javax.xml.transform.Source; import javax.xml.transform.stream.StreamSource; import javax.xml.validation.*; import java.net.URL; import org.xml.sax.SAXException; //import java.io.File; // if you use File import java.io.IOException; ... URL schemaFile = new URL("http://host:port/filename.xsd"); // webapp example xsd: // URL schemaFile = new URL("http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"); // local file example: // File schemaFile = new File("/location/to/localfile.xsd"); // etc. Source xmlFile = new StreamSource(new File("web.xml")); SchemaFactory schemaFactory = SchemaFactory .newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); try { Schema schema = schemaFactory.newSchema(schemaFile); Validator validator = schema.newValidator(); validator.validate(xmlFile); System.out.println(xmlFile.getSystemId() + " is valid"); } catch (SAXException e) { System.out.println(xmlFile.getSystemId() + " is NOT valid reason:" + e); } catch (IOException e) {}
模式工厂常量是http://www.w3.org/2001/XMLSchema
定义XSD 的字符串.上面的代码针对URL验证WAR部署描述符,http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd
但您可以轻松地针对本地文件进行验证.
您不应该使用DOMParser来验证文档(除非您的目标是创建文档对象模型).这将在解析文档时开始创建DOM对象 - 如果您不打算使用它们会浪费.
以下是使用Xerces2的方法.这里有一个教程,这里(需要注册).
原始归属:从这里公然复制:
import org.apache.xerces.parsers.DOMParser; import java.io.File; import org.w3c.dom.Document; public class SchemaTest { public static void main (String args[]) { File docFile = new File("memory.xml"); try { DOMParser parser = new DOMParser(); parser.setFeature("http://xml.org/sax/features/validation", true); parser.setProperty( "http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation", "memory.xsd"); ErrorChecker errors = new ErrorChecker(); parser.setErrorHandler(errors); parser.parse("memory.xml"); } catch (Exception e) { System.out.print("Problem parsing the file."); } } }
我们使用ant构建项目,因此我们可以使用schemavalidate任务来检查我们的配置文件:
现在顽皮的配置文件将失败我们的构建!
http://ant.apache.org/manual/Tasks/schemavalidate.html
由于这是一个很受欢迎的问题,我将指出java也可以对"引用"xsd进行验证,例如,如果.xml文件本身在标题中指定XSD,则使用xsi:SchemaLocation
或xsi:noNamespaceSchemaLocation
(或xsi表示特定名称空间)ex:
...
或SchemaLocation(始终是xsd映射的命名空间列表)
...
其他答案也适用于此,因为.xsd文件"映射"到.xml文件中声明的命名空间,因为它们声明了一个命名空间,如果与.xml文件中的命名空间匹配,那么你就是好的.但有时候能够拥有自定义解析器很方便......
来自javadocs:"如果您创建了一个模式而没有指定URL,文件或源,那么Java语言会创建一个查找正在验证的文档以查找它应该使用的模式的模式.例如:"
SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema"); Schema schema = factory.newSchema();
这适用于多个名称空间等.这种方法的问题在于xmlsns:xsi
它可能是一个网络位置,所以默认情况下它会在每次验证时都出现并点击网络,而不是最佳.
下面是一个示例,它针对它引用的任何XSD验证XML文件(即使它必须从网络中提取它们):
public static void verifyValidatesInternalXsd(String filename) throws Exception { InputStream xmlStream = new new FileInputStream(filename); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setValidating(true); factory.setNamespaceAware(true); factory.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaLanguage", "http://www.w3.org/2001/XMLSchema"); DocumentBuilder builder = factory.newDocumentBuilder(); builder.setErrorHandler(new RaiseOnErrorHandler()); builder.parse(new InputSource(xmlStream)); xmlStream.close(); } public static class RaiseOnErrorHandler implements ErrorHandler { public void warning(SAXParseException e) throws SAXException { throw new RuntimeException(e); } public void error(SAXParseException e) throws SAXException { throw new RuntimeException(e); } public void fatalError(SAXParseException e) throws SAXException { throw new RuntimeException(e); } }
即使xml文件引用了url,也可以通过手动指定xsd(请参阅此处的其他答案)或使用"XML目录" 样式解析程序,避免从网络中引用引用的XSD .Spring显然也可以拦截 URL请求以提供本地文件进行验证.或者您可以通过setResourceResolver设置自己的,例如:
Source xmlFile = new StreamSource(xmlFileLocation); SchemaFactory schemaFactory = SchemaFactory .newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); Schema schema = schemaFactory.newSchema(); Validator validator = schema.newValidator(); validator.setResourceResolver(new LSResourceResolver() { @Override public LSInput resolveResource(String type, String namespaceURI, String publicId, String systemId, String baseURI) { InputSource is = new InputSource( getClass().getResourceAsStream( "some_local_file_in_the_jar.xsd")); // or lookup by URI, etc... return new Input(is); // for class Input see // /sf/ask/17360801/ } }); validator.validate(xmlFile);
另见这里的另一个教程.
我相信,默认是使用DOM解析,你可以做与被验证SAX解析器类似的东西,以及 saxReader.setEntityResolver(your_resolver_here);
使用Java 7,您可以按照包描述中提供的文档进行操作.
// parse an XML document into a DOM tree DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder(); Document document = parser.parse(new File("instance.xml")); // create a SchemaFactory capable of understanding WXS schemas SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); // load a WXS schema, represented by a Schema instance Source schemaFile = new StreamSource(new File("mySchema.xsd")); Schema schema = factory.newSchema(schemaFile); // create a Validator instance, which can be used to validate an instance document Validator validator = schema.newValidator(); // validate the DOM tree try { validator.validate(new DOMSource(document)); } catch (SAXException e) { // instance document is invalid! }