This is an exploratory editor's draft. Its source is both a ReSpec document and a conforming example of the IA² attribute binding it defines. The embedded decision trace uses the Inferal Decision Ontology and PROV-O. The optional RDF Navigator shows the dataset extracted from the current live DOM and refreshes after semantic mutations.

Abstract

This document defines a deliberately small model for extracting an RDF 1.2 dataset from an HTML document, together with a provisional attribute-based binding of that model.

The model keeps semantic information attached to the HTML that presents it. It does not embed another serialization, depend on a remote context, execute script, or construct triples through inherited parser state.

Its central rule is:

One statement element in an extraction root’s tree determines one complete asserted RDF triple. The same element shape inside an object-position template determines one unasserted triple term.

A statement element represents its own subject by default. A non-empty native HTML id gives that subject a fragment IRI; without one, the subject is an element-local blank node. Explicit subject attributes let the statement describe another IRI or a reusable extraction-local resource without introducing inherited context.

Ordinary HTML attributes and content carry the RDF object. There is no rdf-object attribute and no miniature RDF term language inside an attribute value. An inline, inert template used as a statement’s object carrier represents an RDF 1.2 triple term. Because template contents occupy a separate DocumentFragment, an unasserted triple term does not accidentally become an asserted document triple and does not appear in an ordinary document-wide DOM query. The contents of any other template may be supplied separately as a DocumentFragment extraction root without adding them to the containing document’s dataset.

The model is vocabulary-neutral. SHACL Core, SHACL Advanced Features, SHACL 1.2 Rules, OWL, PROV-O, and other RDF vocabularies require no model-specific extensions.

Goals

The Core model has the following goals:

  1. HTML-native: RDF is carried by HTML elements and attributes, not by an embedded JSON-LD, Turtle, or RDF/XML document.
  2. Local: extraction requires only the parsed HTML document and its retrieval, semantic source, and base IRIs; it does not require dereferencing the canonical document IRI.
  3. Deterministic: every statement element is locally complete.
  4. Queryable: asserted statements are selectable with a normal DOM query.
  5. Non-executing: extraction never executes JavaScript, custom elements, event handlers, SPARQL, SHACL rules, or other code.
  6. RDF-model-complete: within the strings and IRIs representable by the HTML DOM, the syntax can represent every RDF 1.2 term kind and dataset structure, including blank nodes, empty and populated named graphs, arbitrary datatypes, directional language-tagged strings, nested triple terms, and reification.
  7. Shape-complete: SHACL and SHACL-AF graphs use exactly the same mechanism as all other RDF.
  8. Human-correlated: visible semantic HTML may serve simultaneously as presentation and as the lexical or IRI value of an RDF object, while exact-value and metadata-only carriers remain available when they better fit the document.

Non-goals

The Core model does not define:

Those features may be defined by separate layers. They must not change the dataset extracted by this Core model.

Design invariants

One element, one complete statement

An element bearing rdf-predicate is a statement element. A conforming statement element MUST determine exactly one subject, one predicate, one object, and at most one graph name.

An incomplete statement element is an authoring error. Processors MUST NOT retain it as pending state or complete it from a descendant, ancestor, sibling, or later element.

No inheritance

The following values are never inherited for RDF extraction:

HTML nesting has no RDF meaning by itself.

This decision rejects RDFa-style scoped evaluation context in favor of local decidability. Once the source document IRI and document base IRI are known, a processor can determine a statement by inspecting its element and, only for a triple-term object, its direct object template. It never needs to walk ancestors looking for a subject, graph, datatype, language, vocabulary, or partially constructed relationship.

The rationale is practical:

The cost is some repetition: a descendant that describes an identified ancestor refers to that ancestor explicitly, and graph names, datatypes, and literal metadata may appear on multiple elements. The Core model accepts that cost because explicit references are easier to inspect, move, sign, cache, and debug than inherited meaning. An element describing itself does not repeat its subject: its own HTML identity supplies the default.

HTML inheritance still controls presentation and accessibility as usual. For example, an ancestor’s lang continues to affect the rendered document, but it does not become part of an RDF literal unless lang is directly present on the statement element. This keeps the identity of the extracted RDF term stable when the element moves between HTML contexts.

No implicit chaining

The object of one statement does not become the subject of nested statements. A statement’s subject is constructed from that statement element itself or given by an explicit subject attribute; it never flows from another statement.

No external semantic state

The Core model has no context URL, default vocabulary, imported prefix map, or vocabulary lookup step. Ordinary IRI references are resolved against the RDF document base IRI. Element identities and fragment-only subject references use the source document IRI established from the retrieval IRI and any usable HTML canonical link, as defined in §5.2.

Processors MUST NOT dereference an IRI merely to extract the dataset.

Core 0.1 defines no compact IRI or prefix-expansion syntax. A value such as schema:name is processed as an ordinary RFC 3987 IRI reference and, because it has a scheme component, denotes the absolute IRI schema:name; it is never expanded through a prefix map. Authoring tools MAY accept compact notation in their own interfaces, but they MUST emit full IRI references when producing this binding.

Extraction is not execution

Extracting a SHACL rule, SPARQL query, function declaration, script IRI, or executable vocabulary term records RDF statements only. It does not authorize or cause execution.

Proposed HTML attribute binding

The rdf-* names below are the canonical attribute spelling proposed by this document. They are defined as global HTML attributes: any HTML element may carry them where the processing rules permit.

Existing browsers preserve unknown attributes in the DOM and otherwise ignore them, so the binding degrades safely before native browser support exists. HTML validators may report these attributes as nonconforming until they are incorporated into an applicable HTML specification or extension.

The Core Model is independent of this spelling. A different host-language binding may use different surface syntax while preserving the same assertion boundaries and term-construction rules.

Attribute Meaning
rdf-version="1.2" Announces this HTML binding and RDF version on the html element
rdf-subject="IRI reference" Overrides the element’s default subject with an IRI subject
rdf-subject-key="key" Overrides the default subject with the blank node selected by an extraction-local key
rdf-predicate="IRI reference" Marks a statement element and gives its predicate
rdf-object-key="key" Makes the object the blank node selected by an extraction-local key
rdf-datatype="IRI reference" Gives the datatype of a literal object
rdf-graph="IRI reference" Places a statement in an IRI-named graph, or declares that graph on a non-statement element
rdf-graph-key="key" Places a statement in a blank-node-named graph, or declares that graph on a non-statement element

The existing HTML id attribute participates in subject construction. The native single-IRI carriers listed in §5.4.3, meta[content], data[value], time[datetime], and the directly present lang and dir attributes participate in object construction as defined below.

There is intentionally no general rdf-object attribute containing a serialized RDF term. rdf-object-key is a specialized correlation carrier for the one object kind that native HTML cannot otherwise identify: a reusable anonymous resource.

The three *-key attributes are deliberately positional. A single RDF dataset statement can independently use a blank node as its subject, its object, and its graph name, so the role of a local key cannot be inferred from one undifferentiated attribute. Keeping the role in the attribute name avoids a term mini-language, ancestor scope, or DOM lookup.

“Key” is an HTML-authoring concept in this binding. A key correlates occurrences within one extraction of a document or one of its fragments; it is not an RDF identifier and does not survive into the RDF dataset. The extractor maps each distinct key to a blank node. Core 0.1 fixes the positional rdf-subject-key, rdf-object-key, and rdf-graph-key surface because RDF permits independent blank nodes in all three positions and a generic key would require an embedded role syntax or contextual inference.

Reading the attributes

The examples in this section assume the HTML document IRI is https://example.com/page and use the Turtle prefixes ex:, rdf:, schema:, and xsd: with their conventional meanings.

An element bearing rdf-predicate is a statement carrier. By default, it also represents the statement’s subject. Its attributes and native HTML identity answer four independent questions:

  1. What RDF term is the statement about? This is the subject.
  2. What relationship or property is being stated? This is the predicate.
  3. What is the value or other RDF term at the end of that relationship? This is the object.
  4. In which graph is the statement asserted? This is the optional graph name.

For example, this identified heading describes itself:

<h1
  id="alice"
  rdf-predicate="https://schema.org/name"
>Alice</h1>
<https://example.com/page#alice> schema:name "Alice" .

The h1 is both the statement carrier and the subject-bearing HTML element. Its id gives it the fragment IRI https://example.com/page#alice; rdf-predicate supplies schema:name; and its text supplies the literal object "Alice".

If a statement carrier has no explicit subject attribute and no non-empty id, it still describes itself, but its RDF subject is a fresh blank node associated with that element for this extraction:

<span rdf-predicate="https://schema.org/name">Alice</span>
_:generated schema:name "Alice" .

The Turtle label is illustrative and need not be stable between extractions.

Another element can describe the identified element by referring explicitly to its fragment IRI. The identified element need not carry a statement itself:

<article id="alice">
  <h1
    rdf-subject="#alice"
    rdf-predicate="https://schema.org/name"
  >Alice</h1>

  <a
    href="https://example.com/bob"
    rdf-subject="#alice"
    rdf-predicate="https://schema.org/knows"
  >Bob</a>
</article>
<https://example.com/page#alice> schema:name "Alice" ;
                                     schema:knows ex:bob .

The h1 and a do not inherit the article’s subject. Each contains the explicit IRI reference #alice, which happens to identify the parent element. Moving either statement elsewhere in the document does not change its subject. The article’s id makes it referable; it does not assert a triple because the article has no rdf-predicate.

The Turtle semicolon is only serialization shorthand. The RDF graph contains two complete triples, just as the HTML contains two complete statement elements.

HTML authors choose a carrier according to the page’s ordinary information architecture. RDF extraction does not prefer visibly semantic markup over an exact-value or metadata carrier. Given an event represented by <article id="launch">, each of the following alternatives expresses the same typed literal:

<!-- Visible, semantically appropriate HTML -->
<time
  datetime="2026-09-01"
  rdf-subject="#launch"
  rdf-predicate="https://schema.org/startDate"
  rdf-datatype="http://www.w3.org/2001/XMLSchema#date"
>September 1, 2026</time>
<!-- A visible label with a separately preserved machine value -->
<data
  value="2026-09-01"
  rdf-subject="#launch"
  rdf-predicate="https://schema.org/startDate"
  rdf-datatype="http://www.w3.org/2001/XMLSchema#date"
>Launch date</data>
<!-- Metadata-only carriage, for example in head -->
<meta
  name="date"
  content="2026-09-01"
  rdf-subject="#launch"
  rdf-predicate="https://schema.org/startDate"
  rdf-datatype="http://www.w3.org/2001/XMLSchema#date"
>

All three extract as:

<https://example.com/page#launch>
  schema:startDate "2026-09-01"^^xsd:date .

The first form contributes native time semantics and human-readable presentation. The second preserves a lexical value while allowing different visible text. The third carries information without visible presentation. This interchangeability is intentional: authors should use the HTML element that best fits the document while the RDF attributes preserve one extraction model.

The examples below explain each attribute individually. Their Turtle prefixes are:

PREFIX ex: <https://example.com/>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX schema: <https://schema.org/>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>

rdf-version

<html rdf-version="1.2">

This attribute announces the binding and RDF version used by the document. It belongs only on the document’s html element, configures extraction, and does not emit a triple. Its Turtle 1.2 serialization counterpart is the version directive:

VERSION "1.2"

For a document extraction, rdf-version="1.2" selects this Core 0.1 processing model. If rdf-version is absent, the extractor MUST process the document as version 1.2 and report a missing-version diagnostic. If the value is present but unsupported, the extractor MUST report an unsupported-version diagnostic and MUST NOT extract a dataset under guessed semantics.

For a DocumentFragment extraction, the caller MAY supply the binding version explicitly. Otherwise, the extractor uses a supported rdf-version on the fragment’s owner document. If neither exists, it applies the same version-1.2 default and diagnostic. An rdf-version attribute anywhere other than the document’s html element has no processing effect and produces a diagnostic.

HTML parsing resolves duplicate source attributes before RDF extraction; the extractor uses the single rdf-version value present in the resulting DOM. Duplicate-attribute parse errors are therefore an HTML conformance matter rather than RDF version negotiation.

rdf-subject

rdf-subject explicitly overrides the subject derived from the statement element. It is useful when the statement describes another element, the document itself, or any resource whose IRI is not the carrier’s own identity. Fragment-only values such as #alice refer within the source document; other relative values resolve against the document base IRI.

<data
  value="Alice"
  rdf-subject="https://example.com/alice"
  rdf-predicate="https://schema.org/name"
></data>
ex:alice schema:name "Alice" .

Here the explicit attribute makes the subject https://example.com/alice, regardless of whether the data element has an id. The literal object is obtained from value.

An empty value is meaningful rather than missing:

<data
  value="IA² HTML/RDF"
  rdf-subject=""
  rdf-predicate="https://schema.org/name"
></data>
<https://example.com/page> schema:name "IA² HTML/RDF" .

Because "" is the empty relative IRI reference, it resolves to the document base IRI—which is the document’s own IRI in this example.

rdf-subject-key

Some RDF subjects have identity within the dataset but no IRI. rdf-subject-key overrides the element’s self-subject with the blank node selected by an extraction-local correlation key. Repeating that key in any key-bearing RDF position refers to the same blank node during this extraction.

<cite
  rdf-subject-key="work"
  rdf-predicate="https://schema.org/name"
>The Dispossessed</cite>
_:work schema:name "The Dispossessed" .

Here cite retains its normal HTML meaning and visible presentation while its text also supplies the RDF literal. The source key work is not an RDF term. The Turtle blank-node label is illustrative, and a serializer may replace it while preserving blank-node identity.

rdf-subject and rdf-subject-key are mutually exclusive overrides. Use rdf-subject for an explicit IRI subject and rdf-subject-key for a reusable extraction-local subject. If neither is present, the statement element itself supplies the subject: a non-empty id produces a fragment IRI, and an element without one produces a fresh blank node.

rdf-predicate

rdf-predicate marks the element as a statement carrier and supplies the relationship between its subject and object. A predicate is always an IRI. Merely placing an annotated element inside another annotated element does not create a relationship.

<a
  href="/license"
  rdf-subject=""
  rdf-predicate="http://purl.org/dc/terms/license"
>License</a>
<https://example.com/page>
  <http://purl.org/dc/terms/license>
  <https://example.com/license> .

In this example, rdf-subject="" denotes the document, rdf-predicate denotes the license relationship, and href denotes the license resource used as the object.

rdf-object-key

rdf-object-key makes the object the blank node selected by an extraction-local key. A matching rdf-subject-key can then use that same resource as another statement’s subject.

<address
  rdf-object-key="address"
  rdf-subject="https://example.com/alice"
  rdf-predicate="https://schema.org/address"
>
  <span
    rdf-subject-key="address"
    rdf-predicate="https://schema.org/addressLocality"
  >Vancouver</span>
</address>
ex:alice schema:address _:address .
_:address schema:addressLocality "Vancouver" .

The outer address element carries the statement connecting Alice to an unnamed address. The inner span carries a second statement about that same blank node. The shared local key—not the HTML nesting—joins the statements; the address element simultaneously retains its native human-facing meaning.

rdf-datatype

rdf-datatype gives the datatype IRI for a literal object. It is the HTML binding of the information written after ^^ in Turtle; the literal’s lexical form still comes from element text, data[value], time[datetime], or meta[content].

<time
  datetime="2026-09-01"
  rdf-subject="https://example.com/conference"
  rdf-predicate="https://schema.org/startDate"
  rdf-datatype="http://www.w3.org/2001/XMLSchema#date"
>September 1, 2026</time>
ex:conference schema:startDate "2026-09-01"^^xsd:date .

The lexical form comes from native datetime, while the human-readable text remains free to follow the page’s presentation style. rdf-datatype cannot be combined with a language tag because an RDF literal is either datatype-qualified or language-tagged. Native lang and dir are explained in §5.5.

rdf-graph

On a statement element, rdf-graph places that triple in the named graph identified by an IRI. On a non-statement element, it declares the IRI-named graph without adding a triple, as defined in §5.6. It does not establish a scope for descendants or siblings; every statement assigned to that graph repeats the attribute.

<a
  href="https://example.com/bob"
  rdf-subject="https://example.com/alice"
  rdf-predicate="https://schema.org/knows"
  rdf-graph="https://example.com/graphs/public"
>Bob</a>

Turtle serializes one RDF graph and therefore cannot carry its graph name. The RDF dataset equivalent uses TriG, the Turtle-family dataset syntax:

<https://example.com/graphs/public> {
  ex:alice schema:knows ex:bob .
}

rdf-graph-key

rdf-graph-key is the local-identity counterpart to rdf-graph. On a statement element, it places that triple in the blank-node-named graph selected by an extraction-local key. On a non-statement element, it declares that graph without adding a triple, as defined in §5.6.

<img
  src="https://example.com/photos/alice.jpg"
  alt="Alice at the conference"
  rdf-subject="https://example.com/alice"
  rdf-predicate="https://schema.org/image"
  rdf-graph-key="observations"
>

Again, the dataset equivalent requires TriG:

_:observations {
  ex:alice schema:image <https://example.com/photos/alice.jpg> .
}

The image remains ordinary accessible page content. Its native src supplies the IRI object; alt remains presentation and accessibility text rather than a second RDF value.

Triple-term object template

A direct child template used as a statement’s object carrier has one internal statement that constructs an RDF 1.2 triple term. No RDF-specific attribute is needed on the template: its object-carrier position supplies the meaning. The inner triple is used as the outer statement’s object but is not thereby asserted as a graph statement.

<aside
  rdf-subject-key="claim"
  rdf-predicate="http://www.w3.org/1999/02/22-rdf-syntax-ns#reifies"
>
  <p>This claim is recorded for provenance review.</p>
  <template>
    <a
      href="https://example.com/bob"
      rdf-subject="https://example.com/alice"
      rdf-predicate="https://schema.org/knows"
    >Bob</a>
  </template>
</aside>
_:claim rdf:reifies <<( ex:alice schema:knows ex:bob )>> .

The aside can present human-facing context while its direct inert template supplies the RDF object. The triple inside <<( ... )>> is a triple term. It is not asserted by this Turtle statement, matching the inert template’s behavior. A template that is not selected as a statement’s object carrier has no special RDF meaning in the containing extraction.

Statement construction

Discovering asserted statements

An extraction root is either an HTML Document or a DocumentFragment. A processor begins with statement elements in that root’s tree. For a document extraction, the candidate set is equivalent to:

document.querySelectorAll("[rdf-predicate]")

An ordinary query on a Document or DocumentFragment does not traverse the contents of a descendant HTML template. Therefore, statements inside template.content are not asserted merely because their markup contains rdf-predicate.

The content of any template MAY be supplied explicitly as a separate extraction root. Its statements then form a separate extraction result; they do not become assertions in the dataset extracted from the tree containing the template element. A fragment extraction uses the source document IRI and document base IRI supplied by the caller, normally those of the template’s owner document.

For example, this ordinary template contains two independently extractable statements but contributes neither to the containing document’s dataset:

<template id="candidate-profile">
  <span
    rdf-subject="/people/alice"
    rdf-predicate="https://schema.org/name"
  >Alice</span>

  <a
    href="/people/bob"
    rdf-subject="/people/alice"
    rdf-predicate="https://schema.org/knows"
  >Bob</a>
</template>

If candidate-profile.content is explicitly supplied as an extraction root, its result contains:

</people/alice> schema:name "Alice" ;
  schema:knows </people/bob> .

Canonical document IRI

An extractor distinguishes the retrieval document IRI, from which the HTML representation was obtained, from the source document IRI used as the semantic identity of that document. They are the same unless the document declares one usable HTML canonical link.

To establish the source document IRI, a processor MUST apply these rules before extracting statements:

  1. Let the retrieval document IRI be the absolute IRI supplied by the acquisition environment.
  2. Within the document head, collect link elements whose rel token set contains canonical, compared ASCII case-insensitively, and which have an href attribute.
  3. If there is exactly one candidate, resolve its href using HTML URL processing against the HTML document base URL. If the result is an absolute, fragmentless IRI, use it as the source document IRI.
  4. If there is no candidate, use the retrieval document IRI as the source document IRI. If there is more than one candidate, or the sole candidate is invalid or contains a fragment, report a diagnostic and use the retrieval document IRI.

This use follows HTML’s canonical link type and the Canonical Link Relation. A processor MUST NOT dereference the canonical IRI merely to extract RDF. The link establishes extraction context but does not, by itself, emit an RDF statement.

If the document contains an explicit HTML base[href], the HTML document base URL is the RDF document base IRI. Otherwise, the source document IRI is also the RDF document base IRI. Consequently, a document retrieved from http://127.0.0.1:8765/specs/html-rdf/ that declares <link rel="canonical" href="https://ia2.dev/spec/html-rdf"> describes https://ia2.dev/spec/html-rdf; an element with id="subject" describes https://ia2.dev/spec/html-rdf#subject. The retrieval IRI remains available for provenance and diagnostics.

IRI-reference processing

Unless a more specific rule states otherwise, every IRI-valued rdf-* attribute and native IRI object carrier is processed as follows:

  1. Read the parsed DOM content-attribute value exactly. Do not use a reflected IDL property such as element.href or element.src.
  2. Require the value to conform to the RFC 3987 IRI-reference production.
  3. Resolve the reference against the document base IRI according to RFC 3986 section 5.
  4. Require the result to be an absolute RDF IRI.
  5. Perform no additional case folding, percent-encoding normalization, default-port removal, host rewriting, Unicode normalization, or other URL canonicalization.

Failure at any step makes the affected statement or graph declaration invalid. IRI equality is simple string equality of the resulting Unicode code-point sequences, as required by RDF 1.2.

The RDF document base IRI is established by the canonical document IRI rules and then used as the base for RDF reference resolution. An explicit HTML base[href] retains HTML’s document-base-URL behavior; without one, the semantic source document IRI is the RDF base. This deliberately separates retrieval location, semantic document identity, HTML base discovery, and RDF IRI construction. Native IRI carriers remain useful HTML carriers, but their RDF values come from their content attributes rather than the browser’s possibly canonicalized URL properties. Authors who require the HTML URL and RDF IRI to be character-for-character identical SHOULD use a reference whose HTML URL resolution and RDF IRI resolution agree.

Subject

A statement’s subject is constructed locally from its statement element in this order:

  1. If rdf-subject is present, its value is resolved to an IRI and used as the subject.
  2. Otherwise, if rdf-subject-key is present, its value selects the blank-node subject by extraction-local key.
  3. Otherwise, if the element has a non-empty HTML id, the source document IRI, with any existing fragment removed and the element’s encoded fragment identifier appended, gives the subject.
  4. Otherwise, the subject is a fresh blank node uniquely associated with that element for the duration of the extraction.

rdf-subject and rdf-subject-key MUST NOT occur together. They override the element’s default self-subject; neither is required.

The empty string is a valid empty relative IRI reference. rdf-subject="" therefore resolves to the document base IRI using the IRI-reference-processing algorithm. It is an explicit base-resource subject, not missing or inherited semantic state. In the absence of an explicit HTML base, this is the canonical source document IRI when one was declared. Authors MAY use an explicit document IRI when they specifically mean the source document and an HTML base could differ from it.

For subject construction, a fragment-only rdf-subject value such as #alice is a local element reference and MUST resolve against the source document IRI, not against an IRI supplied by HTML base. An id-derived self-subject and an explicit reference to that encoded fragment therefore denote the same RDF term even when the document changes the base used by ordinary relative URLs. Other relative rdf-subject values use the document base IRI.

To construct an IRI fragment from id, remove any existing fragment from the source document IRI and append # followed by the encoded identifier. For each Unicode scalar value in the identifier, preserve it when RFC 3987 permits it directly in ifragment and it is not %; otherwise encode its UTF-8 bytes as uppercase percent-encoded octets. Encoding % unconditionally makes the mapping from arbitrary HTML identifiers injective. A value that is not a Unicode scalar-value string cannot supply an id-derived subject. Processors MUST compare the resulting RDF terms, not their source spellings.

An element with id but no rdf-predicate does not assert a statement. Its fragment IRI can nevertheless be named explicitly by statement elements, including descendants:

<article id="alice">
  <h1
    rdf-subject="#alice"
    rdf-predicate="https://schema.org/name"
  >Alice</h1>
</article>

This is an explicit IRI reference, not subject inheritance. Extraction of the h1 does not require inspecting its parent, and moving it elsewhere in the same document does not change its subject.

An automatically allocated blank-node self-subject has no author-controlled key and cannot be named by another statement. Authors needing several statements to share an anonymous subject MUST use the same extraction-local key with rdf-subject-key and, where that resource is an object, rdf-object-key.

Local keys are scoped to one extraction operation, including any term fragments parsed as part of it. The same key in rdf-subject-key, rdf-object-key, or rdf-graph-key selects the same blank node within the extracted dataset, including across RDF positions. Separately extracting a template’s content starts a separate key scope. Keys are authoring-time correlation handles: they are not RDF terms, are not persistent identifiers, and are not matched across extraction operations. A serializer chooses its own blank-node labels independently of the source keys.

A local key MUST be non-empty and MUST NOT contain ASCII whitespace. Keys are compared case-sensitively using their parsed DOM attribute values. They are not resolved as IRIs and processors MUST NOT dereference them.

RDF 1.2 triple terms cannot occupy the subject position, so this binding defines no triple-term subject form.

Predicate

The value of rdf-predicate MUST be a valid IRI reference. It is resolved against the document base IRI.

The Core model defines no special treatment for rdf:type or any other predicate.

Object

The statement’s object is determined from the statement element itself. Exactly one of the following object-carrier forms MUST apply.

Triple-term object

If the statement element has one direct child template and no competing object carrier, that template is the statement’s object carrier. The object is the RDF 1.2 triple term constructed from the template.

The statement element MUST NOT contain more than one direct child template and MUST NOT also carry rdf-object-key, a native IRI carrier, or a native literal-value carrier. The object-position template MUST NOT itself carry a Core-defined rdf-* attribute. Other child content MAY provide human-facing context and does not compete with the template object.

Local-key object

If the statement element has rdf-object-key, its object is the blank node selected by that extraction-local key.

The element MUST NOT also provide any other object carrier.

IRI object

The following native element-and-attribute pairs are the Core 0.1 single-IRI object carriers:

Attribute HTML elements
href a, area, link
src audio, embed, iframe, img, input, script, source, track, video
cite blockquote, del, ins, q
action form
formaction button, input
data object
poster video

If exactly one supported pair is present on the statement element, its object is the IRI obtained by applying §5.1.1 to that content-attribute value. More than one supported native IRI carrier makes the statement invalid.

The allowlist is fixed for Core 0.1. URL lists such as srcset and ping, embedded HTML such as srcdoc, fragment-oriented attributes such as usemap, and the document-configuration attribute base[href] are not single-IRI carriers. An attribute name used on an element not listed for it does not become an RDF object carrier merely because a browser preserves it in the DOM. If an otherwise useful HTML element has multiple supported carriers, the author MUST use a separate statement element to avoid ambiguity.

This lets ordinary links and media carry their own semantic identity:

<a
  href="/people/bob"
  rdf-subject="/people/alice"
  rdf-predicate="https://schema.org/knows"
>Bob</a>

The link text is presentation. The RDF object is the resolved href IRI.

Authors needing a non-visible IRI statement may use an ordinary hidden anchor rather than an RDF-specific element:

<a
  hidden
  href="https://schema.org/Person"
  rdf-subject="/people/alice"
  rdf-predicate="http://www.w3.org/1999/02/22-rdf-syntax-ns#type"
></a>

Literal object

If none of the preceding forms applies, the object is a literal. Its lexical form is obtained as follows:

  1. For meta[content], use the content attribute exactly.
  2. For data[value], use the value attribute exactly.
  3. For time[datetime], use the datetime attribute exactly.
  4. Otherwise:
    1. concatenate the element’s descendant text nodes in document order, excluding all template contents;
    2. replace each maximal sequence of ASCII whitespace—U+0009, U+000A, U+000C, U+000D, or U+0020—with one U+0020 SPACE; and
    3. remove a leading or trailing U+0020 SPACE.

A statement using the text-content form MUST NOT contain a descendant statement element outside a template. This prevents nested semantic markup from silently changing the literal.

This fallback normalization is based only on DOM text and ASCII whitespace. It does not use CSS, layout, innerText, accessibility-name computation, Unicode normalization, or implied separators at element boundaries. Non-ASCII whitespace, including U+00A0 NO-BREAK SPACE, is preserved. Authors MUST include desired separation in the source text; <span>A</span><span>B</span> produces AB.

These carriers are interchangeable at the RDF layer when they produce the same lexical form and literal metadata. Authors can therefore use time[datetime] for a date presented in prose, data[value] when the displayed label differs from the exact or whitespace-sensitive value, meta[content] for metadata-only carriage, and ordinary semantic elements when normalized text is the desired lexical form. In particular, authors of whitespace-sensitive pre or code content SHOULD use data[value] or meta[content] rather than the fallback.

For example:

<p
  rdf-subject="/people/alice"
  rdf-predicate="https://schema.org/description"
>
  Alice <em>builds</em>
  knowledge graphs.
</p>

produces the lexical form Alice builds knowledge graphs. independently of indentation.

Authors SHOULD use data[value] when exact lexical preservation matters:

<data
  value="01"
  rdf-subject="/inventory/widget"
  rdf-predicate="https://example.com/count"
  rdf-datatype="http://www.w3.org/2001/XMLSchema#integer"
>1 item</data>

The lexical form is 01, even though the visible text is 1 item.

Literal datatype, language, and direction

Literal metadata is determined by the following ordered algorithm:

  1. If rdf-datatype is present:
    1. resolve its value to the datatype IRI;
    2. the datatype IRI MUST NOT be http://www.w3.org/1999/02/22-rdf-syntax-ns#langString or http://www.w3.org/1999/02/22-rdf-syntax-ns#dirLangString;
    3. a non-empty directly present lang or a directly present dir whose value matches ltr or rtl ASCII case-insensitively MUST NOT also be present; and
    4. construct a typed literal with no language tag and no base direction.
  2. Otherwise, inspect only lang and dir directly present on the statement element:
    1. an absent or empty lang supplies no language tag;
    2. a non-empty lang MUST be a well-formed BCP 47 language tag;
    3. dir values are matched ASCII case-insensitively: ltr and rtl supply the corresponding lowercase RDF base direction, while an absent dir or dir="auto" supplies no RDF base direction;
    4. any other directly present dir value makes the statement invalid;
    5. a base direction without a non-empty language tag makes the statement invalid;
    6. a language tag plus a base direction constructs an RDF 1.2 directional language-tagged string with datatype http://www.w3.org/1999/02/22-rdf-syntax-ns#dirLangString;
    7. a language tag without a base direction constructs a language-tagged string with datatype http://www.w3.org/1999/02/22-rdf-syntax-ns#langString; and
    8. if neither is present, construct a literal with datatype http://www.w3.org/2001/XMLSchema#string.

Language tags are compared ASCII case-insensitively as required by RDF 1.2. An extractor MAY preserve their source case or normalize them according to BCP 47; either representation denotes the same RDF 1.2 term.

HTML language or direction inherited from ancestors affects presentation but not RDF extraction. dir="auto" remains available for HTML presentation but has no RDF base-direction equivalent.

rdf-datatype on an IRI, blank-node, or triple-term object is an authoring error.

<cite
  lang="ar"
  dir="rtl"
  rdf-subject="/books/1"
  rdf-predicate="https://schema.org/name"
>تصميم مواقع الويب</cite>
</books/1> schema:name "تصميم مواقع الويب"@ar--rtl .

The cite element communicates that the visible phrase is a work title; direct lang and dir simultaneously determine the RDF 1.2 directional language-tagged literal.

Graph names and declarations

If neither graph attribute is present, the triple belongs to the default graph.

Otherwise, a statement element MUST have exactly one of:

Graph membership is stated on every statement. It is never inherited from a container.

<a
  href="/people/bob"
  rdf-subject="/people/alice"
  rdf-predicate="https://schema.org/knows"
  rdf-graph="/graphs/public-profile"
>Bob</a>

An element without rdf-predicate that carries exactly one of rdf-graph or rdf-graph-key, and is not an object-position template, is a graph declaration element. It adds the named graph to the extracted dataset without adding a triple. This represents empty named graphs and may also redundantly declare a graph populated by statements elsewhere in the extraction root.

<template rdf-graph="/graphs/reserved"></template>
<template rdf-graph-key="private-observations"></template>

The result contains an empty IRI-named graph and an empty blank-node-named graph. The choice of template has no RDF significance; any non-statement HTML element may serve as the carrier. A declaration does not scope its descendants, and statements placed inside a declared template remain outside the containing extraction unless its content is separately supplied as an extraction root.

The corresponding TriG dataset structure is:

<https://example.com/graphs/reserved> {}
_:private-observations {}

A graph declaration element MUST NOT carry both graph attributes or any other Core-defined rdf-* attribute. Unknown attributes remain subject to the general unknown-attribute rule. Repeated declarations of the same graph are idempotent. A graph declaration with an invalid graph IRI reference or local key is invalid and does not add a named graph.

RDF 1.2 triple terms

Inert term fragments

A direct child template selected as a statement’s object carrier is a term fragment. Its content MUST contain exactly one element child, that element MUST be a statement element, and it MUST contain no other non-whitespace text nodes. Comments are ignored. A query equivalent to template.content.querySelectorAll("[rdf-predicate]") MUST return exactly that one statement element. Additional statement descendants are therefore forbidden except inside nested template contents, which occupy separate document fragments. A term fragment MUST NOT contain a graph declaration element.

That statement is parsed by the same subject, predicate, and object rules as an asserted statement, with these differences:

  1. It constructs an RDF triple term.
  2. It does not add that triple to any graph.
  3. It MUST NOT have a graph attribute.

The triple term may itself contain an object-position template as a nested term fragment. This permits the recursive triple terms defined by RDF 1.2.

Term fragments are inline. Core 0.1 defines no ID reference or reusable term registry. Repetition is the canonical serialization because references would require DOM lookup, cycle detection, blank-node scope rules, and a distinction between active asserted targets and inert targets. Processors MUST NOT interpret an id, fragment reference, or other HTML relationship as a reusable triple-term reference. Authoring tools MAY deduplicate terms internally but MUST serialize each triple-term occurrence inline.

An ordinary template that is not in object-carrier position is not a term fragment. Its content may contain zero or more statement elements and MAY be supplied explicitly as a separate extraction root. This is ordinary fragment extraction, not an RDF graph term, quotation mechanism, or assertion in the containing dataset.

Reification without accidental assertion

<div
  rdf-subject-key="claim-1"
  rdf-predicate="http://www.w3.org/1999/02/22-rdf-syntax-ns#reifies"
>
  <template>
    <a
      href="/people/bob"
      rdf-subject="/people/alice"
      rdf-predicate="https://schema.org/knows"
    >Bob</a>
  </template>
</div>

<a
  href="/sources/interview-7"
  rdf-subject-key="claim-1"
  rdf-predicate="http://www.w3.org/ns/prov#wasDerivedFrom"
>Interview 7</a>

The extracted default graph contains two asserted triples:

_:claim-1 rdf:reifies <<( </people/alice> schema:knows </people/bob> )>> .
_:claim-1 prov:wasDerivedFrom </sources/interview-7> .

It does not contain:

</people/alice> schema:knows </people/bob> .

The proposition becomes asserted only if an equivalent statement element also exists in the extraction root’s tree.

DOM separation

The asserted and non-asserted layers remain mechanically distinct:

// Asserted statements in the document dataset
const asserted = document.querySelectorAll("[rdf-predicate]");

// Direct object templates of asserted statements
const terms = [...asserted]
  .map(statement => statement.querySelector(":scope > template"))
  .filter(Boolean);

// A term's internal statement is queried explicitly
const inner = terms[0].content.querySelector("[rdf-predicate]");

A document-wide selector does not accidentally return inner.

RDF expressivity

The Core model and its provisional HTML binding are structurally complete for RDF 1.2 datasets whose strings and IRIs are representable in the parsed HTML DOM:

RDF construct Provisional HTML binding
Element-fragment IRI subject Native id on a statement element
Other IRI subject rdf-subject
Element-local blank-node subject Statement element without id or a subject override
Reusable blank-node subject rdf-subject-key
IRI predicate rdf-predicate
IRI object A native single-IRI carrier from §5.4.3
Blank-node object rdf-object-key
Literal object Native HTML value or text
Typed literal rdf-datatype
Language-tagged literal Direct lang
RDF 1.2 directional literal Direct lang plus dir
RDF 1.2 triple-term object Direct child template in object-carrier position
Default graph No graph attribute
IRI-named graph rdf-graph
Blank-node-named graph rdf-graph-key
Empty IRI-named graph rdf-graph on an element without rdf-predicate
Empty blank-node-named graph rdf-graph-key on an element without rdf-predicate
RDF collection Ordinary rdf:first, rdf:rest, and rdf:nil triples
Reifier Ordinary subject of an rdf:reifies statement

No dedicated syntax is needed for RDF containers, collections, reification metadata, classes, properties, ontologies, or entailment vocabularies. They are RDF triples.

This completeness claim concerns the RDF abstract model, not arbitrary source-byte round trips. HTML parsing may replace or discard source characters that RDF strings can otherwise contain. Such HTML parser limitations do not remove an RDF term kind or dataset structure from the model, but they can prevent a particular lexical value from being carried by static HTML source.

SHACL and SHACL-AF

Shapes are RDF

SHACL data graphs and shapes graphs use the same statement syntax. The extractor does not interpret sh:NodeShape, sh:path, sh:rule, or any other vocabulary term specially.

A consumer chooses which extracted graph is the data graph and which is the shapes graph. Authors SHOULD place shapes in an explicitly named graph when an HTML document carries both.

Core 0.1 defines no non-RDF graph-role attribute. A consumer may select a graph by its name through application configuration, or the graph-name resource may be described with ordinary RDF statements. For example, an application vocabulary can classify the shapes graph in the default graph:

<a
  hidden
  href="https://example.com/vocab/ShapesGraph"
  rdf-subject="/graphs/shapes"
  rdf-predicate="http://www.w3.org/1999/02/22-rdf-syntax-ns#type"
></a>

The extractor remains vocabulary-neutral: it emits the classification triple but does not assign operational meaning to ex:ShapesGraph.

Example shape graph

The following hidden HTML asserts a minimal SHACL shape into /graphs/shapes:

<section hidden>
  <a
    href="http://www.w3.org/ns/shacl#NodeShape"
    rdf-subject="#PersonShape"
    rdf-predicate="http://www.w3.org/1999/02/22-rdf-syntax-ns#type"
    rdf-graph="/graphs/shapes"
  ></a>

  <a
    href="https://schema.org/Person"
    rdf-subject="#PersonShape"
    rdf-predicate="http://www.w3.org/ns/shacl#targetClass"
    rdf-graph="/graphs/shapes"
  ></a>

  <span
    rdf-object-key="name-property"
    rdf-subject="#PersonShape"
    rdf-predicate="http://www.w3.org/ns/shacl#property"
    rdf-graph="/graphs/shapes"
  ></span>

  <a
    href="https://schema.org/name"
    rdf-subject-key="name-property"
    rdf-predicate="http://www.w3.org/ns/shacl#path"
    rdf-graph="/graphs/shapes"
  ></a>

  <data
    value="1"
    rdf-subject-key="name-property"
    rdf-predicate="http://www.w3.org/ns/shacl#minCount"
    rdf-datatype="http://www.w3.org/2001/XMLSchema#integer"
    rdf-graph="/graphs/shapes"
  ></data>
</section>

The use of hidden affects HTML presentation only. These are active document elements, so their triples are asserted and discoverable by the ordinary asserted-statement query.

Advanced Features and Rules

SHACL Advanced Features—including custom targets, annotation properties, functions, node expressions, and rules—are RDF graph structures and can be represented without extending the Core model or its HTML binding.

RDF lists used by function calls and node expressions are expressed as explicit rdf:first and rdf:rest statements. SPARQL bodies are literal objects. SHACL 1.2 Rules are likewise ordinary RDF statements.

Extraction MUST NOT execute any of them.

A separate SHACL processor MAY consume the extracted shapes graph. Such a processor MUST apply its own trust, capability, resource, and execution policy. The presence of a rule or function declaration in HTML is never consent to run it.

Extraction algorithm

A conforming extractor performs these steps:

  1. Accept an HTML Document or DocumentFragment as the extraction root. Core does not prescribe how the root was acquired. It may be an inert document parsed from downloaded source, a live application DOM after scripts have changed it, a template content fragment, a shadow root, or another fragment supplied by the caller.
  2. Establish the retrieval document IRI, source document IRI, and RDF document base IRI according to the canonical document IRI rules. For a fragment root, use the values supplied by the caller, normally those established for its owner document.
  3. Determine the binding version according to the rdf-version rules. Stop with diagnostics and no extracted dataset if the declared version is unsupported.
  4. Select statement elements and graph declaration elements among the extraction root’s light-tree descendants. Statement candidates are equivalent to root.querySelectorAll("[rdf-predicate]"). Graph declaration candidates are equivalent to root.querySelectorAll("[rdf-graph]:not([rdf-predicate]), [rdf-graph-key]:not([rdf-predicate])") after excluding object-position templates. Do not traverse into descendant template contents, shadow roots, or the child documents of iframe, object, or similar embedding elements. A template content fragment, shadow root, or embedded document MAY be supplied explicitly as a separate extraction root.
  5. For each statement element:
    1. construct its subject;
    2. resolve its predicate;
    3. construct its object;
    4. determine its graph;
    5. if every preceding step succeeds, add the resulting triple to that graph.
  6. Parse a template as a term fragment only when it is the direct object carrier of a statement or nested triple term.
  7. For each valid graph declaration element, ensure that its named graph exists in the dataset, even if it contains no triples.
  8. Return the resulting RDF 1.2 dataset and any authoring diagnostics.

Acquisition determines the DOM state presented to extraction. A source-oriented agent can parse downloaded HTML with the scripting flag disabled and without a custom-element registry to obtain an inert document; in that case, markup inside noscript participates in the parsed light tree. An in-application extractor can instead receive the current live DOM, including information produced by earlier application mutations. In either case, document-root queries do not cross template, shadow, or embedded-document boundaries; any such fragment may be supplied explicitly as its own extraction root.

Extraction operates on a snapshot of the supplied root’s relevant tree, attributes, and text at invocation. Mutations after extraction begins do not alter that result. A later extraction over a modified DOM is a new extraction operation and may intentionally produce a different dataset and fresh blank nodes. A live integration MAY observe DOM mutations and schedule repeated extraction; Core defines each result, not the observation or scheduling policy.

Processors MUST NOT:

Unknown rdf-* attributes MUST be ignored with a diagnostic. They MUST NOT alter extraction state.

Invalid statements and recovery

An invalid statement emits no triple. A processor MUST report a diagnostic and MUST continue with other independent statement elements.

If a term fragment is invalid, construction of that triple term fails and the immediately containing statement is invalid. This rule applies recursively to nested term fragments. No triple represented by an invalid term fragment is asserted merely as a recovery action.

Competing object carriers, an invalid or unresolved IRI reference, invalid literal metadata, a forbidden graph attribute on a term-fragment statement, or failure to construct any required RDF term makes the affected statement invalid. Processors MUST NOT select one competing carrier by precedence, repair a malformed value, or infer replacement state from surrounding markup.

Statements are independent for recovery unless one contains the other through an object-position term fragment. An invalid ordinary statement does not invalidate another statement merely because they use the same IRI or local key.

An invalid graph declaration adds no named graph and does not invalidate statements that independently use the same graph name.

Authoring conformance

A conforming document:

  1. announces rdf-version="1.2" on its html element;
  2. gives every statement a locally constructible subject, either from the element itself or from exactly one explicit subject override;
  3. gives every statement one valid predicate IRI reference;
  4. gives every statement exactly one object carrier;
  5. gives every statement at most one graph-name form and every graph declaration exactly one graph-name form;
  6. does not depend on inherited RDF state;
  7. gives every term fragment exactly one top-level statement;
  8. does not place graph attributes on a term-fragment statement;
  9. uses directly present lang and dir for RDF literal metadata;
  10. does not combine datatype and language metadata;
  11. uses non-empty, whitespace-free values for all local keys;
  12. does not rely on script execution for extraction; and
  13. uses graph attributes on non-statement elements only for graph declarations.

An extractor SHOULD report all violations it can identify and continue extracting independent conforming statements. It MUST NOT guess missing predicates, objects, or graph names, or search surrounding elements for semantic state.

Security and trust

RDF extracted from HTML is untrusted input unless the consumer has established otherwise.

This specification separates four operations that must not be conflated:

  1. Acquiring a DOM obtains either parsed source or a selected live application state.
  2. Extracting RDF constructs a dataset from a snapshot of that supplied state.
  3. Validating RDF evaluates a data graph against a shapes graph.
  4. Executing rules or actions may compute statements or cause effects.

Success at an earlier stage does not authorize a later stage.

An inert-source extraction and a live-runtime extraction can legitimately differ. Consumers comparing, caching, signing, or acting on results SHOULD record which acquisition mode was used and, for a live DOM, the application state or observation time needed to interpret the dataset. The fact that an application previously executed code to produce a DOM does not mean that the extractor executed that code or that extracted rules are authorized to run.

Consumers SHOULD preserve:

Semantic and source signatures

Core extraction defines the semantic input to a signing layer but does not define canonicalization, hashing, key discovery, or a signature envelope. A semantic-signature profile performs these operations in order:

  1. extract the Core dataset;
  2. reject unsupported constructs or transform them by a profile-defined, information-preserving procedure;
  3. canonicalize the resulting dataset with an explicitly identified algorithm;
  4. sign the canonical bytes; and
  5. bind the signature to the extraction version and every transformation and canonicalization identifier used.

Presentation-only HTML edits preserve a semantic signature when and only when they leave that profile’s canonical semantic input unchanged. A signature over the HTML representation itself is a separate source signature and MUST cover explicitly defined source bytes or a separately defined HTML canonical form.

RDFC-1.0 is based on an RDF 1.1-style set-of-quads model. It cannot by itself represent every Core 0.1 dataset, including datasets with RDF 1.2 triple terms or significant empty named graphs. A profile using RDFC-1.0 MUST therefore restrict such inputs or define and identify a compatible information-preserving transformation before canonicalization. Core extractors MUST NOT silently apply one.

Relationship to adjacent approaches

RDFa

RDFa integrates RDF with HTML but includes inherited evaluation context, incomplete triples, and chaining behavior. This Core model intentionally trades compactness for statement locality and mechanical extraction.

JSON-LD

JSON-LD represents RDF in a separate serialization, commonly inside a script element. This Core model keeps semantic statements correlated with DOM elements and does not require JSON parsing, context processing, or script-element discovery.

Microdata and microformats

Microdata and microformats provide useful HTML-integrated patterns but do not aim to expose the full RDF 1.2 data model, arbitrary named graphs, or triple terms.

MCP, A2A, and WebMCP

Those efforts address agent/service communication, agent interoperability, or callable webpage tools. This model addresses a lower layer: deterministic, non-executing extraction of document meaning. A tool protocol may consume this dataset, but is not required to extract it.

Minimal complete example

<!doctype html>
<html lang="en" rdf-version="1.2">
  <head>
    <meta charset="utf-8">
    <title>Alice</title>
    <meta
      name="description"
      content="Public profile for Alice"
      rdf-subject="#alice"
      rdf-predicate="https://schema.org/description"
    >
  </head>
  <body>
    <article id="alice">
      <h1
        rdf-subject="#alice"
        rdf-predicate="https://schema.org/name"
      >Alice</h1>

      <p>
        Alice knows
        <a
          href="/people/bob"
          rdf-subject="#alice"
          rdf-predicate="https://schema.org/knows"
        >Bob</a>.
      </p>

      <p>
        Alice was born on
        <time
          datetime="1990-03-12"
          rdf-subject="#alice"
          rdf-predicate="https://schema.org/birthDate"
          rdf-datatype="http://www.w3.org/2001/XMLSchema#date"
        >March 12, 1990</time>.
      </p>

      <data
        value="42"
        rdf-subject="#alice"
        rdf-predicate="https://example.com/reputation"
        rdf-datatype="http://www.w3.org/2001/XMLSchema#integer"
      >Reputation: 42</data>

      <div
        hidden
        rdf-subject-key="source-claim"
        rdf-predicate="http://www.w3.org/1999/02/22-rdf-syntax-ns#reifies"
      >
        <template>
          <a
            href="/people/bob"
            rdf-subject="#alice"
            rdf-predicate="https://schema.org/knows"
          >Bob</a>
        </template>
      </div>
    </article>
  </body>
</html>

Assuming the source document IRI is https://example.com/page, the asserted default graph is:

PREFIX ex: <https://example.com/>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX schema: <https://schema.org/>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>

<https://example.com/page#alice>
  schema:description "Public profile for Alice" ;
  schema:name "Alice" ;
  schema:knows <https://example.com/people/bob> ;
  schema:birthDate "1990-03-12"^^xsd:date ;
  ex:reputation "42"^^xsd:integer .

_:source-claim rdf:reifies <<(
  <https://example.com/page#alice>
  schema:knows
  <https://example.com/people/bob>
)>> .

The article’s native id gives Alice the fragment IRI #alice. Each statement refers to that IRI explicitly; none inherits it from the article. The head meta can refer to an element appearing later because resolving an IRI is not a pending triple or DOM lookup. It carries a non-visible description, the heading contributes visible text, the link contributes an IRI object, time separates a machine date from its presentation, and data preserves an exact numeric lexical form. All are ordinary statement elements under the same extraction rules.

An extractor can obtain the asserted statement elements with one document query. It traverses the object-position template only to construct the object of the rdf:reifies statement. The triple inside that template is mentioned and, independently, also asserted by the visible link earlier in the page.

Semantic publication profile

The specification uses its own attribute binding to describe more than its design decisions. Its publication graph identifies sections, section titles, lists, tables, examples, source-code samples, serialization results, bibliographic references, and the relationships among them.

Document structure uses the Document Components Ontology (DoCO), the Pattern Ontology, C4O, and Dublin Core Terms. Code and example relations use Schema.org. Citation intent uses CiTO, while DEO supplies rhetorical document roles. These annotations are informative: they demonstrate that the Core remains vocabulary-neutral and that an agent can recover a useful information architecture without a parallel metadata block.

Visible headings and reference links carry statements directly when their native text or IRI is the intended RDF object. Code samples and serialization results remain addressable HTML resources whose content is available from the DOM; the RDF graph classifies and relates them without duplicating their full source as literals. Hidden ordinary HTML carriers add metadata that has no appropriate visible rendering. Together these forms create a rich conformance specimen while retaining the one-element, one-statement rule.

References

Decision and provenance trace

This appendix is not a second normative source. It makes the commitments already expressed in the controlling sections machine-readable and links each one back to that text. The HTML document itself is the decision:DecisionRecord; the commitments it records remain distinct RDF resources.

Provenance

Editor and attributed agent
Yurii Rashkovskii

Deliberation frame

How can an HTML document carry an RDF 1.2 dataset that is easy to locate, extract, inspect, and correlate with page content?

The motivating resources pursued by this deliberation are the eight goals defined in Goals.

IA² Core 0.1 syntax and extraction deliberation

Prefer local, explicit HTML bindings that preserve RDF 1.2 expressivity and DOM-query fidelity, accepting some repetition in exchange for deterministic extraction, stable movement, and clear assertion boundaries.

Recorded commitments

Use HTML attributes, not an embedded serialization

Selected option: Attach RDF construction attributes directly to ordinary HTML elements.

This keeps semantic assertions correlated with their DOM carriers and avoids a parallel JSON-LD, Turtle, or RDF/XML document.

Use the concise rdf-* attribute family

Selected option: Spell the global attributes rdf-*, not data-rdf-*.

The names are a proposed language binding rather than private application data, and brevity matters when complete statements repeat attributes.

One carrier determines one complete statement

Selected option: Require each rdf-predicate element to determine a complete subject, predicate, object, and optional graph.

There are no pending triples or parser state completed by another element.

A statement carrier describes itself by default

Selected option: Use the carrier's non-empty id as a fragment IRI; otherwise allocate an element-local blank node.

The common case needs no explicit subject, while unidentified HTML still has a valid RDF subject.

Refer to parent resources explicitly; inherit no RDF state

Selected option: Use rdf-subject or rdf-subject-key on every carrier that describes another resource.

A heading may describe its parent by fragment IRI, but DOM nesting never changes its RDF subject, graph, datatype, language, or direction.

Do not chain subjects through nesting

Selected option: Never make one statement's object the implicit subject of another statement.

Shared anonymous resources use explicit positional keys rather than inherited object-to-subject flow.

Use no remote context, vocabulary scope, or compact IRI expansion

Selected option: Resolve ordinary IRI references only against the document's established base.

Extraction requires no network fetch and no hidden prefix map; authoring tools may abbreviate internally but emit full IRI references.

Extraction records data and executes nothing

Selected option: Never run scripts, custom elements, SHACL, SPARQL, rules, or functions as part of extraction.

The supplied root may be inert source or a live DOM previously changed by an application. Extraction itself still executes nothing, and executable vocabulary terms remain data rather than authority or consent.

Define no general rdf-object term syntax

Selected option: Construct objects from native HTML carriers, text, positional blank-node keys, or object-position templates.

A miniature Turtle-like value grammar inside one attribute would recreate a second serialization and obscure DOM correlation.

Keep blank-node keys positional

Selected option: Use separate rdf-subject-key, rdf-object-key, and rdf-graph-key attributes.

RDF independently permits blank nodes in all three positions; one generic key would need a role mini-language or contextual inference.

Use a fixed allowlist of native single-IRI carriers

Selected option: Read supported content attributes such as a[href], img[src], and q[cite] as IRI objects.

An allowlist preserves native HTML meaning while excluding URL lists, embedded documents, and ambiguous multi-value carriers.

Separate visible text from exact literal values when needed

Selected option: Use normalized text by default, with meta[content], data[value], and time[datetime] as exact lexical carriers.

Datatype uses rdf-datatype; language and base direction use only directly present native lang and dir.

Use object-position template for unasserted triple terms

Selected option: A direct child template containing one statement constructs the outer statement's RDF 1.2 triple-term object.

Template contents occupy a separate DocumentFragment, so the inner proposition can be represented without asserting or element-referencing it.

Let ordinary templates remain ordinary extractable fragments

Selected option: Give non-object-position templates no special RDF meaning in the containing document, but allow their content to be separately extracted.

Such a fragment may contain zero, one, or many statements; this removes the need for rdf-fragment and rdf-term marker attributes.

Serialize triple terms inline

Selected option: Repeat each triple-term template occurrence instead of referencing a reusable term element.

References would require lookup, cycle detection, blank-node scope rules, and a new active-versus-inert target distinction.

State graph membership locally and declare empty graphs explicitly

Selected option: Put rdf-graph or rdf-graph-key on each statement, and use the same attribute on a non-statement element for an empty graph declaration.

Graph containers do not establish scope, while declaration elements preserve empty named graphs in the RDF dataset model.

Target the complete RDF 1.2 abstract model

Selected option: Represent every RDF 1.2 term kind and dataset structure supported by the parsed HTML DOM.

The Core includes arbitrary datatypes, directional language strings, nested triple terms, blank nodes, populated and empty named graphs, and reification.

Represent SHACL and SHACL-AF as ordinary RDF

Selected option: Use the same IA² statements for shapes, rules, functions, node expressions, lists, and graph-role descriptions.

The extractor remains vocabulary-neutral and assigns no operational meaning to shapes or graph roles.

Announce extraction semantics with rdf-version

Selected option: Use rdf-version="1.2" on the document element; diagnose absence and stop on unsupported values.

A missing declaration has a documented 1.2 default for migration, while an unknown version must not be guessed.

Separate source-document identity from HTML base resolution

Selected option: Resolve fragment-only subjects and id identities against the source document IRI, while other relative IRIs use the RDF document base.

An HTML base element must not make an element's own fragment identity disagree with an explicit reference to that element.

Honor HTML canonical document identity

Selected option: Use exactly one valid, fragmentless link[rel~="canonical"] as the semantic source document IRI, falling back to the retrieval IRI with diagnostics.

A local preview, cache, or mirrored representation can preserve stable public RDF identities without hiding where the HTML was actually obtained.

Extract a light-tree snapshot from an explicit inert or live root

Selected option: Accept a Document or DocumentFragment, query its light tree, and do not cross template, shadow, or embedded-document boundaries.

Core does not prescribe how the root was acquired. Source agents can parse inert HTML; in-app tools can extract current runtime state and repeat extraction after DOM mutations. Each invocation remains a stable snapshot.

Recover locally from invalid statements

Selected option: Emit no triple for an invalid carrier, report a diagnostic, and continue with independent statements.

Processors do not pick among competing carriers, repair malformed values, or infer missing state from nearby markup.

Keep canonicalization and signatures above Core extraction

Selected option: Define semantic-signature profiles over the extracted dataset and source-signature profiles over separately defined HTML bytes.

Core supplies deterministic semantic input but does not silently restrict or transform RDF 1.2 triple terms or empty named graphs for an RDF 1.1-era canonicalizer.

Publish the ReSpec source as an IA² document

Selected option: Express document metadata, provenance, deliberation, selected options, and recorded commitments with the same rdf-* attributes the specification defines.

The first draft is therefore both a readable specification and a non-trivial conformance specimen for its own extraction model.

Provide the RDF document navigator as a separate live package

Selected option: Import the independently npm-able @ia2-dev/html-rdf-navigator browser module and update its dataset view after runtime DOM mutations.

The Navigator's drawer UI demonstrates live-DOM extraction without turning observation, serialization, or script execution into Core semantics. Downloading agents may still choose inert acquisition.