Read an RDF/XML document as the same triples vaelii.foreign.turtle yields.
RDF/XML is a third syntax for the graph the other two already carry, so this is a
second lexer and not a second reader: it emits {:s :p :o} maps with terms spelled
exactly as turtle spells them, and vaelii.foreign.rdf's OWL projection is reached
without changing a line of it. Nothing here knows what rdfs:subClassOf means.
Why it has to exist. Turtle is what a person writes and N-Triples is what a dump ships, but RDF/XML is what an OWL ontology is published as — it was the only serialization OWL 1 defined, so the tooling that generates ontologies still emits it. OpenCyc's OWL export, DOLCE, and the OWL product of every OBO Foundry ontology are all RDF/XML. A reader that stopped at Turtle could not open any of them.
The syntax is striped, alternating node and property elements:
<rdf:Description rdf:about="#Dog"> <!-- node: the subject -->
<rdfs:subClassOf rdf:resource="#Mammal"/> <!-- property: one triple -->
<rdfs:label xml:lang="en">dog</rdfs:label>
</rdf:Description>
and nearly everything else in the grammar abbreviates that shape. A node element's
tag is an rdf:type triple unless it is rdf:Description; an attribute that is not
syntax is a triple with a literal object; rdf:parseType switches the content between
three readings; rdf:li counts. The awkward part of RDF/XML is not the striping but
how many ways it offers to write one triple, and this reader's job is that every one
of them lands as the same data.
Parsed with the JDK's StAX, pulled one top-level node element at a time, so a
252 MB ontology streams rather than building a DOM. DTD support is on because RDF/XML
routinely declares internal entities for its namespaces (<!ENTITY owl "http://…">,
then &owl;Class) and a parser rejecting those could not read the files it exists for;
external entities are off, which is what keeps that safe.
What is approximated. rdf:parseType="Literal" should hold the exclusive XML
canonicalization of its content. This writes a faithful but not canonical
serialization — attribute order and namespace declarations may differ from C14N — so
an XMLLiteral compares equal to itself and not necessarily to another parser's. No
ontology reasons over one, and vaelii.foreign.rdf keeps it as a string.
Read an RDF/XML document as the same triples `vaelii.foreign.turtle` yields.
RDF/XML is a **third syntax for the graph the other two already carry**, so this is a
second lexer and not a second reader: it emits `{:s :p :o}` maps with terms spelled
exactly as `turtle` spells them, and `vaelii.foreign.rdf`'s OWL projection is reached
without changing a line of it. Nothing here knows what `rdfs:subClassOf` means.
**Why it has to exist.** Turtle is what a person writes and N-Triples is what a dump
ships, but RDF/XML is what an *OWL ontology* is published as — it was the only
serialization OWL 1 defined, so the tooling that generates ontologies still emits it.
OpenCyc's OWL export, DOLCE, and the OWL product of every OBO Foundry ontology are all
RDF/XML. A reader that stopped at Turtle could not open any of them.
**The syntax is striped**, alternating node and property elements:
```xml
<rdf:Description rdf:about="#Dog"> <!-- node: the subject -->
<rdfs:subClassOf rdf:resource="#Mammal"/> <!-- property: one triple -->
<rdfs:label xml:lang="en">dog</rdfs:label>
</rdf:Description>
```
and nearly everything else in the grammar abbreviates that shape. A node element's
tag is an `rdf:type` triple unless it is `rdf:Description`; an attribute that is not
syntax is a triple with a literal object; `rdf:parseType` switches the content between
three readings; `rdf:li` counts. The awkward part of RDF/XML is not the striping but
how many ways it offers to write one triple, and this reader's job is that every one
of them lands as the same data.
**Parsed with the JDK's StAX**, pulled one top-level node element at a time, so a
252 MB ontology streams rather than building a DOM. DTD support is on because RDF/XML
routinely declares internal entities for its namespaces (`<!ENTITY owl "http://…">`,
then `&owl;Class`) and a parser rejecting those could not read the files it exists for;
**external** entities are off, which is what keeps that safe.
**What is approximated.** `rdf:parseType="Literal"` should hold the exclusive XML
canonicalization of its content. This writes a faithful but not canonical
serialization — attribute order and namespace declarations may differ from C14N — so
an XMLLiteral compares equal to itself and not necessarily to another parser's. No
ontology reasons over one, and `vaelii.foreign.rdf` keeps it as a string.(triples rdr)(triples rdr opts)Every triple rdr holds, as a lazy seq of {:s :p :o} maps — the same shape
vaelii.foreign.turtle/triples returns, so a caller need not know which syntax it got.
One top-level node element is parsed per pull, which is what keeps a large ontology streaming: the queue holds one class's description, not the document.
opts may carry :base, for a document whose own xml:base is absent and whose
relative IRIs are meant to resolve against where it was fetched from.
Every triple `rdr` holds, as a lazy seq of `{:s :p :o}` maps — the same shape
`vaelii.foreign.turtle/triples` returns, so a caller need not know which syntax it got.
One *top-level node element* is parsed per pull, which is what keeps a large ontology
streaming: the queue holds one class's description, not the document.
`opts` may carry `:base`, for a document whose own `xml:base` is absent and whose
relative IRIs are meant to resolve against where it was fetched from.(with-triples path f)(with-triples path f opts)Open the RDF/XML file at path, call (f triples) on a lazy seq of its triples, and
close the file after. .gz is decompressed on the way through — the OpenCyc OWL
export ships that way and is a tenth the size for it.
Open the RDF/XML file at `path`, call `(f triples)` on a lazy seq of its triples, and close the file after. `.gz` is decompressed on the way through — the OpenCyc OWL export ships that way and is a tenth the size for it.
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |