Saturday, November 11, 2006

A Plug-in Mechanism for N3/Turtle

A human readable syntax is helpful for the wide adoption of any language. Many newcomers to the OWL and semantic technology world are scared away by the rather cryptic RDF/XML serialization. This serialization also makes it difficult to copy-and paste fragments and to debug.

At one occasion during the OWL 1.1 workshop, I commented that the N3 syntax is much more readable and hand-codable than the other triple-based formats of OWL. For example, the snippet below shows a class definition of Capital, a subclass of City that has some Museums.


:Capital
a owl:Class ;
rdfs:subClassOf :City ;
rdfs:subClassOf
[ a owl:Restriction ;
owl:onProperty :hasActivity ;
owl:someValuesFrom :Museums
] .

I think this is still maintainable by hand, and I know of several people who use text editors like emacs for all their ontology work. However, if logical class expressions and blank node trees become more deeper, then even N3 becomes difficult to read:


:BudgetAccommodation
a owl:Class ;
owl:equivalentClass
[ a owl:Class ;
owl:intersectionOf (:Accommodation [ a owl:Restriction ;
owl:onProperty :rating ;
owl:someValuesFrom
[ a owl:Class ;
owl:oneOf (:OneStar :TwoStar)
]
])
] .

Some people in the OWL 1.1 field will work on a human-editable format for OWL class expressions, based on the Manchester OWL syntax. For example, the equivalent class above would be written as

Acommodation and (hasRating some {OneStarRating TwoStarRating})

This syntax is already supported by TopBraid Composer and Protege-OWL.

The idea I'd like to discuss in this entry is to define a plug-in mechanism for N3/Turtle, so that domain-specific custom serializations like the Manchester Syntax can be used inside of N3 documents. The following snippet shows the N3 file above with a Manchester Syntax N3 plug-in.


:BudgetAccommodation
a owl:Class ;
owl:equivalentClass
@manchesterSyntax("Acommodation and (rating some {OneStar TwoStar})") .

The same approach could be used to embed other RDF-based languages such as SWRL. Without this hack, an average SWRL rule would look like


:Def-hasUncle
a swrl:Imp ;
swrl:body
[ a swrl:AtomList ;
rdf:first
[ a swrl:IndividualPropertyAtom ;
swrl:argument1 :x ;
swrl:argument2 :y ;
swrl:propertyPredicate
:hasParent
] ;
rdf:rest
[ a swrl:AtomList ;
rdf:first
[ a swrl:IndividualPropertyAtom ;
swrl:argument1 :y ;
swrl:argument2 :z ;
swrl:propertyPredicate
:hasBrother
] ;
rdf:rest ()
]
] ;
swrl:head
[ a swrl:AtomList ;
rdf:first
[ a swrl:IndividualPropertyAtom ;
swrl:argument1 :x ;
swrl:argument2 :z ;
swrl:propertyPredicate
:hasUncle
] ;
rdf:rest ()
] .

but this could be shortened to



:Def-hasUncle
@swrl("(?x hasParent ?y) (?y hasBrother ?z) -> (?x hasUncle ?z)") .



N3/Turtle parsers would be able to handle these specific extensions generically, if the N3 files would declare how to convert the domain-specific expressions into triples. For example, the N3 file could start with a declaration that points to a web service such as


@plugin manchesterSyntax: <http://man.uk/parser> .

where the Web service (or a local implementation of it) could take the string and the current subject and namespace prefixes as input, and return a stream of triples as output.

Such a plug-in mechanism for N3 would not only make N3 files much easier to maintain, but also significantly shorter. This way, this approach would IMHO be an attractive alternative to data exchange formats like DIG 2.0.

Theoretically this approach could also be used to embed SPARQL queries inside of N3 files, and to dynamically create triples depending on the context. There are certainly many use cases that I am currently missing - just brainstorming...

0 Comments:

Post a Comment

<< Home