如何将catalog.xml实体与数据库匹配?

时间:2014-10-29 09:23:10

标签: java xml database xsd-validation xmlcatalog

我必须使用.xsd文件验证一些xml文件,这些文件列在catalog.xml中,但它们位于数据库中。所以我需要解析器,它将来自catalog.xml的systemId与存储为blob的.xsd文件匹配在数据库中。 我发现XMLInputSource resolveEntity(XMLResourceIdentifier resourceIdentifier)方法正在执行此操作,但我无法找到解析器如何使用此方法,因此我不确定如何覆盖它以便在属性上执行此操作。我认为它返回XMLInputStram,其中包含Stream中的.xsd文件,但由于"实体的解析和输入流的打开直到调用者"它不是真的。 ,根据XMLInputSource文档。

所以我的问题是 - 如何使用存储在数据库中的.xsd文件映射catalog.xml中的实体?

我真的希望我能清楚地解释问题,但我知道我的英语很差 - 所以请随时提出更多细节或更好的解释。

问候, Rzysia

2 个答案:

答案 0 :(得分:1)

这是the resolver I wrote。此解析程序将系统ID解析为Maven工件中的资源。这与你的任务有些类似。

  • 基本上,您的任务是实施resolveEntity方法。
  • 通常扩展现有的CatalogResolver
  • 是切实可行的
  • 然后您可以覆盖getResolvedEntity方法。
  • 通常,您首先调用超级方法来解析systemId / publicId
  • 然后你尝试自定义分辨率。
  • systemId通常是资源位置网址(或逻辑URI)。
  • publicId通常是命名空间URI。

以下是来自another resolver的简单代码段,它解析了类路径中的classpath:com/acme/foo/schema.xsd

public static final String URI_SCHEME_CLASSPATH = "classpath";

@Override
public String getResolvedEntity(String publicId, String systemId) {
    final String result = super.getResolvedEntity(publicId, systemId);

    if (result == null) {
        return null;
    }

    try {
        final URI uri = new URI(result);
        if (URI_SCHEME_CLASSPATH.equals(uri.getScheme())) {
            final String schemeSpecificPart = uri.getSchemeSpecificPart();
            final URL resource = Thread.currentThread()
                    .getContextClassLoader()
                    .getResource(schemeSpecificPart);
            if (resource == null) {
                return null;
            } else {
                return resource.toString();
            }
        } else {
            return result;
        }
    } catch (URISyntaxException urisex) {
        return result;
    }
}

在您的方案中,我会执行以下操作:

  • 定义URI架构,如database:schema:table:value:id:schema.xsd
  • 编写一个能够解析此类URI的目录解析器。
  • 定义一个目录文件,该文件将名称空间URI或绝对架构位置URL重写为database:... URI。

简单的表示法就是:

REWRITE_SYSTEM "http://example.com/schemas" "database:schemas:content:schema_id:example/schemas"
  • 因此,“基本”目录解析器会首先将http://example.com/schemas/schema.xsd解析为database:schemas:content:schema_id:example/schemas/schema.xsd
  • 然后您的代码将database:schemas:content:schema_id:example/schemas/schema.xsd解析为数据库资源。

答案 1 :(得分:0)

好的,我找到了解决方案 - 正如我所想,方法XMLInputSource resolveEntity(XMLResourceIdentifier resourceIdentifier) shoud 返回XMLInputSource,并设置了我自己的包含伪装xsd架构的InputStream。 我这个重写课程的版本:

public XMLInputSource resolveEntity(XMLResourceIdentifier resourceIdentifier)
        throws XNIException, IOException {

    String resolvedId = resolveIdentifier(resourceIdentifier);

    if (resolvedId != null) {
        XMLInputSource xmlis = new XMLInputSource(resourceIdentifier.getPublicId(),
                resolvedId,
                resourceIdentifier.getBaseSystemId());

        try {
            InputStream is = getXSDFromDb(resourceIdentifier.getLiteralSystemId());                
            xmlis.setByteStream(is);
        } catch (SQLException ex) {
            ex.printStackTrace();
        }

        return xmlis;
    }
    return null;