如何使用RELAX NG模式和JAXP验证XML文档?

2022-09-03 13:18:24

我想使用RELAX NG schemata验证XML文档,我想使用JAXP验证API

从谷歌搜索中,似乎我可以使用JingISO RELAX JARV到JAXP Bridge。不幸的是,在将两者都添加到我的类路径后,我无法让它工作。 只是在它试图实例化一个工厂时立即抛出一个 - 我查看内部,显然返回一个空结果。SchemaFactoryIllegalArgumentExceptionSchemaFactorySchemaFactoryFinder

因此,我很感激任何一个问题的答案:

  • 我怎样才能与荆和这座桥一起工作?
  • 有没有一组更好/不同的库我应该尝试?

我需要这个来与Java 5和Java 6一起使用。

谢谢!


答案 1

我在Java 1.6上用下面一行解决了这个错误:

// Specify you want a factory for RELAX NG "compact"
System.setProperty(SchemaFactory.class.getName() + ":" + XMLConstants.RELAXNG_NS_URI, "com.thaiopensource.relaxng.jaxp.CompactSyntaxSchemaFactory");

SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.RELAXNG_NS_URI);

这允许我使用 Jing 根据 Compact RELAX NG 模式验证 XML 文档。完整示例如下。我没有使用桥或其他任何东西。运行时类路径只有 jing.jar (20091111) 和我自己的 Validator 类。

import java.io.File;
import java.io.IOException;

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 org.xml.sax.SAXException;

public class Validate
{

    public static void main(String[] args) throws SAXException, IOException
    {
        // Specify you want a factory for RELAX NG
        System.setProperty(SchemaFactory.class.getName() + ":" + XMLConstants.RELAXNG_NS_URI, "com.thaiopensource.relaxng.jaxp.CompactSyntaxSchemaFactory");
        SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.RELAXNG_NS_URI);

        // Load the specific schema you want.
        // Here I load it from a java.io.File, but we could also use a
        // java.net.URL or a javax.xml.transform.Source
        File schemaLocation = new File(args[0]);

        // Compile the schema.
        Schema schema = factory.newSchema(schemaLocation);

        // Get a validator from the schema.
        Validator validator = schema.newValidator();

        for (int i = 1; i < args.length; i++)
        {
            String file = args[i];

            // Check the document
            try
            {
                validator.validate(new StreamSource(new File(file)));
                System.out.println(file + " is valid.");
            }
            catch (SAXException ex)
            {
                System.out.print(file + " is not valid because: " + ex.getMessage());
            }
        }
    }

}

再一次,我只测试了这个离子Java 1.6。

$ java -version
java version "1.6.0_01"
Java(TM) SE Runtime Environment (build 1.6.0_01-b06)
Java HotSpot(TM) Client VM (build 1.6.0_01-b06, mixed mode, sharing)

答案 2

参见 Stefan Bodewig 于 2008 年 3 月 7 日撰写的名为 RELAX NG Validation in XMLUnit 的博客:

由于昨晚XMLUnit的中继包含一个新的Veristrator类,该类基于javax.xml.validation,它是JAXP 1.3(即Java5 +)的一部分。

...

据我所知,没有 JAXP 实现支持开箱即用的 RELAX NG。Sun 自己的 JAXP 1.4 (Java6+) 当然不会。一些搜索将我带到了Kohsuke Kawaguchi的博客,鉴于他在JAXP,Sun的多模式验证器,等relax和其他东西上的工作,他应该知道。

使用他的等边桥Jing并没有让我在Java6上得到任何东西。我回到Kohsuke Kawaguchi的文章并阅读了评论:该桥不适用于Java6,因为它们更改了SchemaFactory查找算法。好吧,尝试了Java5 - 进步,我现在在Jing内部的某个地方得到了一个NullPointerException,所以至少它正在加载工厂。接下来,我用MSV替换了Jing(现在在这里,无论有多少链接将您带到Sun的WebServices堆栈页面,这么多“好的URL永远不会改变”),真的,我的简单测试通过了。

因此,您可能需要跳过一些箍才能将RELAX NG支持放入JAXP设置中 - 在我的情况下,Java5,MSV和Kawaguchi的桥接工作正常,但注释表明它也应该在Java6中实现 - 但是一旦您设法正确配置所有内容,XMLUnit现在就可以让您在单元测试中断言文档的有效性。但是,它似乎不适用于紧凑的语法。

要阅读Kohsuke Kawaguchi博客上的评论,您必须使用 archive.org,因为它们现在都消失了:

Java 5 将 Service Provider 文件解释为键/值对的列表,这违反了 Java 5 和 6 JAR 文件规范,但恰好与您的示例相匹配。

Java 6 按照指定解析服务提供程序文件,即。作为完全限定类名的列表,但无法实例化适配器的 SchemaFactory,因为服务提供程序文件的内容无效。

为了与 Java 5 和 Java 6 兼容而不必更改 JAXP-JARV-adapter JAR 文件,只需添加另一个包含正确的 javax.validation.schemaFactory Service Provider 文件的 JAR 文件.xml即可。


推荐