RDF Nice (dfki.rdf.util.RDFNice)
Despite the fact that RDF is generally nothing but a graph, typical RDF data often has hierarchical structure(s). And as the typical form of serialization of RDF is XML, which explicitly provides hierarchy, it is just a pity, that we aren't using the hierarchical presentation althought it's useful. Well, the reason for this is, of course, that you can't ever present RDF hierarchical, generally. But: In non-general, say, typical, scenarios, your RDF is nearly always structured hierarchically to the max. That's why I wrote this small tool.
The idea behind RDF Nice is to give the XML serializer some hints about which predicate is a hierarchy-driving relation. You do this by assigning some predicates positive or negative numbers. If you assign a positive number to a predicate, this will indicate, that following this predicate will go DOWN the hierarchy; negative numbers indicate, that following the predicate is UP the hierarchy. You can prioritize these UP/DOWN indications by using higher numbers (+100 is stronger than +1, -10 is also stronger than +1, but weaker than +100). At the moment, you have to cope with integer numbers, a lexical ordering would, of course, be better... Note, that -10 is only ten times stronger than +1, which means, that eleven predicate of type +1 outperform one of type -10!
So, what's happening with all that numbers?
- First of all, RDF Nice puts all RDF subjects in a bag. Iteratively, subjects are being drawn out of this bag and are attached to some XML branch.
- Every time, a subject has to be chosen, to be taken out of the bag, RDF Nice calculates for each residuary subject a value. This value results from summing the values of all outgoing predicates plus the negative(!) sum of all incoming predicates. Then the subject with the highest value is taken.
- After the XML element has been created, the outgoing predicates together with the objects, these predicates are pointing to, are attached below the subject node. The ordering of these predicates will be according to there value, i.e., the predicate with the highest value will be the first child of the subject node.
- Whenever a predicate points to some subject still in the bag, the algorithm will go into recursion and that way create the hierarchical presentation. If the predicate points to some subject not in the bag, this means, either that subject is not part of the RDF data, or that subject has already attached elsewhere on the XML tree. Anyhow, in that case, the subject is not serialized again, but just referenced in the RDF typical manner.
Whatever values you assign to predicates, the resulting RDF will always stay the same, just the presentation changes. However, I wouldn't swear to RDF Diff being bug-less. ;-)
Call RDF Diff the following way to get a "nice" version of the RDF file for our small "Person" example:
java -cp <...CLASSPATH...> dfki.rdf.util.RDFNice C:\TEMP\example1.rdf http://org.dfki/rdf2java/example1#hasParent -1000 http://org.dfki/rdf2java/example1#name 1
So, the first parameter is the RDF file, followed by arbitrarily many pairs(!) of parameters, namely one for the predicate (the whole URI, not only the local name), and one for the value you want to assign to that predicate. RDF Nice produces another file (so no original RDF file will be harmed) with the same path and filename plus postfix ".nice.rdf", i.e., "example1.rdf.nice.rdf" in our example. Doing this, you get the following RDF, which is not quite impresing, but that's because the simple "Person" example is a bad one. The only hierarchical relation is pointing into the wrong direction, namely upwards, but XML serialization is always about the other direction, namely downwards. Note, that the predicate name comes before hasParent, because its value is greater (greater, not stronger!).
<?xml version='1.0' encoding='ISO-8859-1'?> <!DOCTYPE rdf:RDF [ <!ENTITY example1 'http://org.dfki/rdf2java/example1#'> <!ENTITY rdf 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'> <!ENTITY rdfs 'http://www.w3.org/TR/1999/PR-rdf-schema-19990303#'> ]> <rdf:RDF xmlns:example1="&example1;" xmlns:rdf="&rdf;" xmlns:rdfs="&rdfs;"> <example1:Person rdf:about="&example1;example1_00006" example1:name="Homer Simpson"/> <example1:Person rdf:about="&example1;example1_00005" example1:name="Bart Simpson"> <example1:hasParent rdf:resource="&example1;example1_00006"/> </example1:Person> </rdf:RDF>
To get a better picture of RDF Nice, we switch to example2.* in the example directory. To rememver, we added a new property to the RDF Schema: the property hasChild being the inverse property to hasParent. Changing the call to RDF Nice (see rdfnice.bat) taking into account the new property (hasChildis assigned the negative value of hasParent: +1000), we receive the following XML serialization for example2_lisa.rdf (including Lisa):
<?xml version='1.0' encoding='ISO-8859-1'?> <!DOCTYPE rdf:RDF [ <!ENTITY example1 'http://org.dfki/rdf2java/example1#'> <!ENTITY rdf 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'> <!ENTITY rdfs 'http://www.w3.org/TR/1999/PR-rdf-schema-19990303#'> ]> <rdf:RDF xmlns:example1="&example1;" xmlns:rdf="&rdf;" xmlns:rdfs="&rdfs;"> <example1:Person rdf:about="&example1;example1_00006" example1:name="Homer Simpson"> <example1:hasChild> <example1:Person rdf:about="&example1;example1_00005" example1:name="Bart Simpson"> <example1:hasParent rdf:resource="&example1;example1_00006"/> </example1:Person> </example1:hasChild> <example1:hasChild> <example1:Person rdf:about="&example1;example2_00007" example1:name="Lisa Simpson"> <example1:hasParent rdf:resource="&example1;example1_00006"/> </example1:Person> </example1:hasChild> </example1:Person> </rdf:RDF>