针对Java中的XSD验证XML

有许多工具可用于根据XSD 验证XML文档 。 其中包括操作系统脚本和工具,例如xmllint ,XML编辑器和IDE,甚至是在线验证器。 由于前面提到的方法的局限性或问题,我发现拥有自己的易于使用的XML验证工具很有用。 Java使编写这样的工具变得容易,并且这篇文章演示了用Java开发简单的XML验证工具是多么容易。

本文中开发的Java工具需要JDK8。但是,可以很容易地修改简单的Java应用程序,使其可以与JDK 7或什至与JDK 5一样旧的Java版本一起使用。在大多数情况下,我尝试对需要JDK 7或JDK 8识别这些依赖关系并在Java的早期版本中提供替代方法的代码。 我这样做是为了使该工具即使在具有旧版Java的环境中也可以工作。

本文结尾讨论了本文讨论的基于Java的XML验证工具的完整代码清单。 接下来显示当讨论针对一个或多个XSD的XML验证时,该应用程序中最重要的代码行。

使用Java针对XSD验证XML的本质

final Schema schema = schemaFactory.newSchema(xsdSources);
final Validator validator = schema.newValidator();
validator.validate(new StreamSource(new File(xmlFilePathAndName)));

前面的代码清单显示了标准JDK中可用的直接方法,用于根据XSD验证XML。 通过调用javax.xml.validation.SchemaFactory.newSchema(Source []) (其中javax.xml.transform.Source对象的数组表示一个或多个XSD)来实例化javax.xml.validation.Schema的实例。 通过Schema的newValidator()方法从Schema实例中获取javax.xml.validation.Validator的实例。 可以将要验证的XML传递到Validator的validate(Source)方法,以针对最初提供给使用SchemaFactory.newSchema(Source[])创建的Schema对象的XSD或XSD执行XML验证。

下一个代码清单包括刚刚突出显示的代码,但表示该代码所驻留的整个方法。

validateXmlAgainstXsds(String,String [])

/*** Validate provided XML against the provided XSD schema files.** @param xmlFilePathAndName Path/name of XML file to be validated;*    should not be null or empty.* @param xsdFilesPathsAndNames XSDs against which to validate the XML;*    should not be null or empty.*/
public static void validateXmlAgainstXsds(final String xmlFilePathAndName, final String[] xsdFilesPathsAndNames)
{if (xmlFilePathAndName == null || xmlFilePathAndName.isEmpty()){out.println("ERROR: Path/name of XML to be validated cannot be null.");return;}if (xsdFilesPathsAndNames == null || xsdFilesPathsAndNames.length < 1){out.println("ERROR: At least one XSD must be provided to validate XML against.");return;}final SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);final StreamSource[] xsdSources = generateStreamSourcesFromXsdPathsJdk8(xsdFilesPathsAndNames);try{final Schema schema = schemaFactory.newSchema(xsdSources);final Validator validator = schema.newValidator();out.println(  "Validating " + xmlFilePathAndName + " against XSDs "+ Arrays.toString(xsdFilesPathsAndNames) + "...");validator.validate(new StreamSource(new File(xmlFilePathAndName)));}catch (IOException | SAXException exception)  // JDK 7 multi-exception catch{out.println("ERROR: Unable to validate " + xmlFilePathAndName+ " against XSDs " + Arrays.toString(xsdFilesPathsAndNames)+ " - " + exception);}out.println("Validation process completed.");
}

validateXmlAgainstXsds(String, String[])方法的代码清单显示了如何使用指定的架构类型( XMLConstants.W3C_XML_SCHEMA_NS_URI )获得SchemaFactory实例。 此方法还处理在验证过程中可能引发的各种类型的异常。 正如代码中的注释所指出的那样,此方法使用了支持在单个catch子句中捕获多个异常的JDK 7语言更改,但可以替换为单独的catch子句或对早于JDK的代码库捕获单个更通用的异常7。

刚刚显示的方法调用了一个名为generateStreamSourcesFromXsdPathsJdk8(String[]) ,下一个清单是该调用的方法。

generateStreamSourcesFromXsdPathsJdk8(String [])

/*** Generates array of StreamSource instances representing XSDs* associated with the file paths/names provided and use JDK 8* Stream API.** This method can be commented out if using a version of* Java prior to JDK 8.** @param xsdFilesPaths String representations of paths/names*    of XSD files.* @return StreamSource instances representing XSDs.*/
private static StreamSource[] generateStreamSourcesFromXsdPathsJdk8(final String[] xsdFilesPaths)
{return Arrays.stream(xsdFilesPaths).map(StreamSource::new).collect(Collectors.toList()).toArray(new StreamSource[xsdFilesPaths.length]);
}

刚刚显示的方法使用JDK 8流支持,根据路径/名称字符串所指向的XSD的内容,将表示XSD文件的路径/名称的字符串数组转换为StreamSource的实例。 在该类的完整代码清单中,还有一个不赞成使用的方法generateStreamSourcesFromXsdPathsJdk7(final String[]) ,该方法可以代替基于JDK 8的Java版本上的代码使用此方法。

从命令行执行时,此单类Java应用程序最有用。 为此,定义了一个main功能,如下面的代码清单所示。

可执行main(String [])函数

/*** Validates provided XML against provided XSD.** @param arguments XML file to be validated (first argument) and*    XSD against which it should be validated (second and later*    arguments).*/
public static void main(final String[] arguments)
{if (arguments.length < 2){out.println("\nUSAGE: java XmlValidator <xmlFile> <xsdFile1> ... <xsdFileN>\n");out.println("\tOrder of XSDs can be significant (place XSDs that are");out.println("\tdependent on other XSDs after those they depend on)");System.exit(-1);}// Arrays.copyOfRange requires JDK 6; see// http://stackoverflow.com/questions/7970486/porting-arrays-copyofrange-from-java-6-to-java-5// for additional details for versions of Java prior to JDK 6.final String[] schemas = Arrays.copyOfRange(arguments, 1, arguments.length);validateXmlAgainstXsds(arguments[0], schemas);
}

如果传递给可执行文件的命令行参数少于两个,则可执行文件main(String[])打印一条使用情况语句,因为它至少希望验证XML文件的名称/路径以及要验证的XSD的名称/路径。 XML反对。

javaXsdValidationToolUsage

main函数采用第一个命令行参数,并将其视为XML文件的路径/名称,然后将所有其余的command lin参数视为一个或多个XSD的路径/名称。

现在已经显示了用于针对一个或多个XSD验证XML的简单Java工具(完整的代码清单在文章底部)。 有了它,我们就可以对示例XML文件和关联的XSD运行它。 在此演示中,我使用的是Servlet 2.5 web.xml 部署描述符的非常简单的体现 。

样本有效Servlet 2.5 web.xml

<web-app xmlns="http://java.sun.com/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"version="2.5"> <display-name>Sample Java Servlet 2.5 Web Application</display-name>
</web-app>

刚刚显示的简单web.xml文件对Servlet 2.5 XSD有效,并且运行此简单的基于Java的XSD验证工具的输出证明不报告任何验证错误。

validWebXml25ShowsNoValidationErrors

使用此工具的XSD有效XML文件不会产生非常有趣的结果。 下一个代码清单显示了一个故意无效的web.xml文件,该文件具有未在关联的Servlet 2.5 XSD中指定的“ title”元素。 代码列表后显示了输出,其中突出显示了错误消息的最重要部分。

样本无效的Servlet 2.5 web.xml(web-invalid.xml)

<web-app xmlns="http://java.sun.com/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"version="2.5"><display-name>Java Servlet 2.5 Web Application</display-name><title>A handy example</title>
</web-app>

invalidWebXml25ShowsValidationErrors

如最后一个输出所示,当提供的XML无效时,在输出方面,事情会变得更加有趣。

我想在此强调一个重要的警告。 有时需要以特定顺序指定此基于Java的工具提供的XSD。 特别是,在包含其他XSD的XSD之后,应该在命令行上列出它们所包含的XSD。 换句话说,通常在命令行上提供不包含“包括”依赖项的XSD,然后再将包含它们的XSD提供给它们。

下一个代码清单用于完整的XmlValidator类。

XmlValidator.java(完整的类列表)

package dustin.examples.xmlvalidation;import org.xml.sax.SAXException;import javax.xml.XMLConstants;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;import static java.lang.System.out;/*** Validate provided XML against the provided XSDs.*/
public class XmlValidator
{/*** Validate provided XML against the provided XSD schema files.** @param xmlFilePathAndName Path/name of XML file to be validated;*    should not be null or empty.* @param xsdFilesPathsAndNames XSDs against which to validate the XML;*    should not be null or empty.*/public static void validateXmlAgainstXsds(final String xmlFilePathAndName, final String[] xsdFilesPathsAndNames){if (xmlFilePathAndName == null || xmlFilePathAndName.isEmpty()){out.println("ERROR: Path/name of XML to be validated cannot be null.");return;}if (xsdFilesPathsAndNames == null || xsdFilesPathsAndNames.length < 1){out.println("ERROR: At least one XSD must be provided to validate XML against.");return;}final SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);final StreamSource[] xsdSources = generateStreamSourcesFromXsdPathsJdk8(xsdFilesPathsAndNames);try{final Schema schema = schemaFactory.newSchema(xsdSources);final Validator validator = schema.newValidator();out.println("Validating " + xmlFilePathAndName + " against XSDs "+ Arrays.toString(xsdFilesPathsAndNames) + "...");validator.validate(new StreamSource(new File(xmlFilePathAndName)));}catch (IOException | SAXException exception)  // JDK 7 multi-exception catch{out.println("ERROR: Unable to validate " + xmlFilePathAndName+ " against XSDs " + Arrays.toString(xsdFilesPathsAndNames)+ " - " + exception);}out.println("Validation process completed.");}/*** Generates array of StreamSource instances representing XSDs* associated with the file paths/names provided and use JDK 8* Stream API.** This method can be commented out if using a version of* Java prior to JDK 8.** @param xsdFilesPaths String representations of paths/names*    of XSD files.* @return StreamSource instances representing XSDs.*/private static StreamSource[] generateStreamSourcesFromXsdPathsJdk8(final String[] xsdFilesPaths){return Arrays.stream(xsdFilesPaths).map(StreamSource::new).collect(Collectors.toList()).toArray(new StreamSource[xsdFilesPaths.length]);}/*** Generates array of StreamSource instances representing XSDs* associated with the file paths/names provided and uses* pre-JDK 8 Java APIs.** This method can be commented out (or better yet, removed* altogether) if using JDK 8 or later.** @param xsdFilesPaths String representations of paths/names*    of XSD files.* @return StreamSource instances representing XSDs.* @deprecated Use generateStreamSourcesFromXsdPathsJdk8 instead*    when JDK 8 or later is available.*/@Deprecatedprivate static StreamSource[] generateStreamSourcesFromXsdPathsJdk7(final String[] xsdFilesPaths){// Diamond operator used here requires JDK 7; add type of// StreamSource to generic specification of ArrayList for// JDK 5 or JDK 6final List<StreamSource> streamSources = new ArrayList<>();for (final String xsdPath : xsdFilesPaths){streamSources.add(new StreamSource(xsdPath));}return streamSources.toArray(new StreamSource[xsdFilesPaths.length]);}/*** Validates provided XML against provided XSD.** @param arguments XML file to be validated (first argument) and*    XSD against which it should be validated (second and later*    arguments).*/public static void main(final String[] arguments){if (arguments.length < 2){out.println("\nUSAGE: java XmlValidator <xmlFile> <xsdFile1> ... <xsdFileN>\n");out.println("\tOrder of XSDs can be significant (place XSDs that are");out.println("\tdependent on other XSDs after those they depend on)");System.exit(-1);}// Arrays.copyOfRange requires JDK 6; see// http://stackoverflow.com/questions/7970486/porting-arrays-copyofrange-from-java-6-to-java-5// for additional details for versions of Java prior to JDK 6.final String[] schemas = Arrays.copyOfRange(arguments, 1, arguments.length);validateXmlAgainstXsds(arguments[0], schemas);}
}

尽管这篇文章的篇幅最初可能暗示了多少,但使用Java来针对XSD验证XML还是相当简单的。 此处显示和解释的示例应用程序试图证明这一点,并且是针对指定XSD对XML文档进行简单命令行验证的有用工具。 可以轻松地将其移植到Groovy,以使其更加脚本友好。 如前所述,这个简单的工具需要当前编写的JDK 8,但是可以很容易地改编为在JDK 5,JDK 6或JDK 7上运行。

翻译自: https://www.javacodegeeks.com/2015/03/validating-xml-against-xsds-in-java.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/360841.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

uniapp uni.request GET方式请求,不能直接传数组解决方法

这里写目录标题目录遇到的问题 GET请求方法传数组解决方案目录 遇到的问题 GET请求方法传数组 想传一个数组&#xff0c;但是后台接受到的数据与浏览器中显示的数据和前台代码传的不一样&#xff1b; 前台代码打印 浏览器显示数据 其中HerbalNameList &#xff0c;变成了字…

休眠CascadeType.LOCK陷阱

介绍 引入了Hibernate 显式锁定支持以及Cascade Types之后 &#xff0c;就该分析CascadeType.LOCK行为了。 休眠锁定请求触发内部LockEvent 。 关联的DefaultLockEventListener可以将锁定请求级联到锁定实体子级。 由于CascadeType.ALL也包括CascadeType.LOCK &#xff0c;因…

c++中在堆和栈中申请空间的差别

堆中和栈中申请的空间的比较, 我找到了下面的比较: 栈的情况&#xff1a;栈上分配空间的好处是快&#xff0c;而且对象生存期是自动的&#xff0c;离开当前域之后就自动析构回收。坏处就是栈空间有限&#xff0c;而且不能人为控制对象的生存期&#xff0c;比如你无法将一个函数…

推销自己的海盗猫王运营商

因此&#xff0c;Java没有Elvis运算符&#xff08;或者更正式的名称是null合并运算符或null安全成员选择&#xff09;……虽然我个人不太在意它&#xff0c;但有些人似乎很喜欢它。 当一位同事需要几天后&#xff0c;我坐下来探讨了我们的选择。 而且你知道什么&#xff01; 您…

使用CDI简化JAX-RS缓存

这篇文章&#xff08;通过一个简单的示例&#xff09;说明了如何使用CDI Producers使其在RESTful服务中利用缓存控制语义更加容易 与HTTP 1.0中可用的Expires标头相比&#xff0c; HTTP 1.1中添加了Cache-Control标头&#xff0c;这是急需的改进。 RESTful Web服务可以利用此标…

transform限制position:fixed的跟随效果

我们应该都知道&#xff0c;position:fixed可以让元素不跟随浏览器的滚动条滚动&#xff0c;而且这种跟随效果连它的兄弟们position:relative/absolute都限制不了。但是&#xff0c;真是一物降一物&#xff0c;position:fixed固定效果却被小小的transform给干掉了&#xff0c;直…

Java 8 Lambda表达式教程

问候&#xff01; :) 离开几个月后&#xff0c;我决定恢复风格:)。 我注意到我以前有关新的Date / Time API的一篇文章非常受欢迎&#xff0c;因此这次我将把本篇文章专门介绍Java 8的另一个新功能&#xff1a; Lambda Expressions 。 功能编程 Lambda表达式是Java编程语言最…

[HDU] 2553 N皇后问题-简单深搜

题目链接&#xff1a; http://acm.hdu.edu.cn/showproblem.php?pid2553 方法&#xff1a; 1.可以用对称的思想&#xff0c;即&#xff1a;如果N是偶数&#xff0c;则只计算第一个皇后分别放在第一行的位置1到N/2这N/2个情况的结果和&#xff0c;最后再乘以2。如果是奇数&#…

您真的了解@WebService吗?

SOAP Web服务无论如何都不是最先进的技术-尽管它仍然存在&#xff0c;但是基于REST的Web服务却提供了激烈的竞争。 无论如何–这绝对不是REST vs SOAP帖子&#xff01; 我观察到了一些实例&#xff0c;至少可以说&#xff0c;使用基于Java的SOAP Web服务的方式不太理想。 我认…

Error: Module “xxx“ does not exist in container. / antd pro v5启用qiankun报错 / 同时使用mfsu和qiankun报错

一、问题描述 我们用antd pro v5搭建前端项目&#xff0c;启用qiankun微前端模式&#xff0c;终端报错如下&#xff1a; Uncaught (in promise) Error: Module “xxx” does not exist in container. while loading “xxx” from webpack/container/reference/mf 经过排查&…

双链表

问题&#xff1a;在分配空间时&#xff0c;遇到问题 定义一个结构体&#xff1a; typedef struct dLinkListNode{ int data; struct dLinkListNode *prior; struct dLinkListNode *next;}*dLinkList,dListNode; dList(dLinkList)malloc(sizeof(dListNode));与dList(dLinkList)m…

JVMTI标记如何影响GC暂停

这篇文章分析了为什么Plumbr Agents在某些情况下以及如何延长GC暂停的时间。 对基本问题进行故障诊断揭示了有关在GC暂停期间如何处理JVMTI标记的有趣见解。 发现问题 我们的一位客户抱怨说&#xff0c;附加了Plumbr代理后&#xff0c;应用程序的响应速度明显降低。 通过分析G…

使用Apache Hadoop计算PageRanks

目前&#xff0c;我正在接受Coursera的培训“ 挖掘海量数据集 ”。 我对MapReduce和Apache Hadoop感兴趣已有一段时间了&#xff0c;通过本课程&#xff0c;我希望对何时以及如何MapReduce可以帮助解决一些现实世界中的业务问题有更多的了解&#xff08;我在这里介绍了另一种解…

分享一篇关于奇异值分解的文章[Eng]

原文地址&#xff1a;http://www.igvita.com/2007/01/15/svd-recommendation-system-in-ruby/ One day, a bunch of friends, who happened to be big Family Guy fans, decided to put together a site to rank and share their thoughts on the show. Soon thereafter they h…

为雅安祈福

四川是个多灾多难的省份&#xff0c;更是个多地震的省份&#xff0c;十年之内发生了两次大地震。我们能做的就是为雅安的人们祈福。 淘宝给互联网带头了&#xff1a; 天猫也跟着祈福了&#xff0c;因为他们都属于阿里巴巴&#xff0c;这里就不上图了。 百度作为国内互联网企业的…

在运行时打开GC日志记录

总是有下一个JVM表现不佳。 而且&#xff0c;您内心深知&#xff0c;如果您只有少数启动选项可以公开一些有关正在发生的事情的信息&#xff0c;那么您可能就有机会真正修复该死的东西。 但是不&#xff0c;您需要的标志&#xff08; -XX&#xff1a; HeapDumpOnOutOfMemoryErr…

jpannel设置位置xy_实用的摄影技巧!10种常见摄影场景的单反相机设置技巧!

相机是爱拍一族必不可少的东西&#xff0c;对于摄影爱好者对于一些相机设置技巧可能也不是太了解&#xff0c;在摄影过程中&#xff0c;有很多的场景需要不同的设置&#xff0c;根据光线变化和周围环境&#xff0c;一般来说都会特定的摄影技巧&#xff0c;今天红视觉和大家一起…

Only digits (0-9) can be put inside [] in the path string: formData.XXX

使用uniapp开发时微信小程序中爆出的问题&#xff0c;问题在于form表单组件中绑定表单值,去除报错值则正常。 解决办法如下&#xff1a; 修改注释行内容&#xff0c; 转载连接

外包以小时计算金额的费用_2020年初级会计各大税种的计算公式,请收藏!

一、各种税的计算方式增值税1、一般纳税人应纳税额销项税额—进项税销项税额销售额税率组成计税价格成本(1成本利润率)组成计税价格成本(1成本利润率)(1-消费税税率)2、进口货物应纳税额组成计税价格税率组成计税价格关税完税价格关税(消费税)3、小规模纳税人应纳税额销售额征收…

VSCode设置ESLint语法检查

转载 "eslint.validate": ["javascript","javascriptreact","vue-html",{"language": "vue","autoFix": true}],"eslint.run": "onSave","eslint.autoFixOnSave": true…