9

Say I have two projects, A and B. Java projects, in case that's important.

Project A contains a bunch of XSD files that represent core types and elements. They are all placed in a package called, say, "definition". This gets built into project-a.jar.

Project B represents an extension project, and it's allowed to defined its own types and elements. I created a new schema and placed it in "definition.extension" package. This gets built into project-b.jar.

Now, for the XSDs in Project B, what exactly should I put as the schemaLocation for an include?

schemaLocation="../core-types.xsd" didn't quite work (I know, it's needs a URI), but what exactly is the proper or standard approach to this? Google found me more people asking this question that clear-cut, standard approaches on what really is the correct way to handle this.

It can't be that I have programmatically adjust the schemaLocation during runtime... or that I'd need a build step/script that will dynamically replaced the schemaLocation during compilation... right?

I'm not looking for answers like "put them in a shared location". I'm looking for something more along the lines of a dev environment that uses relative references instead of hardcoded references.

FYI, I'm using IntelliJ IDEA, in case there's an IDE-specific approach.

aberrant80
  • 12,815
  • 8
  • 45
  • 68
  • [EntityResolver](http://docs.oracle.com/javase/6/docs/api/org/xml/sax/EntityResolver.html) might be a technical solution at runtime. – Claude Mar 13 '13 at 09:25
  • URIs can also reference files embedded in a jar. See [this post](http://stackoverflow.com/questions/2049659/get-a-file-or-uri-object-for-a-file-inside-an-archive-with-java). – geert3 Mar 13 '13 at 15:52
  • Perhaps Class.getResource() or ClassLoader.getResource()? See [this post](http://stackoverflow.com/questions/6608795/what-is-the-difference-between-class-getresource-and-classloader-getresource) – CAB Mar 15 '13 at 18:43
  • have you tried something like schemalocation="classpath:core-types.xsd"? – DavidA Mar 15 '13 at 20:19

2 Answers2

1

If you just want IntelliJ to stop showing your includes in red, you can use some custom URI in your include. You then go to Project Settings -> Schema's and DTD's where you can map this URI onto a local file.

If you need to do schema validation at run time, that's a different story. You probably need to use an XML Catalog. If you're using JAXB, you should have a look at this question: jaxb - how to map xsd files to URL to find them

Community
  • 1
  • 1
Pieter Herroelen
  • 5,977
  • 2
  • 29
  • 37
1

You should use XML Catalogs. This link gives a thorough introduction to XML catalogs - and how to use them in Java for instance - by XML expert Norman Walsh. Quote:

These catalog files can be used to map public and system identifiers and other URIs to local files (or just other URIs).

The aforementioned identifiers are typically the schemalocations or namespaces you use in schema imports.

When using such catalogs, in order to avoid confusions and some bug in XJC, I strongly recommend you remove all schemaLocations from the schema imports in XML schemas, and only keep the namespace (if you have a choice of course). For example:

<import namespace="http://www.w3.org/1999/xlink" />

Then specify the mappings for each namespace to the actual schema location in the catalog. For example, using the OASIS XML catalog format:

<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
    <uri name="http://www.w3.org/1999/xlink" uri="w3c/1999/xlink.xsd" />
</catalog>

At compilation time, if you are generating JAXB-annotated classes from the schemas, I recommend you use Episodes to achive separate schema compilation aka modular schema compilation. This is supported by maven-jaxb2-plugin for instance, which also has advanced support for catalogs.

For runtime, depending on your XML use case, you should try to use a library with native support for XML catalogs, such as most Java web service frameworks (JAX-WS RI/Metro, Apache CXF...) if you are developing web services for example. If you can't or if you want finer control over the XML catalog (e.g. being able to load schemas from the classpath), I invite you to look at the XML Entity and URI Resolvers page mentioned earlier, especially the sections Using Catalogs with Popular Applications and Adding Catalog Support to Your Applications. Basically, you play with org.apache.xml.resolver.tools.CatalogResolver and optionally (for finer control) org.apache.xml.resolver.CatalogManager classes. For concrete examples of custom CatalogResolver/CatalogManager, you may look at code sources from Apache commons-configuration, AuthzForce, CXF, etc.

cdan
  • 3,470
  • 13
  • 27