fix: extract rdfs:subClassOf hierarchies as relationships (Brick follow-up) - #102
Open
Mathew Benjamin (mathewtbenjamin) wants to merge 2 commits into
Open
Conversation
Importing the Brick ontology (and any ontology serialized by rdflib or
similar tools) failed with 'No ontology metadata or OWL classes found'.
The parser only recognized typed node elements (<owl:Class rdf:about>),
but many serializers emit the equivalent rdf:Description form:
<rdf:Description rdf:about='...'>
<rdf:type rdf:resource='http://www.w3.org/2002/07/owl#Class'/>
</rdf:Description>
Brick 1.4's official RDF/XML declares all 1,530 classes this way and
contains zero typed elements.
- Add getTypedElements(): collects both typed node elements and
rdf:Description elements typed via rdf:type, used for owl:Ontology,
owl:Class, owl:DatatypeProperty and owl:ObjectProperty extraction.
- Detect Turtle input (@prefix/@base) and raise a clear, actionable
error instead of 'Malformed XML' (brickschema.org defaults to .ttl).
- Replace the live getElementsByTagName('*') collection in the
DataBinding scan with a static querySelectorAll('*') snapshot;
repeated indexed access on live collections is quadratic in some DOM
implementations, making large imports pathologically slow.
- 9 new tests: rdf:Description extraction for all four types, mixed
syntax dedupe, and Turtle detection.
Verified against Brick 1.4 RDF/XML (5.3 MB): parses to 1,530 entity
types, ontology name 'Brick'.
Fixes microsoft#85
Importing taxonomy-shaped ontologies (e.g. Brick) produced a graph of fully disconnected nodes: the relationship mapper only used owl:ObjectProperty rdfs:domain/rdfs:range pairs, and Brick 1.4 carries just 2 rdfs:domain / 5 rdfs:range statements in the whole file. Its actual structure is 2,016 rdfs:subClassOf statements between classes, which the parser ignored entirely. - Add getChildResources(): collects every rdf:resource reference for a given child local name (a class may declare multiple parents). - After class extraction, emit a many-to-one 'subClassOf' relationship for each rdfs:subClassOf reference whose target was imported as an entity. External parents (owl:Thing, other vocabularies), nested owl:Restriction forms, self-references, and duplicate edges are skipped. - 7 new tests: typed-node + rdf:Description syntaxes, multiple inheritance, external-parent/self-reference/duplicate skipping, owl:Restriction tolerance, coexistence with object-property relationships. Verified against Brick 1.4 RDF/XML (5.2 MB): 1,530 entities now carry 1,739 subClassOf relationships connecting 1,525 of them (previously 0 relationships), with no duplicate ids and unchanged parse time (~7s under jsdom). Fixes microsoft#101
Author
|
Friendly nudge 🙂 — this PR has been open ~3 weeks, the CLA check is green, and it's currently mergeable with no conflicts. Is there anything I can do to help move it toward review (rebase, split, or extra context)? Happy to help. Thanks! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #101 — after #96 makes the Brick import succeed, the resulting graph is 1,530 fully disconnected nodes: 0 relationships.
Root cause: the relationship mapper only builds edges from
owl:ObjectPropertyelements carryingrdfs:domain/rdfs:rangepairs. Brick 1.4 has just 2rdfs:domain/ 5rdfs:rangestatements in the whole 5.2 MB file. Its actual graph structure is the class taxonomy — 2,016rdfs:subClassOfstatements between classes — which the parser dropped entirely. This affects any taxonomy-shaped ontology, not just Brick.Changes
getChildResources()(new helper insrc/lib/rdf/parser.ts): plural counterpart ofgetChildResource()— collects everyrdf:resourcereference for a child local name, since a class may declare multiple parents.rdfs:subClassOfreference whose target was imported as an entity becomes amany-to-onerelationship namedsubClassOf(id<sub>-subClassOf-<super>). Deliberately conservative:owl:Thing, other vocabularies) are skipped — no dangling edges;owl:Restrictionforms (nordf:resource) are ignored gracefully;rdf:Descriptionsyntaxes, multiple inheritance, external-parent/self-reference/duplicate skipping,owl:Restrictiontolerance, and coexistence with object-property relationships.Validation
npx tsc --noEmit— cleannpx eslinton touched files — cleannpx vitest run— 24 files, 408/408 tests pass (7 new)subClassOfrelationships connecting 1,525 of them (previously 0), no duplicate relationship ids, parse time unchanged (~7s under jsdom)Notes
fix/turtle-import-error) — it needsgetTypedElements()from that branch to see Brick'srdf:Description-typed classes at all. The first commit here is fix: support rdf:Description typed-node syntax in RDF import (Brick) #96's; onlyc042566is new. Happy to rebase once fix: support rdf:Description typed-node syntax in RDF import (Brick) #96 lands.owl:ObjectProperty— re-exporting an imported taxonomy is lossy w.r.t.rdfs:subClassOfsemantics. Faithful subClassOf serialization could be a follow-up if wanted.sh:property→sh:path/sh:class, blank-node indirection); noted in Imported ontologies with rdfs:subClassOf hierarchies have no relationships (Brick: 1,530 entities, 0 edges) #101 as a possible further enhancement, out of scope here.