1

我必须使用 .xsd 文件验证一些 xml 文件,这些文件在 catalog.xml 中列出,但它们在数据库中。所以我需要解析器,它将catalog.xml中的systemId与作为blob存储在数据库中的.xsd文件匹配。我发现该XMLInputSource resolveEntity(XMLResourceIdentifier resourceIdentifier)方法执行此操作,但我找不到解析器如何使用此方法,因此我不确定如何覆盖它以正确执行此操作。根据 XMLInputSource 文档,我认为它返回XMLInputStram包含 Stream 中的 .xsd 文件,但事实并非如此,因为“将实体的解析和输入流的打开留给调用者”。

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

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

问候, Rzysia

4

2 回答 2

1

这是我为编写的解析器。此解析器将系统 ID 解析为 Maven 工件中的资源。这与您的任务有些相似。

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

这是另一个在类路径中解析的解析器的简单代码片段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.xsddatabase:schemas:content:schema_id:example/schemas/schema.xsd.
  • 然后您的代码解析database:schemas:content:schema_id:example/schemas/schema.xsd为数据库资源。
于 2014-10-29T09:55:10.510 回答
0

好的,我找到了解决方案 - 正如我所想,方法XMLInputSource resolveEntity(XMLResourceIdentifier resourceIdentifier) 应该返回 XMLInputSource 并设置我自己的 InputStream 包含指定的 xsd 模式。我的这个被覆盖类的版本:

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;
于 2014-10-30T12:35:40.727 回答