Friday, April 22, 2005

Jena tip: namespaces and the j.0 problem

A frequently asked question we get on the Jena list is paraphrased as: "help - my output contains these weird j.0 namespaces, how do I get rid of them?". In the hope that Google will save some future askers of this question some time, here's an explanation of what is happening, and what to do about it.

First, consider the following code snippet:

    public static void main( String[] args ) {
        Model m = ModelFactory.createDefaultModel();
        Property p = m.createProperty( "p" );
        Resource r = m.createResource( "r" );
        r.addProperty( p, 42 );
        m.write( System.out, "RDF/XML" );
    }

This could be expected to write a representation of the simple RDF model r p "42". But in fact, it produces a Java exception. Exactly which exception depends on the version of Jena we are using, in my current test setup I get Exception in thread "main" com.hp.hpl.jena.rdf.arp.RelativeURIException: No scheme found in URI 'p'. The problem is that RDF (and RDFS, and OWL) expect the names of things to be URI's. The symbol p isn't a URI. So let's change the example slightly:

    public static void main( String[] args ) {
        Model m = ModelFactory.createDefaultModel();
        String NS = "http://example.com/foo#";
        Property p = m.createProperty( NS + "p" );
        Resource r = m.createResource( NS + "r" );
        r.addProperty( p, 42 );
        m.write( System.out, "RDF/XML" );
    }

OK, now this runs and produces the following output:

<rdf:RDF
    xmlns:j.0="http://example.com/foo#"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" >
  <rdf:Description rdf:about="http://example.com/foo#r">
    <j.0:p>42</j.0:p>
  </rdf:Description>
</rdf:RDF>

So here's the mysterious j.0 appearing. What's going on? The j.0 is an XML namespace. It's defined in the root element of the RDF file:

    xmlns:j.0="http://example.com/foo#"

To get the full URI, just replace j.0: with the URI defined in the namespace declaration. But why was it put there at all? Consider the alternative. With RDF's striping XML syntax, elements are alternately resource and property names. Suppose we hadn't used a namespace for p:

<rdf:RDF
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" >
  <rdf:Description rdf:about="http://example.com/foo#r">
    <http://example.com/foo#p>42</http://example.com/foo#p>
  </rdf:Description>
</rdf:RDF>

<http://example.com/foo#p> isn't a legal XML element name. It contains characters (such as colon) that are not syntactically permitted in an XML element name. So, using XML's namespace mechanism gets us out of a hole when we want RDF identifiers in XML to be URI's. It also has value in its own right though: semantically your p relation may denote something different to my p relation; if we put them in different namespaces there's much less chance of an accidental confusion of semantics.

So, now that we know why j.0 appears, what can we do? One solution is to not use XML output. The same example, written in N3 format instead of RDF/XML, becomes:

<http://example.com/foo#r>
      <http://example.com/foo#p>
              "42" .

No funny prefixes in sight. Alternatively, we can just ensure that we use a sensible name for the namespace instead of Jena's autogenerated j.0, j.1, etc. The key to this is the PrefixMapping interface, which is a super-interface of Model. The method setNsPrefix lets us assign a more meaningful (to human readers!) namespace:

    public static void main( String[] args ) {
        Model m = ModelFactory.createDefaultModel();
        String NS = "http://example.com/foo#";
        m.setNsPrefix( "eg", NS );
        Property p = m.createProperty( NS + "p" );
        Resource r = m.createResource( NS + "r" );
        r.addProperty( p, 42 );
        m.write( System.out, "RDF/XML" );
    }

Producing:

<rdf:RDF
    xmlns:eg="http://example.com/foo#"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" >
  <rdf:Description rdf:about="http://example.com/foo#r">
    <eg:p>42</eg:p>
  </rdf:Description>
</rdf:RDF>

del.icio.us: jena, semantic web.

5 comments:

Anonymous said...

could you explain how to parse a simple owl ontology using Jena APIs? Thanks!

Ian said...

Yes, I'll do a quick overview shortly. In the meantime, there's quite a reasonable tutorial at the Jena site.

Iouri Goussev said...

Thank you! Thank you! Thank you!

Anonymous said...

thanks, great tip!

Amal said...

thank you