Another approach ...
Transforming the Abbreviated Syntax into Very Basic RDF
Introduction
This document gives a design for an XML transform based approach to specifying
the semantics of an RDF/XML document.
The implementation of this design may be in XSLT; however any appropriate
XML transform framework should do.
A key design goal is to be declarative. The total semantics is given
by a set of simple transforms. Each transform gives the meaning of one
of the grammar rules of the abbreviated syntax.
A naive implementation can transform an RDF document by repreatedly
applying any of the simple transforms that match any top-level element
in the document. When no more simple transforms match the document is in
Very Basic RDF.
Very Basic RDF
Very Basic RDF is motivated by the Basic Serialization of M&S. Principle
differences are:
-
Each rdf:Description element has exactly one child element, describing
a single property.
-
Thus each rdf:Description element corresponds to one triple in the model.
-
rdf:parseType="Literal" is supported in the propertyElt production.
-
rdf:about="local:name" and rdf:resource="local:name" both refer to bNodes
rather than graph node labelled with URIs. (Note: I will change "local:"
to be an illegal namespace prefix to avoid clashing in future versions
of RDF)
Example:
<rdf:RDF xmlns:rdf="..." xmlns:foo="...">
<rdf:Description rdf:about="local:v1">
<foo:bar>Simple string value</foo:bar>
</rdf:Description>
<rdf:Description rdf:about="http://example.org/">
<rdf:value rdf:resource="local:v1"/>
</rdf:Description>
<rdf:Description rdf:about="http://example.org/">
<foo:baz rdf:parseType="Literal">
<an>XML Literal</an>
</foo:baz>
</rdf:Description>
<rdf:Description rdf:about="http://example.org/">
<rdf:type rdf:resource="http://example.org/ExampleClass"/>
</rdf:Description>
<rdf:RDF>
The mapping from very basic RDF to NTriple is straight forward (except
rdf:parseType="Literal").
Limitations for now
I only consider bits of the abbreviated syntax, specifically I will duck
for now bagID and aboutEach. However, unlike with the LFG approach I do
not think these are inherently impossible, just hard.
Without much loss of generality I will just consider XML documents
whose document element is rdf:RDF.
I will talk informally about the rules, using a very loose syntax with
$ variables. I will refer to the grammar rules using EBNF forms rather
than the new forms in infoset, this is simply for convenience. Unlike with
the LFG approach, this transform approach is built on infoset not EBNF.
I don't treat xml attributes nor do I correctly handle namespaces (in
some of the propertyElt productions in particular).
The input must be well-formed.
The transforms
Remember: these only apply to the top-level elements, i.e. the immediate
children of the rdf:RDF node.
This is not intended to be correct yet, just indicative of an approach.
All the rules should be mutually exclusive or commutative so there
is no ambiguity about the meaning of an RDF doc.
I have made up the notation simply for this doc. There is no key :(.
PropAttr-1:
<$tag $any-attrs $prop=$val>
$any-content
</$tag> with $prop not in namespace rdf.
==>
<$tag $any-attrs>
<$prop>$val</$prop>
$any-content
</$tag>
PropAttr-2:
<$tag $any-attrs rdf:type=$val>
$any-content
</$tag> with $prop not in namespace rdf.
==>
<$tag $any-attrs>
<rdf:type rdf:resource=$val/>
$any-content
</$tag>
bNode:
<$tag>
$any-content
</$tag>
==>
<$tag rdf:about=GenSym()>
$any-content
</$tag>
GenSym() is a function which always returns
a different string value starting in "local:"
TypedNode 1:
<$tag rdf:about=$uri>
$any-content
</$tag>
with $tag != rdf:Description
==>
<rdf:Description rdf:about=$uri rdf:liCounter="1">
<rdf:type rdf:resource=$tag/>
$any-content
</rdf:Description>
TypedNode 2:
<$tag rdf:ID=$id>
$any-content
</$tag>
with $tag != rdf:Description
==>
<rdf:Description rdf:about="#"&$id rdf:liCounter="1">
<rdf:type rdf:resource=$tag/>
$any-content
</rdf:Description>
Description 1:
<rdf:Description rdf:about=$uri rdf:liCounter=$N />
may include whitespace as element content
==>
empty
Description 2 (liCounter):
<rdf:Description rdf:about=$uri rdf:liCounter=$N >
<rdf:li $attrs>
$elt-content
</rdf:li>
$content
</rdf:Description>
==>
<rdf:Description rdf:about=$uri >
<rdf:_$N $attrs>
$elt-content
</rdf:_$N>
</rdf:Description>
<rdf:Description rdf:about=$uri rdf:liCounter=eval("1+$N") >
$content
</rdf:Description>
Description 3:
<rdf:Description rdf:about=$uri rdf:liCounter=$N >
<$prop $attrs>$elt-content</$prop>
$content
</rdf:Description>
with $prop != rdf:li
==>
<rdf:Description rdf:about=$uri >
<$prop $attrs>$elt-content</$prop>
</rdf:Description>
<rdf:Description rdf:about=$uri rdf:liCounter=$N) >
$content
</rdf:Description>
PropertyElt 1:
<rdf:Description rdf:about=$uri >
<$prop rdf:ID?>
<$tag rdf:ID=$id $attrs>
$content
</$tag>
</$prop>
</rdf:Description>
==>
<$tag rdf:ID=$id $attrs>
$content
</$tag>
<rdf:Description rdf:about=$uri >
<$prop rdf:ID? rdf:resource="#"&$ID/>
</rdf:Description>
Note the optional reification ID is carried over from the template
to the result element.
PropertyElt 2:
<rdf:Description rdf:about=$uri >
<$prop rdf:ID?>
<$tag rdf:about=$uri $attrs>
$content
</$tag>
</$prop>
</rdf:Description>
==>
<$tag rdf:about=$uri $attrs>
$content
</$tag>
<rdf:Description rdf:about=$uri >
<$prop rdf:ID? rdf:resource=$uri/>
</rdf:Description>
Note the optional reification ID is carried over from the template
to the result element.
PropertyElt 3:
<rdf:Description rdf:about=$uri >
<$prop rdf:ID?>
<$tag $attrs>
$content
</$tag>
</$prop>
</rdf:Description>
with rdf:about and rdf:ID not in $attrs
and $genSym = GenSym()
==>
<$tag rdf:about=$genSym $attrs>
$content
</$tag>
<rdf:Description rdf:about=$uri >
<$prop rdf:ID? rdf:resource=$genSym/>
</rdf:Description>
Note the optional reification ID is carried over from the template
to the result element.
PropertyElt 4:
<rdf:Description rdf:about=$uri >
<$prop rdf:ID? rdf:parseType="Resource">
$content
</$prop>
</rdf:Description>
==>
<rdf:Description rdf:about=$uri >
<$prop rdf:ID?>
<rdf:Descrption>
$content
</rdf:Descrption>
</$prop>
</rdf:Description>
Note the optional reification ID is carried over from the template
to the result element.
PropertyElt 5:
<rdf:Description rdf:about=$uri >
<$prop rdf:ID? rdf:resource=$uri $attrs/>
</rdf:Description>
with $attrs != empty
==>
<rdf:Description rdf:about=$uri >
<$prop rdf:ID?>
<rdf:Descrption rdf:about=$uri
$attrs/>
</$prop>
</rdf:Description>
Note the optional reification ID is carried over from the template
to the result element.
PropertyElt 6:
<rdf:Description rdf:about=$uri >
<$prop rdf:ID? $attrs/>
</rdf:Description>
with $attrs != empty and not containing rdf:resource
==>
<rdf:Description rdf:about=$uri >
<$prop rdf:ID?>
<rdf:Descrption $attrs/>
</$prop>
</rdf:Description>
Note the optional reification ID is carried over from the template
to the result element.
Reification 1:
<rdf:Description rdf:about=$subject >
<$prop rdf:ID=$reify rdf:resource=$object/>
</rdf:Description>
==>
<rdf:Description rdf:about=$subject >
<$prop rdf:resource=$object/>
</rdf:Description>
<rdf:Description rdf:about=$reify >
<rdf:object rdf:resource=$object/>
</rdf:Description>
<rdf:Description rdf:about=$reify >
<rdf:subject rdf:resource=$subject/>
</rdf:Description>
<rdf:Description rdf:about=$reify >
<rdf:predicate rdf:resource=$prop/>
</rdf:Description>
<rdf:Description rdf:about=$reify >
<rdf:type rdf:resource=rdf:Statement/>
</rdf:Description>
Reification 2:
<rdf:Description rdf:about=$subject >
<$prop rdf:ID=$reify>$object<$prop/>
</rdf:Description>
where $object is empty or a text string
==>
<rdf:Description rdf:about=$subject >
<$prop>$object<$prop/>
</rdf:Description>
<rdf:Description rdf:about=$reify >
<rdf:object>$object<rdf:object/>
</rdf:Description>
<rdf:Description rdf:about=$reify >
<rdf:subject rdf:resource=$subject/>
</rdf:Description>
<rdf:Description rdf:about=$reify >
<rdf:predicate rdf:resource=$prop/>
</rdf:Description>
<rdf:Description rdf:about=$reify >
<rdf:type rdf:resource=rdf:Statement/>
</rdf:Description>
Reification 3:
<rdf:Description rdf:about=$subject >
<$prop rdf:ID=$reify rdf:parseType="Literal">
$object
<$prop/>
</rdf:Description>
==>
<rdf:Description rdf:about=$subject >
<$prop rdf:parseType="Literal">
$object
<$prop/>
</rdf:Description>
<rdf:Description rdf:about=$reify >
<rdf:object rdf:parseType="Literal">
$object
<rdf:object/>
</rdf:Description>
<rdf:Description rdf:about=$reify >
<rdf:subject rdf:resource=$subject/>
</rdf:Description>
<rdf:Description rdf:about=$reify >
<rdf:predicate rdf:resource=$prop/>
</rdf:Description>
<rdf:Description rdf:about=$reify >
<rdf:type rdf:resource=rdf:Statement/>
</rdf:Description>