How to match catalog.xml entities with database?

113 views Asked by At

I have to validate some xml files with .xsd files, which are listed in catalog.xml, but they are in database. So i need resolver, which will match systemId from catalog.xml with .xsd file stored as blob in database. I found that XMLInputSource resolveEntity(XMLResourceIdentifier resourceIdentifier) method doing this, but I can't find how parser uses this method, so I'm not sure how to override it to do it propertly. I thought that it returns XMLInputStram which contains .xsd file in Stream, but it's not true because of "leaving resolution of the entity and opening of the input stream up to the caller", according to XMLInputSource documentation.

So my question is - how to map entities from catalog.xml with .xsd files stored in database?

I really hope that I explained problem clearly, but I know that my english is really poor - so feel free to ask for more details or better explaation.

Greetings, Rzysia

2

There are 2 answers

0
rzysia On BEST ANSWER

Ok, i found solution - as I thought, method XMLInputSource resolveEntity(XMLResourceIdentifier resourceIdentifier) shoud return XMLInputSource with setted my own InputStream containing speciefied xsd schema. My version of this overrided class:

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;
3
lexicore On

Here's the resolver I wrote for the . This resolver resolves system ids to resources in Maven artifacts. This is somewhat similar task to yours.

  • Your task is, basically, to implement the resolveEntity method.
  • Normally it is practical to extend an existing CatalogResolver.
  • Then you can override the getResolvedEntity method.
  • Typically you first call the super method to resolve systemId/publicId.
  • Then you try to do you custom resolution.
  • systemId is normally the resource location URL (or logical URI).
  • publicId is often the namespace URI.

Here's a simple code snippet from another resolver which resolves classpath:com/acme/foo/schema.xsd in the classpath:

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;
    }
}

In your scenario, I'd do the following:

  • Define the URI schema like database:schema:table:value:id:schema.xsd.
  • Write a catalog resolver which is capable of resolving such URIs.
  • Define a catalog file which rewrites namespace URIs or absolute schema location URLs to your database:... URIs.

In simple notation this would be something like:

REWRITE_SYSTEM "http://example.com/schemas" "database:schemas:content:schema_id:example/schemas"
  • So the "base" catalog resolver would first resolve http://example.com/schemas/schema.xsd into database:schemas:content:schema_id:example/schemas/schema.xsd.
  • Then your code resolves database:schemas:content:schema_id:example/schemas/schema.xsd into a database resource.