xsd文件_针对Java中的XSD验证XML

xsd文件

xsd文件

许多工具可用于根据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的实例。 通过SchemanewValidator()方法从Schema实例中获取javax.xml.validation.Validator的实例。 可以将要验证的XML传递到Validatorvalidate(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.
    */
   @Deprecated
   private 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 6
      final 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

xsd文件

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值