15

我想使用 RELAX NG 模式验证 XML 文档,并且我想使用JAXP 验证 API

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

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

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

我需要它来使用 Java 5 和 Java 6。

谢谢!

4

5 回答 5

13

我在 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());
            }
        }
    }

}

再一次,我只测试了这个 ion 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)
于 2010-01-20T19:39:17.050 回答
9

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

从昨晚开始,XMLUnit 的主干包含一个基于 javax.xml.validation 的新 Validator 类,该类是 JAXP 1.3(即 Java5+)的一部分。

...

据我所知,没有开箱即用的支持 RELAX NG 的 JAXP 实现。Sun 自己的 JAXP 1.4 (Java6+) 肯定不会。一些搜索把我带到了Kohsuke Kawaguchi 的博客,鉴于他在 JAXP、Sun 的多模式验证器、isorelax 和其他方面的工作,他应该知道。

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

因此,您可能必须跳过一些障碍才能在您的 JAXP 设置中获得 RELAX NG 支持——在我的情况下,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.xml.validation.SchemaFactory 服务提供程序文件的 JAR 文件。

于 2009-10-21T04:42:44.387 回答
1

我无法为您提供 JAXP 验证 API,但Nux提供了一个类,它几乎可以验证人类已知的所有类型的模式。关于 RELAX NG 模式,使用这个工厂方法来创建相关的验证器对象。

于 2009-10-20T21:36:04.070 回答
1

另一种选择是Trang,它是一个 RelaxNG 到 XMLSchema 的转换器。我相信它被设计为用作构建工具而不是运行时库,但您最好的选择可能是在构建时使用 Trang 将您的模式转换为 XMLSchema,然后对其进行验证。这样,您可以准确地看到翻译的样子,同时充分利用 JAXP 的 XML Schema 支持。

于 2009-10-20T21:48:51.317 回答
0

... IllegalArgumentException 一旦尝试实例化工厂

表示无法识别架构语言,可能有几个原因。

  • 由于默认情况下 Sun JDK 不包含 RELAX NG 验证器,因此可能找不到它。
  • 可能是您在架构语言标识符中犯了错误。
于 2009-10-18T21:02:23.717 回答