--- a/spec/latest/json-ld-api/markus.html Tue Apr 02 18:42:02 2013 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2670 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<title>JSON-LD 1.0 Processing Algorithms and API</title>
-<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
-<script type="text/javascript" src="../respec-w3c-common.js" class="remove"></script>
-<script type="text/javascript" src="../respec-w3c-extensions.js" class="remove"></script>
-<script type="text/javascript" class="remove">
-//<![CDATA[
- var respecConfig = {
- // extend the bibliography entries
- "localBiblio": localBibliography,
-
- doRDFa: "1.1",
- // specification status (e.g. WD, LCWD, NOTE, etc.). If in doubt use ED.
- specStatus: "ED",
- // if you wish the publication date to be other than today, set this
- //publishDate: "2012-12-25",
- copyrightStart: "2010",
-
- // the specification's short name, as in http://www.w3.org/TR/short-name/
- shortName: "json-ld-api",
-
- // if there is a previously published draft, uncomment this and set its YYYY-MM-DD date
- // and its maturity status
- previousPublishDate: "2012-09-30",
- previousMaturity: "ED",
- previousURI: "http://dvcs.w3.org/hg/json-ld/raw-file/66d980964784/spec/ED/json-ld-api/20120930/index.html",
-
- // if there a publicly available Editor's Draft, this is the link
- edDraftURI: "http://json-ld.org/spec/latest/json-ld-api/index.html",
-
- testSuiteURI: "http://json-ld.org/test-suite/",
-
- // if this is a LCWD, uncomment and set the end of its review period
- // lcEnd: "2009-08-05",
-
- // if you want to have extra CSS, append them to this list
- // it is recommended that the respec.css stylesheet be kept
- // extraCSS: [],
-
- issueBase: "https://github.com/json-ld/json-ld.org/issues/",
-
- // editors, add as many as you like
- // only "name" is required
- editors: [
- { name: "Markus Lanthaler", url: "http://www.markus-lanthaler.com/",
- company: "Graz University of Technology", companyURL: "http://www.tugraz.at/" },
- { name: "Gregg Kellogg", url: "http://greggkellogg.net/",
- company: "Kellogg Associates", companyURL: "http://kellogg-assoc.com/" },
- { name: "Manu Sporny", url: "http://manu.sporny.org/",
- company: "Digital Bazaar", companyURL: "http://digitalbazaar.com/" }
- ],
-
- // authors, add as many as you like.
- // This is optional, uncomment if you have authors as well as editors.
- // only "name" is required. Same format as editors.
-
- authors: [
- { name: "Dave Longley", url: "http://digitalbazaar.com/",
- company: "Digital Bazaar", companyURL: "http://digitalbazaar.com/"},
- { name: "Gregg Kellogg", url: "http://greggkellogg.net/",
- company: "Kellogg Associates", companyURL: "http://kellogg-assoc.com/" },
- { name: "Markus Lanthaler", url: "http://www.markus-lanthaler.com/",
- company: "Graz University of Technology", companyURL: "http://www.tugraz.at/" },
- { name: "Manu Sporny", url: "http://digitalbazaar.com/",
- company: "Digital Bazaar", companyURL: "http://digitalbazaar.com/" }
- ],
-
- // name of the WG
- wg: "RDF Working Group",
-
- // URI of the public WG page
- wgURI: "http://www.w3.org/2011/rdf-wg/",
-
- // name (with the @w3c.org) of the public mailing to which comments are due
- wgPublicList: "public-rdf-comments",
-
- // URI of the patent status for this WG, for Rec-track documents
- // !!!! IMPORTANT !!!!
- // This is important for Rec-track documents, do not copy a patent URI from a random
- // document unless you know what you're doing. If in doubt ask your friendly neighbourhood
- // Team Contact.
- wgPatentURI: "http://www.w3.org/2004/01/pp-impl/46168/status",
- maxTocLevel: 3,
- preProcess: [ preProc ],
- alternateFormats: [ {uri: "diff-20120930.html", label: "diff to previous version"} ],
- };
-//]]>
-</script>
-<style type="text/css">
- .diff { font-weight:bold; color:#0a3; }
-</style>
-</head>
-
-<body>
-<section id="abstract">
-<p>
-JSON [[!RFC4627]] has proven to be a highly useful object serialization and
-messaging format. JSON-LD [[!JSON-LD]] harmonizes the representation of
-Linked Data in JSON by outlining a common JSON representation format for
-expressing directed graphs, mixing both Linked Data and non-Linked Data in
-a single document. This document outlines an Application Programming
-Interface and a set of algorithms for programmatically transforming
-JSON-LD documents to make them easier to work with in programming
-environments like those that use JavaScript, Python, and Ruby.
-</p>
-</section>
-
-<section id="sotd">
-<p>This document has been under development for over 18 months in the
-JSON for Linking Data Community Group. The document has recently been
-transferred to the RDF Working Group for review, improvement, and publication
-along the Recommendation track. The specification has undergone significant
-development, review, and changes during the course of the last 18 months.
-</p>
-<p>There are several independent
-<a href="http://json-ld.org/#impl">interoperable implementations</a> of
-this specification. There is
-a <a href="https://github.com/json-ld/json-ld.org/tree/master/test-suite">fairly complete test suite</a>
-and a <a href="http://json-ld.org/playground/">live JSON-LD editor</a>
-that is capable of demonstrating the features described in
-this document. While development on implementations, the test suite
-and the live editor will continue, they are believed to be mature enough
-to be integrated into a non-production system at this point in time with
-the expectation that they could be used in a production system within the
-next year.
-</p>
-<p class="issue">
-It is important for readers to understand that the scope of this document is
-currently under debate and new features may be added to the specification.
-Existing features may be modified heavily or removed entirely from the
-specification upon further review and feedback from the broader community.
-This is a work in progress and publication as a Working Draft
-does not require that all Working Group members agree on the content of the
-document.
-</p>
-
-<p>There are a number of ways that one may participate in the development of
- this specification:</p>
-
-<ul>
- <li>If you want to make sure that your feedback is formally addressed by
- the RDF Working Group, you should send it to public-rdf-comments:
- <a href="http://lists.w3.org/Archives/Public/public-rdf-comments/">public-rdf-comments@w3.org</a></li>
-
- <li>Ad-hoc technical discussion primarily occurs on the public community mailing list:
- <a href="http://lists.w3.org/Archives/Public/public-linked-json/">public-linked-json@w3.org</a></li>
-
- <li><a href="http://json-ld.org/minutes/">Public JSON-LD Community Group teleconferences</a>
- are held on Tuesdays at 1500UTC every week. Participation is open to the
- public.</li>
-
- <li>RDF Working Group teleconferences are held on Wednesdays at 1500UTC
- every week. Participation is limited to RDF Working Group members.</li>
-
- <li>Specification bugs and issues should be reported in the
- <a href="https://github.com/json-ld/json-ld.org/issues">issue tracker</a>
- if you do not want to send an e-mail to the public-rdf-comments mailing
- list.</li>
-
- <li><a href="https://github.com/json-ld/json-ld.org/tree/master/spec">Source code</a>
- for the specification can be found on Github.</li>
-
- <li>The <a href="http://webchat.freenode.net/?channels=json-ld">#json-ld</a>
- IRC channel is available for real-time discussion on irc.freenode.net.</li>
-</ul>
-
-</section>
-
-<section class="informative">
-<h2>Introduction</h2>
-
-<p>
-This document is a detailed specification for an Application Programming
-Interface for the JSON-LD Syntax. The document is primarily intended for
-the following audiences:
-</p>
-
-<ul>
- <li>Web authors and developers that want a very detailed view of how
- a JSON-LD processor and the API operates.</li>
- <li>Software developers that want to implement processors and APIs for
- JSON-LD documents.</li>
-</ul>
-
-<p>
-To understand the basics in this specification you must first be familiar with
-JSON, which is detailed in [[!RFC4627]]. You must also understand the
-JSON-LD Syntax [[!JSON-LD]], which is the base syntax used by all of the
-algorithms in this document. To understand the API and how it is
-intended to operate in a programming environment, it is useful to have working
-knowledge of the JavaScript programming language [[ECMA-262]] and
-WebIDL [[!WEBIDL]]. To understand how JSON-LD maps to RDF, it is helpful to be
-familiar with the basic RDF concepts [[!RDF-CONCEPTS]].</p>
-
-</section>
-
-<section class="informative">
-<h1>Features</h1>
-
-<p>The JSON-LD Syntax specification [[!JSON-LD]] outlines a language that may be
- used to express Linked Data in JSON. Often, it is useful to be able to transform
- JSON-LD documents so that they may be easily processed in various programming
- environments.</p>
-
-<p>There are four major types of transformation that are discussed in this document:
- expansion, compaction, flattening, and RDF conversion.</p>
-
-<section class="informative">
- <h2>Expansion</h2>
- <p>Software algorithms are easiest to write when the data that they are processing
- have a regular form. Since information can be represented by JSON-LD in a
- variety of different ways, transforming all of these methods into a uniform
- structure allows the developer to simplify their processing code. For example,
- note that the following input uses only <tref>term</tref>s and is fairly
- compact:</p>
-
- <pre class="example" data-transform="updateExample"
- title="Sample JSON-LD document">
- <!--
- {
- "@context": {
- "name": "http://xmlns.com/foaf/0.1/name",
- "homepage": {
- "@id": "http://xmlns.com/foaf/0.1/homepage",
- "@type": "@id"
- }
- },
- "@id": "http://me.markus-lanthaler.com/",
- "name": "Markus Lanthaler",
- "homepage": "http://www.markus-lanthaler.com/"
- }
- -->
- </pre>
-
- <p>The next input example uses one <tref>IRI</tref> to express a property, but leaves
- the rest of the information untouched.</p>
-
- <pre class="example" data-transform="updateExample"
- title="Sample JSON-LD document using a IRI instead of a term to express a property">
- <!--
- {
- "@context": {
- "homepage": {
- "@id": "http://xmlns.com/foaf/0.1/homepage",
- "@type": "@id"
- }
- },
- "@id": "http://me.markus-lanthaler.com/",
- "****http://xmlns.com/foaf/0.1/name****": "Markus Lanthaler",
- "homepage": "http://www.markus-lanthaler.com/"
- }
- -->
- </pre>
-
- <p>While both inputs are valid JSON-LD, writing a program to handle every
- permutation of possible inputs can be difficult, especially when the incoming
- context could change as well. To ensure that the data can be given a more
- uniform structure, JSON-LD introduces the notion of expansion. <tdef>Expansion</tdef>
- performs two important operations. The first is to expand all values that represent
- <tref title="IRI">IRIs</tref> to <tref title="absolute IRI">absolute IRIs</tref>.
- The second is to express all values in <tref>expanded form</tref>. Running the
- <a href="#expansion-algorithm">Expansion algorithm</a> against the examples provided
- above results in the following output:</p>
-
- <pre class="example" data-transform="updateExample"
- title="Expanded sample document">
- <!--
- [
- {
- "@id": "http://me.markus-lanthaler.com/",
- "http://xmlns.com/foaf/0.1/name": [
- { "@value": "Markus Lanthaler" }
- ],
- "http://xmlns.com/foaf/0.1/homepage": [
- { "@id": "http://www.markus-lanthaler.com/" }
- ]
- }
- ]
- -->
- </pre>
-
- <p>Note that in the output above all <tref>context</tref> definitions have
- been removed, all <tref title="term">terms</tref> and <tref title="prefix">prefixes</tref>
- have been expanded to absolute <tref title="IRI">IRIs</tref>, and all
- <tref title="JSON-LD value">JSON-LD values</tref> are expressed in <tref>expanded form</tref>.
- While the output is more difficult for a human to read, it is easier for a
- software program to process because of its very regular structure.</p>
-</section>
-
-<section class="informative">
- <h2>Compaction</h2>
- <p>While expansion expands a given input as much as possible, compaction performs
- the opposite operation: it expresses a given input as succinctly as possible. In contrast
- to expansion which is meant to produce something that is easy to process by software
- programs, compaction is meant to produce something that is easy to read by software
- developers. Compaction uses a developer-supplied <tref>context</tref> to compress
- <tref title="IRI">IRIs</tref> to <tref title="term">terms</tref> or
- <tref title="compact IRI">compact IRIs</tref> and <tref title="JSON-LD value">JSON-LD values</tref>
- expressed in <tref>expanded form</tref> to simple values such as
- <tref title="string">strings</tref> or <tref title="number">numbers</tref>.</p>
-
- <p>For example, assume the following expanded JSON-LD input document:</p>
-
- <pre class="example" data-transform="updateExample"
- title="Expanded sample document">
- <!--
- [
- {
- "@id": "http://me.markus-lanthaler.com/",
- "http://xmlns.com/foaf/0.1/name": [
- { "@value": "Markus Lanthaler" }
- ],
- "http://xmlns.com/foaf/0.1/homepage": [
- { "@id": "http://www.markus-lanthaler.com/" }
- ]
- }
- ]
- -->
- </pre>
-
- <p>Additionally, assume the following developer-supplied JSON-LD <tref>context</tref>:</p>
-
- <pre class="example" data-transform="updateExample"
- title="JSON-LD context">
- <!--
- {
- "@context": {
- "name": "http://xmlns.com/foaf/0.1/name",
- "homepage": {
- "@id": "http://xmlns.com/foaf/0.1/homepage",
- "@type": "@id"
- }
- }
- }
- -->
- </pre>
-
- <p>Running the <a href="#compaction-algorithm">Compaction Algorithm</a> given the context
- supplied above against the JSON-LD input document provided above would result in the
- following output:</p>
-
- <pre class="example" data-transform="updateExample"
- title="Compacted sample document">
- <!--
- {
- "@context": {
- "name": "http://xmlns.com/foaf/0.1/name",
- "homepage": {
- "@id": "http://xmlns.com/foaf/0.1/homepage",
- "@type": "@id"
- }
- },
- "@id": "http://me.markus-lanthaler.com/",
- "name": "Markus Lanthaler",
- "homepage": "http://www.markus-lanthaler.com/"
- }
- -->
- </pre>
-
- <p>Note that all <tref title="IRI">IRIs</tref> have been compacted to
- <tref title="term">terms</tref> as specified in the <tref>context</tref>
- which consequently has been injected into the output. While compacted
- output is most useful to humans, it can often also be used to generate
- structures that are easy to program against. Compaction enables developers
- to map any expanded document into an application-specific compacted document.
- While the context provided above mapped <code>http://xmlns.com/foaf/0.1/name</code>
- to <code>name</code>, it could have also have been mapped to any other term
- provided by the developer.</p>
-
-</section>
-
-<section class="informative">
- <h2>Flattening</h2>
- <p>While expansion ensures that a document is in a uniform structure, flattening
- goes a step further and ensures that also the shape of the data is deterministic.
- In expanded documents properties of a single <tref>node</tref> may still be
- spread across a number of different <tref title="JSON object">JSON objects</tref>.
- By flattening a document, all properties of a <tref>node</tref> are collected in a
- single <tref>JSON object</tref> and all <tref title="blank node">blank nodes</tref>
- are labeled with a <tref>blank node identifier</tref>. Often this drastically
- simplifies the code to process JSON-LD data.</p>
-
- <p>For example, assume the following JSON-LD input document:</p>
-
- <pre class="example" data-transform="updateExample"
- title="Sample JSON-LD document">
- <!--
- {
- "@context": {
- "name": "http://xmlns.com/foaf/0.1/name",
- "knows": "http://xmlns.com/foaf/0.1/knows"
- },
- "@id": "http://me.markus-lanthaler.com/",
- "name": "Markus Lanthaler",
- "knows": [
- {
- "name": "Manu Sporny",
- "knows": {
- "@id": "http://greggkellogg.net/foaf#me"
- }
- },
- {
- "@id": "http://greggkellogg.net/foaf#me",
- "name": "Gregg Kellogg"
- }
- ]
- }
- -->
- </pre>
-
- <p>Running the <a href="#flattening-algorithm">Flattening Algorithm</a>
- with a context set to <tref>null</tref> to prevent compaction returns
- the following document:</p>
-
- <pre class="example" data-transform="updateExample"
- title="Flattened sample document in expanded form">
- <!--
- [
- {
- "@id": "http://me.markus-lanthaler.com/",
- "http://xmlns.com/foaf/0.1/name": [
- { "@value": "Markus Lanthaler" }
- ],
- "http://xmlns.com/foaf/0.1/knows": [
- { "@id": "_:t0" },
- { "@id": "http://greggkellogg.net/foaf#me" }
- ]
- },
- {
- "@id": "_:t0",
- "http://xmlns.com/foaf/0.1/name": [
- { "@value": "Manu Sporny" }
- ],
- "http://xmlns.com/foaf/0.1/knows": [
- { "@id": "http://greggkellogg.net/foaf#me" }
- ]
- },
- {
- "@id": "http://greggkellogg.net/foaf#me",
- "http://xmlns.com/foaf/0.1/name": [
- { "@value": "Gregg Kellogg" }
- ]
- }
- ]
- -->
- </pre>
-
- <p>Note how in the output above all properties of a <tref>node</tref> are collected in a
- single <tref>JSON object</tref> and how the <tref>blank node</tref> representing
- "Manu Sporny" has been assigned the <tref>blank node identifier</tref>
- <code>_:t0</code>.</p>
-
- <p>To make it easier for humans to read such a flattened document can be compacted by
- passing a context. Using the same context as the input document, the flattened
- and compacted document looks as follows:</p>
-
- <pre class="example" data-transform="updateExample"
- title="Flattened and compacted sample document">
- <!--
- {
- "@context": {
- "name": "http://xmlns.com/foaf/0.1/name",
- "knows": "http://xmlns.com/foaf/0.1/knows"
- },
- "@graph": [
- {
- "@id": "http://me.markus-lanthaler.com/",
- "name": "Markus Lanthaler",
- "knows": [
- { "@id": "_:t0" },
- { "@id": "http://greggkellogg.net/foaf#me" }
- ]
- },
- {
- "@id": "_:t0",
- "name": "Manu Sporny",
- "knows": {
- "@id": "http://greggkellogg.net/foaf#me"
- }
- },
- {
- "@id": "http://greggkellogg.net/foaf#me",
- "name": "Gregg Kellogg"
- }
- ]
- }
- -->
- </pre>
-
- <p>Please note that the flattened and compacted result will explicitly
- designate the default graph by the <code>@graph</code> member in the top-level
- <tref>JSON object</tref>, except if its value contains just one item.</p>
-
-</section>
-
-<section class="informative">
- <h2>RDF Conversion</h2>
- <p>JSON-LD can be used to serialize data expressed in RDF as described in
- [[RDF-CONCEPTS]]. This ensures that data can be round-tripped to and from
- any RDF syntax without any loss in fidelity.</p>
-
- <p>For example, assume the following RDF input serialized in Turtle [[TURTLE-TR]]:</p>
-
- <pre class="example" data-transform="updateExample"
- title="Sample Turtle document">
- <!--
- <http://me.markus-lanthaler.com/> <http://xmlns.com/foaf/0.1/name> "Markus Lanthaler" .
- <http://me.markus-lanthaler.com/> <http://xmlns.com/foaf/0.1/homepage> <http://www.markus-lanthaler.com/> .
- -->
- </pre>
-
- <p>Using the <a href="#convert-from-rdf-algorithm">Convert from RDF Algorithm</a> a
- developer could transform this document into expanded JSON-LD:</p>
-
- <pre class="example" data-transform="updateExample"
- title="Sample Turtle document converted to JSON-LD">
- <!--
- [
- {
- "@id": "http://me.markus-lanthaler.com/",
- "http://xmlns.com/foaf/0.1/name": [
- {
- "@value": "Markus Lanthaler"
- }
- ],
- "http://xmlns.com/foaf/0.1/homepage": [
- {
- "@id": "http://www.markus-lanthaler.com/"
- }
- ]
- }
- ]
- -->
- </pre>
-
- <p>Note that the output above could easily be compacted using the technique outlined
- in the previous section. It is also possible to transform the JSON-LD document back
- to RDF using the <a href="#convert-to-rdf-algorithm">Convert to RDF Algorithm</a>.</p>
- </section>
-
-</section>
-
-<section>
- <h1>Conformance</h1>
-
- <p>All examples and notes as well as sections marked as non-normative in this
- specification are non-normative. Everything else in this specification is
- normative.</p>
-
- <p>The keywords MUST, MUST NOT, REQUIRED, SHOULD, SHOULD NOT, RECOMMENDED,
- MAY, and OPTIONAL in this specification are to be interpreted as described
- in [[!RFC2119]].</p>
-
- <p>There are two classes of products that can claim conformance to this
- specification: <tref title="JSON-LD Implementation">JSON-LD Implementations</tref>
- and <tref title="JSON-LD Processor">JSON-LD Processors</tref>.</p>
-
- <p>A conforming <tdef>JSON-LD Implementation</tdef> is a system capable of transforming
- JSON-LD documents according the algorithms defined in this specification.</p>
-
- <p>A conforming <tdef>JSON-LD Processor</tdef> is a conforming <tref>JSON-LD Implementation</tref>
- that exposes the Application Programming Interface (API) defined in this specification.</p>
-
- <p>The algorithms in this specification are generally written with more concern for clarity than
- efficiency. Thus, JSON-LD Implementations and Processors may implement the algorithms
- given in this specification in any way desired, so long as the end result is indistinguishable
- from the result that would be obtained by the specification's algorithms.</p>
-
- <p>This specification does not define how JSON-LD Implementations or Processors handle
- non-conforming input documents. This implies that JSON-LD Implementations or Processors
- MUST NOT attempt to correct malformed <tref title="IRI">IRIs</tref> or language tags;
- however, they MAY issue validation warnings. IRIs are not modified other than converted
- between <tref title="relative IRI">relative</tref> and
- <tref title="absolute IRI">absolute IRIs</tref>.</p>
-
- <p class="note">Implementers can partially check their level of conformance to
- this specification by successfully passing the test cases of the JSON-LD test
- suite [[JSON-LD-TESTS]]. Note, however, that passing all the tests in the test
- suite does not imply complete conformance to this specification. It only implies
- that the implementation conforms to aspects tested by the test suite.</p>
-</section>
-
-<section>
- <h1>General Terminology</h1>
-
- <p>This document uses the following terms as defined in JSON [[!RFC4627]]. Refer
- to the <em>JSON Grammar</em> section in [[!RFC4627]] for formal definitions.</p>
-
- <dl>
- <dt><tdef>JSON object</tdef></dt>
- <dd>An object structure is represented as a pair of curly brackets
- surrounding zero or more key-value pairs. A key is a
- <tref>string</tref>. A single colon comes after each key, separating the
- key from the value. A single comma separates a value from a following
- key.</dd>
- <dt><tdef>array</tdef></dt>
- <dd>An array structure is represented as square brackets surrounding zero
- or more values (or elements). Elements are separated by commas.
- In JSON, an array is an <em>ordered</em> sequence of zero or more values.
- While JSON-LD uses the same array representation as JSON,
- the collection is <em>unordered</em> by default. While order is
- preserved in regular JSON arrays, it is not in regular JSON-LD arrays
- unless specific markup is provided (see <a href="#sets-and-lists"></a>).</dd>
- <dt><tdef>string</tdef></dt>
- <dd>A string is a sequence of zero or more Unicode characters,
- wrapped in double quotes, using backslash escapes (if necessary). A
- character is represented as a single character string.</dd>
- <dt><tdef>number</tdef></dt>
- <dd>A number is similar to that used in most programming languages, except
- that the octal and hexadecimal formats are not used and that leading
- zeros are not allowed.</dd>
- <dt><tdef>true</tdef> and <tdef>false</tdef></dt>
- <dd>Values that are used to express one of two possible boolean states.</dd>
- <dt><tdef>null</tdef></dt>
- <dd>The <tref>null</tref> value. A key-value pair in the
- <code>@context</code> where the value, or the <code>@id</code> of the
- value, is <tref>null</tref> explicitly decouples a term's association
- with an IRI. A key-value pair in the body of a JSON-LD document whose
- value is <tref>null</tref> has the same meaning as if the key-value pair
- was not defined. If <code>@value</code>, <code>@list</code>, or
- <code>@set</code> is set to <tref>null</tref> in expanded form, then
- the entire <tref>JSON object</tref> is ignored.</dd>
- </dl>
-
- <p>Furthermore, the following terminology is used throughout this document:</p>
-
- <dl>
- <dt><tdef>keyword</tdef></dt>
- <dd>A JSON key that is specific to JSON-LD, specified in the JSON-LD Syntax specification [[!JSON-LD]]
- in the section titled <cite><a href="../json-ld-syntax/#syntax-tokens-and-keywords">Syntax Tokens and Keywords</a></cite>.</dd>
- <dt><tdef>context</tdef></dt>
- <dd>A a set of rules for interpreting a JSON-LD document as specified in
- <cite><a href="../json-ld-syntax/#the-context">The Context</a></cite> of the [[JSON-LD]] specification.</dd>
- <dt><tdef>JSON-LD document</tdef></dt>
- <dd>A <tref>JSON-LD document</tref> is a serialization of a collection of
- <tref title="JSON-LD graph">JSON-LD graphs</tref> and comprises exactly one
- <tref>default graph</tref> and zero or more <tref title="named graph">named graphs</tref>.</dd>
- <dt><tdef>named graph</tdef></dt>
- <dd>A named graph is a pair consisting of an <tref>IRI</tref> or <tref>blank node</tref>
- (the <tdef>graph name</tdef>) and a <tref>JSON-LD graph</tref>.</dd>
- <dt><tdef>default graph</tdef></dt>
- <dd>The default graph is the only graph in a JSON-LD document which has no <tref>graph name</tref>.</dd>
- <dt><tdef>JSON-LD graph</tdef></dt>
- <dd>A labeled directed graph, i.e., a set of <tref title="node">nodes</tref> connected by <tref title="edge">edges</tref>,
- as specified in the <cite><a href="../json-ld-syntax/#data-model">Data Model</a></cite> section of the JSON-LD syntax
- specification [[!JSON-LD]].</dd>
- <dt><tdef>edge</tdef></dt>
- <dd>Every <tref>edge</tref> has a direction associated with it and is labeled with
- an <tref>IRI</tref> or a <tref>blank node identifier</tref>. Within the JSON-LD syntax
- these edge labels are called <tdef title="property">properties</tdef>. Whenever possible, an
- <tref>edge</tref> SHOULD be labeled with an <tref>IRI</tref>.</dd>
- <dt><tdef>node</tdef></dt>
- <dd>Every <tref>node</tref> is an <tref>IRI</tref>, a <tref>blank node</tref>,
- a <tref>JSON-LD value</tref>, or a <tref>list</tref>.</dd>
- <dt><tdef><abbr title="Internationalized Resource Identifier">IRI</abbr></tdef></dt>
- <dd>An <tref>IRI</tref> (Internationalized Resource Identifier) is a string that conforms to the syntax
- defined in [[RFC3987]].</dd>
- <dt><tdef>absolute IRI</tdef></dt>
- <dd>An absolute IRI is defined in [[!RFC3987]] containing a <em>scheme</em> along with a <em>path</em> and
- optional <em>query</em> and fragment segments.</dd>
- <dt><tdef>relative IRI</tdef></dt>
- <dd>A relative IRI is an IRI that is relative some other <tref>absolute IRI</tref>;
- in the case of JSON-LD this is the base location of the document.</dd>
- <dt><tdef>blank node</tdef></dt>
- <dd>A <tref>node</tref> in a <tref>JSON-LD graph</tref> that does not contain a de-referenceable
- identifier because it is either ephemeral in nature or does not contain information that needs to be
- linked to from outside of the JSON-LD graph.</dd>
- <dt><tdef>blank node identifier</tdef></dt>
- <dd>A blank node identifier is a string that can be used as an identifier for a <tref>blank node</tref> within
- the scope of a JSON-LD document. Blank node identifiers begin with <code>_:</code>.</dd>
- <dt><tdef>JSON-LD value</tdef></dt>
- <dd>A <tref>JSON-LD value</tref> is a <tref>string</tref>, a <tref>number</tref>,
- <tref>true</tref> or <tref>false</tref>, a <tref>typed value</tref>, or a
- <tref>language-tagged string</tref>.</dd>
- <dt><tdef>typed value</tdef></dt>
- <dd>A <tref>typed value</tref> consists of a value, which is a string, and a type, which is an <tref>IRI</tref>.</dd>
- <dt><tdef>language-tagged string</tdef></dt>
- <dd>A <tref>language-tagged string</tref> consists of a string and a non-empty language
- tag as defined by [[BCP47]]. The language tag must be well-formed according to section
- <a href="http://tools.ietf.org/html/bcp47#section-2.2.9">2.2.9</a> of [[BCP47]], and MUST
- be normalized to lowercase.</dd>
- <dt><tdef>list</tdef></dt>
- <dd>A <tref>list</tref> is an ordered sequence of <tref title="IRI">IRIs</tref>,
- <tref title="blank node">blank nodes</tref>, and
- <tref title="JSON-LD value">JSON-LD values</tref>.</dd>
- </dl>
-
-</section>
-
-<section>
-<h1>Algorithms</h1>
-
-<p>All algorithms described in this section are intended to operate on
- language-native data structures. That is, the serialization to a text-based
- JSON document isn't required as input or output to any of these algorithms and
- language-native data structures MUST be used where applicable.</p>
-
-<section>
- <h2>Algorithm Terms</h2>
-
- <dl>
- <dt><tdef>active graph</tdef></dt>
- <dd>The name of the currently active graph that the processor should use when
- processing.</dd>
- <dt><tdef>active subject</tdef></dt>
- <dd>The currently active subject that the processor should use when
- processing.</dd>
- <dt><tdef>active property</tdef></dt>
- <dd>The currently active property that the processor should use when
- processing. The active property is represented in the original lexical form, which
- is used for finding type mappings in the <tref>active context</tref>.</dd>
- <dt><tdef>active object</tdef></dt>
- <dd>The currently active object that the processor should use when
- processing.</dd>
- <dt><tdef>active context</tdef></dt>
- <dd>A context that is used to resolve <tref title="term">terms</tref> while
- the processing algorithm is running.</dd>
- <dt><tdef>local context</tdef></dt>
- <dd>A context that is specified within a <tref>JSON object</tref>,
- specified via the <code>@context</code> <tref>keyword</tref>.</dd>
- <dt><tdef>processor state</tdef></dt>
- <dd>The <tref>processor state</tref>, which includes the <tref>active
- context</tref>, <tref>active subject</tref>, and
- <tref>active property</tref>. The <tref>processor state</tref> is managed
- as a stack with elements from the previous <tref>processor state</tref>
- copied into a new <tref>processor state</tref> when entering a new
- <tref>JSON object</tref>.</dd>
- <dt><tdef>JSON-LD input</tdef></dt>
- <dd>The JSON-LD data structure that is provided as input to the algorithm.</dd>
- <dt><tdef>JSON-LD output</tdef></dt>
- <dd>The JSON-LD data structure that is produced as output by the algorithm.</dd>
- <dt><tdef>term</tdef></dt>
- <dd>A <tref>term</tref> is a short word defined in a context that MAY be expanded to an <tref>IRI</tref></dd>
- <dt><tdef>compact IRI</tdef></dt>
- <dd>A compact IRI is has the form of <tdef>prefix</tdef>:<em>suffix</em> and is used as a way
- of expressing an IRI without needing to define separate <tref>term</tref> definitions for
- each IRI contained within a common vocabulary identified by <tref>prefix</tref>.</dd>
- <dt><tdef>node object</tdef></dt>
- <dd>A <tref>node object</tref> represents zero or more properties of a
- <tref>node</tref> in the <tref>JSON-LD graph</tref> serialized by the
- JSON-LD document. A <tref>JSON object</tref> is a <tref>node object</tref>
- if it exists outside of the JSON-LD <tref>context</tref> and:
- <ul>
- <li>it does not contain the <code>@value</code>, <code>@list</code>,
- or <code>@set</code> keywords, or</li>
- <li>it is not the top-level <tref>JSON object</tref> in the JSON-LD document containing
- the <code>@graph</code> keyword.</li>
- </ul>
- </dd>
- <dt><tdef>list object</tdef></dt>
- <dd>A <tref>list object</tref> is a <tref>JSON object</tref> that has an <code>@list</code>
- member.</dd>
- <dt><tdef>scalar</tdef></dt>
- <dd>A scalar is either a JSON <tref>string</tref>, <tref>number</tref>, <tref>true</tref>,
- or <tref>false</tref>.</dd>
- <dt><tdef>quad</tdef></dt>
- <dd>An <em>RDF triple</em> as specified by [[RDF-CONCEPTS]] augmented with
- a fourth component, a <tref>graph name</tref>.</dd>
- </dl>
-</section>
-
-<section>
- <h2>Expansion Algorithm</h2>
-
- <p>The algorithm takes three input variables: an <tref>active context</tref>,
- an <tref>active property</tref>, and an <em>element</em> to be expanded. To
- begin, the <tref>active context</tref> is set to the result of performing, <a
- href="#context-processing">Context Processing</a> on the passed
- <code class="idlMemberName"><a href="#widl-JsonLdOptions-expandContext">expandContext</a></code>,
- or empty if <code class="idlMemberName"><a href="#widl-JsonLdOptions-expandContext">expandContext</a></code>
- is <tref>null</tref>, <tref>active property</tref> is set to <tref>null</tref>, and
- <em>element</em> is set to the <tref>JSON-LD input</tref>. This algorithm expects the
- <tref>JSON-LD input</tref> to be a well-formed JSON-LD document as defined in [[!JSON-LD]].</p>
-
- <ol class="algorithm">
- <li>If <em>element</em> is a <tref>scalar</tref>, expand it according to the
- <a href="#value-expansion">Value Expansion</a> algorithm, passing copies of the
- <tref>active context</tref> and <tref>active property</tref> and return. If the
- <tref>active property</tref> equals <tref>null</tref> or <code>@graph</code>
- set <em>element</em> to <tref>null</tref> instead and return.</li>
- <li>If <em>element</em> is <tref>null</tref>, return.</li>
- <li>If <em>element</em> is an <tref>array</tref>,
- <ol class="algorithm">
- <li>initialize an empty array <em>result</em>.</li>
- <li>Expand each <em>item</em> by recursively using this algorithm, passing copies of
- the <tref>active context</tref> and <tref>active property</tref>.</li>
- <li>If the <tref title="active property">active property's</tref>
- <tref>container mapping</tref> is set to <code>@list</code> and the expanded
- <em>item</em> is an <tref>array</tref> or a <tref>list object</tref> trigger
- a <code class="error">list of lists detected</code> error.</li>
- <li>If the expanded <em>item</em> is <tref>null</tref>, drop it.</li>
- <li>Otherwise, if the expanded <em>item</em> is an <tref>array</tref>, merge its
- entries with <em>result's</em> entries.</li>
- <li>Otherwise, append <em>item</em> to <em>result</em>.</li>
- <li>Finally, set <em>element</em> to <em>result</em> and return.</li>
- </ol>
- </li>
- <li>Otherwise, <em>element</em> must be an object.
- <ol class="algorithm">
- <li>If <em>element</em> has a <code>@context</code> member, update the
- <tref>active context</tref> according to the steps outlined in
- <a href="#context-processing">Context Processing</a> and remove the
- <code>@context</code> member.</li>
- <li>Initialize an empty <tref>JSON object</tref> <em>result</em> and</li>
- <li>then process each <em>property</em> and <em>value</em> in <em>element</em>
- ordered by <em>property</em> as follows:
- <ol class="algorithm">
- <li>If the <tref>active context</tref> contains a <tref>property generator</tref> for
- <em>property</em> set <em>expanded property</em> to its <tref title="IRI">IRIs</tref>,
- otherwise set it to the result of expanding <em>property</em> according to the steps
- outlined in <a href="#iri-expansion">IRI Expansion</a> (passing <code>true</code> for
- the <em>vocabRelative</em> flag).</li>
- <li>If <em>expanded property</em> is a <tref>keyword</tref>, process it as
- follows:
- <ol class="algorithm">
- <li>If <em>expanded property</em> equals <code>@id</code>, set the <code>@id</code>
- member of <em>result</em> to the result of expanding <em>value</em>
- according the <a href="#iri-expansion">IRI Expansion algorithm</a> (passing <code>true</code>
- for the <em>documentRelative</em> flag). If <em>value</em> is not a <tref>string</tref>
- trigger an <code class="error">invalid @id value</code> error.</li>
- <li>If <em>expanded property</em> equals <code>@type</code>, set the <code>@type</code>
- member of <em>result</em> to the result of expanding <em>value</em>
- according the <a href="#iri-expansion">IRI Expansion algorithm</a> (passing <code>true</code>
- for both the <em>documentRelative</em> and the <em>vocabRelative</em> flag). If <em>value</em>
- is neither a <tref>string</tref> nor an <tref>array</tref> of
- <tref title="string">strings</tref> trigger an <code class="error">invalid type value</code>
- error. Empty <tref title="array">arrays</tref> are ignored.</li>
- <li>If <em>expanded property</em> equals <code>@value</code>, set the <code>@value</code>
- member of <em>result</em> to <em>value</em>. If <em>value</em> is neither a <tref>scalar</tref>
- nor <tref>null</tref> trigger an <code class="error">invalid value object value</code> error.</li>
- <li>If <em>expanded property</em> equals <code>@language</code>, set the <code>@language</code>
- member of <em>result</em> to the lowercased <em>value</em>. If <em>value</em> is not
- a <tref>string</tref>, trigger an <code class="error">invalid language value</code> error.</li>
- <li>If <em>expanded property</em> equals <code>@index</code>, set the <code>@index</code>
- member of <em>result</em> to <em>value</em>. If <em>value</em> is not a <tref>string</tref>
- trigger an <code class="error">invalid @index value</code> error.</li>
- <li>If <em>expanded property</em> equals <code>@set</code> set the <em>expanded property</em>
- member of <em>result</em> to the result of expanding <em>value</em> by
- recursively using this algorithm, passing copies of the <tref>active context</tref> and
- <tref>active property</tref>.</li>
- <li>If <em>expanded property</em> equals <code>@list</code>, set the <em>expanded property</em>
- member of <em>result</em> to the result of expanding <em>value</em> by
- recursively using this algorithm, passing copies of the <tref>active context</tref> and
- <tref>active property</tref>; if <tref>active property</tref> equals <tref>null</tref> or
- <code>@graph</code>, pass <code>@list</code> as <tref>active property</tref> instead.</li>
- <li>If <em>expanded property</em> equals <code>@graph</code>, set the <code>@graph</code>
- member of <em>result</em> to the result of expanding <em>value</em> by
- recursively using this algorithm, passing copies of the <tref>active context</tref> and
- <code>@graph</code> as <tref>active property</tref>.</li>
- <li>Continue with the next <em>property</em>-<em>value</em> pair from <em>element</em>.</li>
- </ol>
- </li>
- <li>If <em>expanded property</em> is neither a <tref>blank node identifier</tref> nor an
- <tref>absolute IRI</tref>,i.e., it is <tref>null</tref> or does not contain a colon
- (<code>:</code>), continue with the next member from <em>element</em>.</li>
- <li>Otherwise, if <em>property's</em> <tref>container mapping</tref> is set to
- <code>@language</code>
- <ol class="algorithm">
- <li>Initialize a new empty <tref>array</tref> <em>language map values</em>.</li>
- <li>Process each <em>key</em>-<em>val</em> pair of <em>value</em> ordered by
- <em>key</em> as follows:
- <ol class="algorithm">
- <li>If <em>val</em> is not an array, transform it to one.</li>
- <li>For each item of <em>val</em>, construct a new <tref>JSON object</tref>
- consisting of two members: <code>@value</code> set to the currently
- processed item and <code>@language</code> set to the lowercased <em>key</em>.
- If <em>val</em> is not a <tref>string</tref>, trigger a
- <code class="error">language map invalid value</code> error. Otherwise append
- the object to <em>language map values</em>.</li>
- </ol>
- </li>
- <li>Set <em>value</em> to <em>language map values</em>.</li>
- </ol>
- </li>
- <li>Otherwise, if <em>property's</em> <tref>container mapping</tref> is set to
- <code>@index</code>
- <ol class="algorithm">
- <li>Initialize a new empty <tref>array</tref> <em>index map values</em>.</li>
- <li>Process each <em>key</em>-<em>val</em> pair of <em>value</em> ordered by
- <em>key</em> as follows:
- <ol class="algorithm">
- <li>If <em>val</em> is not an array, transform it to one.</li>
- <li>Expand <em>val</em> by recursively using this algorithm, passing copies of
- the <tref>active context</tref> and <em>property</em> as
- <tref>active property</tref>.</li>
- <li>Add to each item of <em>val</em> a member <code>@index</code> set to
- <em>key</em> if no such member exists yet and append the resulting
- <tref>JSON object</tref> to <em>index map values</em>.</li>
- </ol>
- </li>
- <li>Set <em>value</em> to <em>index map values</em>.</li>
- </ol>
- </li>
- <li>Otherwise, expand <em>value</em> by recursively using this algorithm, passing
- copies of the <tref>active context</tref> and <em>property</em> as
- <tref>active property</tref>.</li>
- <li>If the expanded <em>value</em> equals <tref>null</tref>, continue with the next
- <em>property</em>-<em>value</em> pair from <em>element</em>.</li>
- <li>If <em>property's</em> <tref>container mapping</tref> is set to <code>@list</code> and
- <em>value</em> is either not an <tref>JSON object</tref> or a <tref>JSON object</tref>
- without an <code>@list</code> member, replace <em>value</em> with a
- <tref>JSON object</tref> with an <code>@list</code> member whose value is set to
- <em>value</em> (wrapped in an <tref>array</tref> if it is not already one).</li>
- <li>If <em>expanded property</em> is an <tref>array</tref>,
- <ol class="algorithm">
- <li>label all <tref title="blank node">blank nodes</tref> in <em>value</em> with
- <tref title="blank node identifier">blank node identifiers</tref> by using the
- <a href="#label-blank-nodes-algorithm">Label Blank Nodes Algorithm</a>.</li>
- <li>Then, for each <em>iri</em> of <em>expanded property</em> merge a copy
- of <em>value</em> into the <em>iri</em> member of the <em>result</em>
- <tref>JSON object</tref>.</li>
- </ol>
- </li>
- <li>Otherwise, merge <em>value</em> into the <em>iri</em> member of the <em>result</em>
- <tref>JSON object</tref>.</li>
- </ol>
- </li>
- <li>Set <em>element</em> to <em>result</em> and <em>numProperties</em> to the number of members
- of <em>result</em>.</li>
- <li>If <em>element</em> has an <code>@index</code> member, decrease <em>numProperties</em>
- by 1.</li>
- <li>If the <tref>active property</tref> equals <tref>null</tref> or <code>@graph</code> and
- <em>element</em> has an <code>@value</code> member, <em>numProperties</em> equals <code>0</code>,
- or <em>element</em> consists of only an <code>@id</code> member, set <em>element</em> to
- <tref>null</tref> and return.</li>
- <li>If <em>element</em> has an <code>@value</code> member,
- <ol class="algorithm">
- <li>decrease <em>numProperties</em> by 1.</li>
- <li>If <em>element</em> has an <code>@language</code> member, decrease <em>numProperties</em>
- by 1 and check that the value of the <code>@value</code> member is a string. If not,
- trigger an <code class="error">invalid language tagged string</code> error.</li>
- <li>Otherwise, if <em>element</em> has an <code>@type</code> member, decrease
- <em>numProperties</em> by 1 and check that the value of the <code>@type</code> member is a
- string. If not, trigger an <code class="error">invalid typed value</code> error.</li>
- <li>If <em>numProperties</em> is greater than 0, trigger an
- <code class="error">invalid value object</code> error.</li>
- <li>If the value of the <code>@value</code> member equals <tref>null</tref>, set
- <em>element</em> to <tref>null</tref>.</li>
- <li>Return.</li>
- </ol>
- </li>
- <li>If <em>element</em> has an <code>@type</code> member whose value is not an <tref>array</tref>,
- transform it to an <tref>array</tref>.</li>
- <li>If <em>element</em> has an <code>@list</code> or <code>@set</code> member and
- <em>numProperties</em> is greater than 1, trigger an
- <code class="error">invalid set or list object</code> error.</li>
- <li>Otherwise, if <em>element</em> has an <code>@set</code> member, set <em>element</em> to
- the value of that member.</li>
- <li>Otherwise, if <em>element</em> has just an <code>@language</code> member, set <em>element</em>
- to null.</li>
- </ol>
- </li>
- </ol>
-
- <p>If, after the algorithm outlined above is run, the resulting <em>element</em> is an
- <tref>JSON object</tref> with just a <code>@graph</code> member, <em>element</em> is set to
- the value of <code>@graph</code>'s value. Finally, if <em>element</em> is a <tref>JSON object</tref>,
- it is wrapped into an <tref>array</tref>, if <em>element</em> equals <tref>null</tref>, an empty
- <tref>array</tref> is returned.</p>
-</section>
-
-<section>
- <h2 id="context">Context Processing</h2>
-
- <p>Processing of JSON-LD data structure is managed recursively. During processing, each
- rule is applied using information provided by the <tref>active context</tref>.</p>
-
- <p>The <tref>active context</tref> contains the active <tdef title="term definition">term definitions</tdef>
- which specify how properties and values have to be interpreted as well as the current
- <tdef>vocabulary mapping</tdef> and the <tdef>default language</tdef>. Each <tref>term definition</tref> consists
- of an <tdef>IRI mapping</tdef> and optionally a <tdef>type mapping</tdef> from terms to datatypes or
- <tdef>language mapping</tdef> from terms to language codes, and a <tdef>container mapping</tdef>. If an
- <tref>IRI mapping</tref> maps a term to multiple <tref="IRI">IRIs</tref> it is said to be a
- <tdef>property generator</tdef>.</p>
-
- <p>If a <tref>local context</tref> is encountered, information from the <tref>local context</tref>
- is merged into the <tref>active context</tref>. A <tref>local context</tref> is identified within
- a <tref>JSON object</tref> having a <code>@context</code> member with a <tref>string</tref>,
- <tref>array</tref> or a <tref>JSON object</tref> value.</p>
-
- <p>This algorithm specifies how the <tref>active context</tref> is updated with a
- <tref>local context</tref>. The algorithm takes three input variables: an <tref>active context</tref>,
- a <tref>local context</tref>, and an array of already included remote contexts <em>remoteContexts</em>. To
- begin, <em>remoteContexts</em> is initialized to an empty array.</p>
-
- <p>All calls of the <a href="#iri-expansion">IRI Expansion algorithm</a> pass the value specified in the
- algorithm along with the <tref>active context</tref>, the currently being processed <tref>local context</tref>,
- and <code>true</code> for the <em>vocabRelative</em> flag.</p>
-
- <ol class="algorithm">
- <li>If the <tref>local context</tref> is not an array, transform it to one.</li>
- <li>Process each item <em>context</em> of the <tref>local context</tref> as follows:
- <ol class="algorithm">
- <li>If <em>context</em> equals <tref>null</tref>, reset the <tref>active context</tref>
- and continue with the next item.</li>
- <li>If <em>context</em> is a <tref>string</tref>:
- <ol class="algorithm">
- <li>Expand <em>context</em> according to <a href="#iri-expansion">IRI Expansion</a>.</li>
- <li>If <em>context</em> is in the <em>remoteContexts</em> array, raise an
- <code class="error">recursive context inclusion</code> error. Otherwise, add
- <em>context</em> to <em>remoteContexts</em>.</li>
- <li>Dereference <em>context</em>.</li>
- <li>If the resulting document is a JSON document consisting of a top-level
- <tref>JSON object</tref> that has a <code>@context</code> member recursively invoke
- this algorithm passing a copy of <tref>active context</tref>, the value of the
- <code>@context</code> member as <tref>local context</tref>, and a copy of
- the <em>remoteContexts</em> array. <tref title="relative IRI">Relative IRIs</tref>
- are expanded using the remote context's IRI. Otherwise raise an
- <code class="error">invalid remote context</code> error.</li>
- <li>Continue with the next item from <em>context</em>.</li>
- </ol>
- </li>
- <li>If <em>context</em> is not a <tref>JSON object</tref>, raise an
- <code class="error">invalid local context</code> error.</li>
- <li>Otherwise, if <em>context</em> is an <tref>JSON object</tref>, perform the following steps:
- <ol class="algorithm">
- <li>If <em>context</em> has a <code>@vocab</code> member: if its value is neither
- an <tref>absolute IRI</tref>, i.e., it does not contain a colon (<code>:</code>),
- nor <tref>null</tref>, trigger an <code class="error">invalid vocab mapping</code>
- error; otherwise set the <tref title="active context">active context's</tref>
- <tref>vocabulary mapping</tref> to its value and remove the <code>@vocab</code>
- member from <em>context</em>.</li>
- <li>If <em>context</em> has a <code>@language</code> member: if its value is neither
- a <tref>string</tref> nor <tref>null</tref>, trigger an
- <code class="error">invalid default language</code> error; otherwise set the
- <tref title="active context">active context's</tref> <tref>default language</tref> to
- its value and remove the <code>@language</code> member from <em>context</em>.</li>
- <li>For each other <em>key</em>-<em>value</em> pair in <em>context</em> perform the
- following steps:
- <ol class="algorithm">
- <li>Remove the <em>key</em>-<em>value</em> pair from <em>context</em>.</li>
- <li>If <em>key</em> is a JSON-LD <tref>keyword</tref>, raise a
- <code class="error">keyword redefinition</code> error.</li>
- <li>If <em>value</em> equals <tref>null</tref>, replace the <tref>term definition</tref>
- for <em>key</em> in the <tref>active context</tref> with an <tref>IRI mapping</tref>
- set to <tref>null</tref> and continue with the next <em>key</em>-<em>value</em> pair.</li>
- <li>If <em>value</em> is a <tref>string</tref>, expand it according to the
- <a href="#iri-expansion">IRI Expansion algorithm</a> and replace the
- <tref>term definition</tref> for <em>key</em> in the <tref>active context</tref> with
- an <tref>IRI mapping</tref> set to the expanded <em>value</em>. Continue with
- the next <em>key</em>-<em>value</em> pair.</li>
- <li>If <em>value</em> is not a <tref>JSON object</tref>, trigger an
- <code class="error">invalid term definition</code> error</li>
- <li>If <tref>term definition</tref> for <em>key</em> exists in the
- <tref>active context</tref>, remove it.</li>
- <li>Initialize a new, empty <tref>term definition</tref> <em>definition</em>.</li>
- <li>If <em>value</em> has an <code>@id</code> member with a value <em>val</em>:
- <ol class="algorithm">
- <li>if <em>val</em> is an <tref>array</tref>,:
- <ol class="algorithm">
- <li>expand each <em>item</em> in the array according the
- <a href="#iri-expansion">IRI Expansion algorithm</a> if it is a
- <tref>string</tref>. If am <em>item</em> is not a <tref>string</tref>,
- raise an <code class="error">invalid property generator</code> error; if
- <em>item</em> does not expand to an <tref>absolute IRI</tref> or
- <tref>blank node identifier</tref>, i.e., it does not contain a colon
- (<code>:</code>) after expansion, raise an
- <code class="error">invalid property generator IRI mapping</code> error.</li>
- <li>Lexicographically sort <em>val</em> and set the <tref>IRI mapping</tref>
- of <em>definition</em> to <em>val</em>.</li>
- </ol>
- <li>Otherwise, expand <em>val</em> according the
- <a href="#iri-expansion">IRI Expansion algorithm</a> and set the
- <tref>IRI mapping</tref> of <em>definition</em> to <em>val</em>.</li>
- </ol>
- </li>
- <li>Otherwise, set the <tref>IRI mapping</tref> of <em>definition</em> to the result of
- expanding <em>key</em> according the <a href="#iri-expansion">IRI Expansion algorithm</a>.</li>
- <li>If the <tref>IRI mapping</tref> of <em>definition</em> is set to <tref>null</tref> or a
- <tref>keyword</tref>, store <em>definition</em> as the <tref>term definition</tref>
- for <em>key</em> in the <tref>active context</tref> and continue with the next
- <em>key</em>-<em>value</em> pair from <em>context</em>.</li>
- <li>Otherwise, if the <tref>IRI mapping</tref> of <em>definition</em> is set to
- a <tref>string</tref> which does not contain a colon (<code>:</code>), i.e., it is
- neither an <tref>absolute IRI</tref> nor a <tref>blank node identifier</tref>,
- raise an <code class="error">invalid term IRI mapping</code> error.</li>
- <li>If <em>value</em> has an <code>@type</code> member with a value <em>val</em> and <em>val</em>
- is not a <tref>string</tref> or does not expand to an <tref>absolute IRI</tref> using the
- <a href="#iri-expansion">IRI Expansion algorithm</a>, raise an
- <code class="error">invalid type mapping</code> error. Otherwise set the
- <tref>IRI mapping</tref> of <em>definition</em> to the expanded <em>val</em>.</li>
- <li>Otherwise, if <em>value</em> has an <code>@language</code> member with a value <em>val</em>
- that is a <tref>string</tref> or <tref>null</tref>, set the <tref>language mapping</tref> of
- <em>definition</em> to the lowercased <em>val</em>. If <em>val</em> is neither a
- <tref>string</tref> nor <tref>null</tref>, raise an
- <code class="error">invalid language mapping</code> error.</li>
- <li>If <em>value</em> has an <code>@container</code> member with a value <em>val</em> that
- equals <code>@list</code>, <code>@set</code>, <code>@language</code>, or <code>@index</code>,
- set the <tref>container mapping</tref> of <em>definition</em> to <em>val</em>.
- If <em>val</em> is not one of those values, raise an
- <code class="error">invalid container mapping</code> error.</li>
- </ol>
- </li>
- </ol>
- </li>
- </ol>
- </li>
- </ol>
-</section>
-
-<section>
- <h2>IRI Expansion</h2>
-
- <p>In JSON-LD documents keys and some values are evaluated to produce an <tref>IRI</tref>.
- This section defines an algorithm for transforming strings representing an IRI into an
- <tref>absolute IRI</tref>. If IRI expansion occurs during context processing, the
- <tref>local context</tref> that is being processed is passed to this algorithm.
- After application of this algorithm, values processed by this algorithm are said to be
- in <tdef>expanded IRI form</tdef>, although this may also include
- <tref title="blank node identifier">blank node identifiers</tref> and
- JSON-LD <tref title="keyword">keywords</tref>.</p>
-
- <p>The algorithm takes two mandatory and four optional input variables: a <em>value</em>
- to be expanded, an <tref>active context</tref>, two flags <em>documentRelative</em> and
- <em>vocabRelative</em> specifying whether <em>value</em> should be interpreted as
- <tref>relative IRI</tref> against the document's base IRI or the
- <tref title="active context">active context's</tref> <tref>vocabulary mapping</tref>,
- along with an <tref>local context</tref> passed when this algorithm is used in
- <a href="#context-processing">Context Processing</a>, and finally an array
- <em>path</em> which is used to detect cyclic <tref title="IRI mapping">IRI mappings</tref>.
- If not passed, the two flags are set to <code>false</code> and <em>path</em> is
- initialized to an empty <tref>array</tref> by default.</p>
-
- <p>The algorithm for generating an IRI is:</p>
-
- <ol class="algorithm">
- <li>If <em>value</em> is <tref>null</tref> or a JSON-LD <tref>keyword</tref>, return
- <em>value</em> as is.</li>
- <li>If a <tref>local context</tref> has been passed
- <ol class="algorithm">
- <li>and <em>value</em> is in the <em>path</em> array, raise a
- <code class="error">cyclic IRI mapping</code> error. Otherwise append <em>value</em>
- to <em>path</em>.</li>
- <li>If <tref>local context</tref> contains an <tref>IRI mapping</tref> for <em>value</em>
- that is not a <tref>property generator</tref> return the result of recursively calling
- this algorithm passing the <tref>IRI</tref> of the <tref>IRI mapping</tref> as new
- <em>value</em>, the <tref>active context</tref> and <tref>local context</tref>,
- <em>path</em>, and <code>true</code> for the <em>vocabRelative</em> flag. If the result
- is a <tref>property generator</tref>, raise an
- <code class="error">property generator in term definition</code> error.</li>
- </ol>
- </li>
- <li>If the <em>vocabRelative</em> flag is set to <code>true</code> and an <tref>IRI mapping</tref>
- exists for <em>value</em> in the <tref>active context</tref> that is not a
- <tref>property generator</tref>, return the value of the <tref>IRI mapping</tref>.</li>
- <li>If <em>value</em> contains a colon (<code>:</code>), perform the following steps:
- <ol class="algorithm">
- <li>Split <em>value</em> into a <em>prefix</em> and <em>suffix</em> at the first occurrence of
- a colon (<code>:</code>).</li>
- <li>If <em>suffix</em> begins with <code>//</code> or <em>prefix</em> equals <code>_</code>,
- return <em>value</em> as is.</li>
- <li>If a <tref>local context</tref> has been passed, expand <em>prefix</em> by recursively
- invoking this algorithm passing <em>prefix</em> as <em>value</em>, the <tref>active context</tref>
- and <tref>local context</tref>, <em>path</em>, and <code>true</code> for the
- <em>vocabRelative</em> flag. If the expanded <em>prefix</em> contains a colon (<code>:</code>)
- generate and return an <tref>IRI</tref> by prepending the expanded <em>prefix</em> to the
- (possibly empty) <em>suffix</em> using textual concatenation.</li>
- <li>Otherwise, if the <tref>active context</tref> contains an <tref>IRI mapping</tref> for
- <em>prefix</em> that is not a <tref>property generator</tref>, generate and return an
- <tref>IRI</tref> by prepending the <tref>IRI</tref> mapped to <em>prefix</em> to the
- (possibly empty) <em>suffix</em> using textual concatenation.</li>
- </ol>
- </li>
- <li>Otherwise, if the <em>vocabRelative</em> flag is set to <code>true</code> and the
- <tref>active context</tref> contains a <tref>vocabulary mapping</tref>, generate and return an
- <tref>IRI</tref> by prepending the <tref>IRI</tref> of the <tref>vocabulary mapping</tref>
- to the <em>value</em> using textual concatenation.</li>
- <li>Otherwise, if the <em>documentRelative</em> flag is set to <code>true</code>, resolve <em>value</em>
- against the base IRI as per [[!RFC3986]] and return the resulting <tref>IRI</tref>. Only the basic
- algorithm in section 5.2 of [[!RFC3986]] is used; neither <em>Syntax-Based Normalization</em>
- nor <em>Scheme-Based Normalization</em> (as described in sections 6.2.2 and 6.2.3 of [[!RFC3986]])
- are performed. Characters additionally allowed in IRI references are treated in the same way that
- unreserved characters are treated in URI references, per section 6.5 of [[!RFC3987]]</li>
- <li>Otherwise return <em>value</em> as is.</li>
- </ol>
-
- <p>If the result of the algorithm above is a <tref>blank node identifier</tref>, i.e., a string that begins with
- <code>_:</code>, and no <tref>local context</tref> has been passed,
- <a href="#generate-blank-node-identifier">generated a new blank node identifier</a> before returning the
- final result.</p>
-</section>
-
-<section>
- <h2>Value Expansion</h2>
-
- <p>Some values in JSON-LD can be expressed in a <tref>compacted form</tref>. These values
- are required to be expanded at times when processing JSON-LD documents.
- A value is said to be in <tdef>expanded form</tdef> after
- the application of this algorithm.</p>
-
- <p>The algorithm for expanding a <em>value</em> takes an <tref>active property</tref>
- and <tref>active context</tref>. It is implemented as follows:</p>
-
- <ol class="algorithm">
- <li>If <em>value</em> is <tref>null</tref>, return <tref>null</tref>.</li>
- <li>Initialize an empty object <em>result</em>.</li>
- <li>If <tref>active property</tref> is <code>@graph</code> or the
- <tref title="active property">active property's</tref> <tref>type mapping</tref> is set to
- <code>@id</code>, add a key-value pair to <em>result</em> where the key is <code>@id</code>
- and the value is the result of expanding <em>value</em> according to the
- <a href="#iri-expansion">IRI Expansion algorithm</a> passing <code>true</code> for the
- <em>documentRelative</em> flag. Then return <em>result</em>.</li>
- <li>Add a key-value pair to <em>result</em> where the key is <code>@value</code>
- and the value is <em>value</em>.</li>
- <li>If the <tref>active property</tref> has a <tref>type mapping</tref>, add a key-value
- pair to <em>result</em> where the key is <code>@type</code> and the value is the
- <tref>IRI</tref> associated with the <tref>type mapping</tref> or a newly
- <a href="#generate-blank-node-identifier">generated blank node identifier</a> if the
- <tref>type mapping</tref> is set to a <tref>blank node identifier</tref>.</li>
- <li>Otherwise, if <em>value</em> is a <tref>string</tref> and the <tref>active property</tref> has a
- <tref>language mapping</tref> or an <tref>default language</tref> is set in the <tref>active context</tref>,
- add a key-value pair to <em>result</em> where the key is <code>@language</code> and the value is the
- language tag associated with the <tref>language mapping</tref> or the <tref>active property</tref> or the
- <tref>default language</tref>.</li>
- <li>Return <em>result</em>.</li>
- </ol>
-</section>
-
-<section>
- <h2>Label Blank Nodes Algorithm</h2>
-
- <p>The algorithm takes a single input variable: an <em>element</em> to be labeled with
- <tref title="blank node identifier">blank node identifiers</tref>.</p>
-
- <ol class="algorithm">
- <li>If <em>element</em> is an <tref>array</tref>, recursively apply this
- algorithm to all its items.</li>
- <li>Otherwise, if <em>element</em> is a <tref>JSON object</tref> with a
- <code>@list</code> member, recursively apply this algorithm to all items
- of the <code>@list</code> member's value.</li>
- <li>Otherwise, if <em>element</em> is a <tref>JSON object</tref>
- <ol class="algorithm">
- <li>For each <em>key</em>-<em>value</em> pair ordered by <em>key</em>
- recursively apply this algorithm to <em>value</em>.</li>
- <li>If <em>element</em> is a <tref>node object</tref> without an <code>@id</code> member,
- create a new <code>@id</code> member and assign it a new
- <tref>blank node identifier</tref> according the
- <a href="#generate-blank-node-identifier">Generate Blank Node Identifier</a> algorithm.</li>
- </ol>
- </li>
- </ol>
-</section>
-
-<section>
- <h2>Generate Blank Node Identifier</h2>
-
- <p>This algorithm is used to generate new
- <tref title="blank node identifier">blank node identifiers</tref> or to relabel existing
- <tref title="blank node identifier">blank node identifiers</tref> with a new one to avoid
- collision by the introduction of new ones. It needs to keep an <em>identifier map</em>,
- a <em>counter</em>, and a <em>prefix</em> between its executions to be able to generate new
- <tref title="blank node identifier">blank node identifiers</tref>. The <em>counter</em>
- is initialized to <code>0</code> and <em>prefix</em> is set to <code>_:t</code> by default.</p>
-
- <p>The algorithm takes a single input variable <em>identifier</em> which might be
- <tref>null</tref>.</p>
-
- <ol class="algorithm">
- <li>If the <em>identifier</em> is not <tref>null</tref> and is in the <em>identifier map</em>,
- return the mapped identifier.</li>
- <li>Otherwise, generate a new <em>blankNodeIdentifier</em> by concatenating <em>prefix</em>
- and <em>counter</em>.</li>
- <li>Increment <em>counter</em> by <code>1</code>.</li>
- <li>If <em>identifier</em> is not <tref>null</tref>, create a new entry in
- <em>identifier map</em> set to <em>blankNodeIdentifer</em>.</li>
- <li>Return <em>blankNodeIdentifier</em>.</li>
- </ol>
-</section>
-
-<section>
- <h2>Compaction Algorithm</h2>
-
- <p>The algorithm takes four input variables: an <tref>active context</tref>,
- an <tref>inverse context</tref>, an <tref>active property</tref>, and an <em>element</em>
- to be compacted. To begin, the <tref>active context</tref> is set to the result of performing
- <a href="#context-processing">Context Processing</a> on the passed <em>context</em>,
- <tref>inverse context</tref> is set to the result of
- <a href="#context-processing">creating an inverse context</a> from the <tref>active context</tref>,
- <tref>active property</tref> is set to <tref>null</tref>, and <em>element</em> is set to
- the result of performing the <a href="#expansion-algorithm">Expansion Algorithm</a>
- on the <tref>JSON-LD input</tref>.</p>
-
- <ol class="algorithm">
- <li>If <em>element</em> is an <tref>array</tref>,
- <ol class="algorithm">
- <li>Initialize a new empty array <em>result</em>.</li>
- <li>Process each item in <em>element</em> recursively using this algorithm,
- passing a copy of the <tref>active context</tref>, <tref>inverse context</tref>,
- and the <tref>active property</tref>. Add each compacted item to <em>result</em>
- unless it is <tref>null</tref>.</li>
- <li>If <em>result</em> has a single item and the
- <code class="idlMemberName"><a href="#widl-JsonLdOptions-compactArrays">compactArrays</a></code>
- option is set to <code>true</code>, return that item; otherwise return
- <em>result</em>.</li>
- </ol>
- </li>
- <li>If <em>element</em> is not a <tref>JSON object</tref> it is already in
- compact form, return it as is.</li>
- <li>If <em>element</em> has an <code>@value</code> or <code>@id</code> member,
- replace <em>element</em> with the result of the
- <a href="#value-compaction">Value Compaction algorithm</a>. If the updated
- <em>element</em> is a <tref>scalar</tref>, return it as it cannot be further
- compacted.</li>
- <li>Initialize a new empty <tref>JSON object</tref> result.</li>
- <li>Process each <em>property</em> and <em>value</em> in <em>element</em> ordered
- by <em>property</em> as follows:
- <ol class="algorithm">
- <li>If <em>property</em> is a JSON-LD <tref>keyword</tref>
- <ol class="algorithm">
- <li>and <em>property</em> equals <code>@id</code>, compact <em>value</em>
- according the rules of the <a href="#iri-compaction-algorithm">IRI Compaction algorithm</a>.</li>
- <li>Otherwise, if <em>property</em> equals <code>@type</code>, compact <em>value</em>
- (or each item of <em>value</em> if it is an <tref>array</tref>) according the rules of the
- <a href="#iri-compaction-algorithm">IRI Compaction algorithm</a> with the
- <em>vocabRelative</em> flag set to <code>true</code>. If <em>value</em> is an
- <tref>array</tref> consisting of just one item, replace <em>value</em> with that item.</li>
- <li>Otherwise, if <em>property</em> equals <code>@graph</code> or <code>@list</code>, compact <em>value</em>
- by recursively invoking this algorithm, passing a copy of the <tref>active context</tref>,
- <tref>inverse context</tref>, and <em>property</em> as <tref>active property</tref>
- ensuring that the result is an <tref>array</tref>.</li>
- <li>Set <tref>active property</tref> to the result of performing
- <a href="#iri-compaction-algorithm">IRI Compaction</a> on <em>property</em>.</li>
- <li>Set the <tref>active property</tref> member of <em>result</em> to <em>value</em>.</li>
- <li>Continue with the next <em>property</em>-<em>value</em> pair from <em>element</em>.</li>
- </li>
- </ol>
- </li>
- <li>If <em>value</em> is an empty <tref>array</tref>,
- <ol class="algorithm">
- <li>set <tref>active property</tref> to the result of performing
- <a href="#iri-compaction-algorithm">IRI Compaction</a> on <em>property</em> with the
- <em>vocabRelative</em> flag set to <code>true</code>.</li>
- <li>If <tref>active property</tref> is a <tref>JSON object</tref>, i.e., it is a
- <tref>property generator</tref>, set <tref>active property</tref> to the result of performing the
- <a href="#find-and-remove-property-generator-duplicates">Find and Remove Property Generator Duplicates</a>
- algorithm passing <em>element</em>, <em>property</em>, <tref>null</tref> for value, the
- <tref>active context</tref>, and <tref>active property</tref>.</li>
- <li>Ensure that <em>result</em> has an <tref>active property</tref> member; if not create it
- and set its value to an empty <tref>array</tref>.</li>
- <li>Continue with the next <em>property</em>-<em>value</em> pair from <em>element</em>.</li>
- </ol>
- </li>
- <li>Otherwise perform the following steps for each <em>item</em> of <em>value</em>:
- <ol class="algorithm">
- <li>Set <tref>active property</tref> to the result of performing
- <a href="#iri-compaction-algorithm">IRI Compaction</a> on <em>property</em> with the
- <em>vocabRelative</em> flag set to <code>true</code>.</li>
- <li>If <tref>active property</tref> is a <tref>JSON object</tref>, i.e., it is a
- <tref>property generator</tref>, set <tref>active property</tref> to the result of performing the
- <a href="#find-and-remove-property-generator-duplicates">Find and Remove Property Generator Duplicates</a>
- algorithm passing <em>element</em>, <em>property</em>, <em>item</em>, the
- <tref>active context</tref>, and <tref>active property</tref>.</li>
- </li>
- <li>If the <tref title="active property">active property's</tref> <tref>container mapping</tref>
- is set to <code>@language</code> or <code>@index</code>
- <ol class="algorithm">
- <li>Unless <em>result</em> has already an <tref>active property</tref> member, create one and
- initialize its value to an empty <tref>JSON object</tref>. This object is called <em>mapObject</em>.</li>
- <li>Set <em>index</em> to the value of the <code>@language</code> or
- <code>@index</code> member of <em>item</em> (depending on the value of the
- <tref title="active property">active property's</tref> <tref>container mapping</tref>).</li>
- <li>First compact <em>item</em> using the <a href="#value-compaction">Value Compaction algorithm</a>
- passing <em>index</em> as <em>containerValue</em>, then compact it by recursively invoking this
- algorithm passing a copy of the <tref>active context</tref>, <tref>inverse context</tref>, and the
- <tref>active property</tref>.</li>
- <li>If no <em>index</em> member exists in the <em>mapObject</em> create one and set its value
- to <em>item</em>; otherwise append <em>item</em> to the <em>index</em> member (converting it to
- an array if it is not one already).</li>
- <li>Continue with the next <em>property</em>-<em>value</em> pair from <em>element</em>.</li>
- </ol>
- </li>
- <li>If <em>item</em> is a <tref>JSON object</tref> having a <code>@list</code> member,
- <ol class="algorithm">
- <li>compact the value of that member by recursively invoking this algorithm passing
- a copy of the <tref>active context</tref>, <tref>inverse context</tref>, and the
- <tref>active property</tref> ensuring that the result is an <tref>array</tref>.</li>
- <li>If the <tref title="active property">active property's</tref> <tref>container mapping</tref>
- is set to <code>@list</code>, set the <tref>active property</tref> member of <em>result</em>
- to the value of <em>item's</em> <code>@list</code> member. If such an member already exists
- in result, raise an <code class="error">compaction to list of lists</code> error; otherwise
- continue with the next <em>property</em>-<em>value</em> pair from <em>element</em>.</li>
- </ol>
- </li>
- <li>If <em>item</em> is a <tref>JSON object</tref>, compact it by recursively
- invoking this algorithm passing a copy of the <tref>active context</tref>,
- <tref>inverse context</tref>, and the <tref>active property</tref>.</li>
- <li>If no <tref>active property</tref> member exists in <em>result</em> create one and set its value
- to <em>item</em>; otherwise append <em>item</em> to the <tref>active property</tref> member
- (converting it to an <tref>array</tref> if it is not one already).</li>
- <li>If the <code class="idlMemberName"><a href="#widl-JsonLdOptions-compactArrays">compactArrays</a></code>
- option is set to <code>false</code> or the <tref title="active property">active property's</tref>
- <tref>container mapping</tref> is set to <code>@list</code> or <code>@set</code>, convert the
- value of the <tref>active property</tref> member of <em>result</em> to an <tref>array</tref> if
- it is not one already.</li>
- </ol>
- </li>
- </ol>
-
- <p>If, after the algorithm outlined above is run, the resulting <em>element</em> is an <tref>array</tref>
- with one or more items, replace it with a new <tref>JSON object</tref> with a single member whose name
- is the result of compacting the value <code>@graph</code> with the
- <a href="#iri-compaction-algorithm">IRI Compaction algorithm</a> and whose value is <em>element</em>. If
- the resulting <em>element</em> is an <tref>array</tref> with zero items, replace it with an empty
- <tref>JSON object</tref>. Finally, if a <em>context</em> has been passed, add a <code>@context</code>
- property to <em>element</em> and set its value to the initially passed <em>context</em>.</p>
-</section>
-
-<section>
- <h2>IRI Compaction Algorithm</h2>
-
- <p>This section defines an algorithm for transforming an <tref>IRI</tref> to a
- <tref>term</tref> or <tref>compact IRI</tref>. If a <em>value</em> is passed
- it is used to choose the best matching <tref>term</tref>.</p>
-
- <p>This algorithm takes three mandatory and three optional parameters. The mandatory
- parameters are the <em>iri</em> to be compacted, an <tref>active context</tref>,
- and an <tref>inverse context</tref>. Optionally it is possible to pass a <em>value</em>,
- and a <em>vocabRelative</em> flag which specifies whether the passed <em>iri</em>
- should be compacted using the <tref title="active context">active context's</tref>
- <tref>vocabulary mapping</tref>, and a base <tref>IRI</tref> which, when passed, is used
- to transform the passed <em>iri</em> to a <tref title="relative IRI">relative IRIs</tref>
- if the <em>vocabRelative</em> flag is set to false (which is its default value).</p>
-
- <p>The algorithm for generating a <tref>compact IRI</tref> is:</p>
-
- <ol class="algorithm">
- <li>Initialize a variable <em>result</em> to <tref>null</tref>.</li>
- <li>If the <em>vocabRelative</em> flag is set to <code>true</code> and an entry for
- <em>iri</em> exists in the <tref>inverse context</tref>, perform the following steps:
- <ol class="algorithm">
- <li>If a <em>value</em> has been passed, perform the following steps:
- <ol class="algorithm">
- <li>Initialize <em>queryPath</em>, which will be used to query the
- <tref>inverse context</tref>, to an empty <tref>array</tref></li>
- <li id="calculate-value-profile-algorithm">Initialize <em>container</em>
- to <code>@set</code>, <em>typeOrLanguage</em>, and <em>typeLanguageValue</em>
- to <tref>null</tref>.</li>
- <li>If <em>value</em> is a <tref>JSON object</tref>
- <ol class="algorithm">
- <li>and it has an <code>@index</code> member, set <em>container</em> to
- <code>@index</code>.</li>
- <li>If <em>value</em> has an <code>@id</code> member, set
- <em>typeOrLanguage</em> to <code>@type</code> and <em>typeLanguageValue</em>
- to <code>@id</code>.</li>
- <li>Otherwise, if <em>value</em> has an <code>@value</code> member,
- <ol class="algorithm">
- <li>and an <code>@type</code> member, set <em>typeOrLanguage</em> to
- <code>@type</code> and <em>typeLanguageValue</em> to the value of the
- <code>@type</code> member of <em>value</em>.</li>
- <li>Otherwise, if it has an <code>@language</code> member, set
- <em>typeOrLanguage</em> to <code>@language</code> and
- <em>typeLanguageValue</em> to the value of the <code>@language</code>
- member of <em>value</em>. If <em>value</em> has no <code>@index</code>
- member, set <em>container</em> to <code>@language</code></li>
- <li>Otherwise, set <em>typeOrLanguage</em> to <code>@language</code> and
- <em>typeLanguageValue</em> to <code>@null</code>.</li>
- </ol>
- </li>
- <li>Otherwise, if <em>value</em> has an <code>@list</code> member,
- <ol class="algorithm">
- <li>If the <code>@list</code> member has at least one item, update
- <em>container</em>, <em>typeOrLanguage</em>, and
- <em>typeLanguageValue</em> by recursively running the steps
- <a href="#calculate-value-profile-algorithm">2.1.2</a> to
- 2.1.3.4 (which will never be true since list of lists are not
- allowed) of this algorithm passing the first item of <em>value's</em>
- <code>@list</code> member as new <em>value</em>.</li>
- <li>If <em>value</em> has no <code>@index</code> member, set
- <em>container</em> to <code>@list</code>.</li>
- <li>Starting from the second item of <em>value's</em> <code>@list</code>
- member, recursively run the steps
- <a href="#calculate-value-profile-algorithm">2.1.2</a> to
- 2.1.3.4 (which will never be true since list of lists are not
- allowed) of this algorithm passing the item as new <em>value</em>. If
- the resulting <em>typeOrLanguage</em> or <em>typeLanguageValue</em>
- differ from the current value of <em>typeOrLanguage</em> or
- <em>typeLanguageValue</em>, set both to <tref>null</tref> and stop
- processing the <code>@list</code> items.</li>
- </ol>
- </li>
- </ol>
- </li>
- <li>If the <em>container</em> equals <code>@list</code>, set the first item of
- <em>queryPath</em> to an <tref>array</tref> consisting of the two elements
- <code>@list</code> and <code>null</code>; otherwise set it to an array
- consisting of three elements where the first element is the value of <em>container</em>
- and the other two elements are <code>@set</code> and <code>@null</code>.</li>
- <li>If <em>typeOrLanguage</em> is <tref>null</tref>, set the second and the the
- third item of <em>queryPath</em> to an <tref>array</tref> consisting of a
- single element <code>@null</code>.</li>
- <li>Otherwise, set the second item of <em>queryPath</em> to an <tref>array</tref>
- consisting of two elements where the first element is the value of
- <em>typeOrLanguage</em> and the second element is <code>@null</code>. Set the
- third item of <em>queryPath</em> to an <tref>array</tref> whose first element
- <em>typeLanguageValue</em> and whose second element is <code>@null</code>.</li>
- <li><a href="#inverse-context-query-algorithm">Query the inverse context</a> and
- store the result in <em>result</em>.</li>
- <li>If <em>result</em> is a a <tref>string</tref> or a <tref>JSON object</tref> with a
- <code>term</code> member, return <em>result</em>.</li>
- </ol>
- </li>
- <li>Otherwise, if the entry for <em>iri</em> in the <tref>inverse context</tref>
- has a <code>term</code> member, return its value.</li>
- </ol>
- </li>
- <li>For each <em>termIri</em>-<em>termDefinition</em> pair in <tref>inverse context</tref>
- sorted in reverse order by <em>termIri</em> the (longest <em>termIri</em> comes first),
- perform the following steps:
- <ol class="algorithm">
- <li>If <em>termDefinition</em> does not have a <code>term</code> member, i.e., it is
- a property generator, continue with the next <em>termIri</em>-<em>termDefinition</em>
- pair from <tref>inverse context</tref>.</li>
- <li>Otherwise, if <em>iri</em> begins with <em>termIri</em> and is longer than
- <em>termIri</em>, generate a <tref>compact IRI</tref> by concatenating the value
- of the <code>term</code> member of <em>termDefinition</em> with a colon
- (<code>:</code>) character and the unmatched part of <em>iri</em>.</li>
- <li>If the resulting <tref>compact IRI</tref> has an entry in the <tref>active context</tref>
- and the <em>vocabRelative</em> flag is set to <code>true</code> or the <tref>IRI mapping</tref>
- does not correspond to <em>iri</em>, continue with the next <em>termIri</em>-<em>termDefinition</em>
- pair from <tref>inverse context</tref> as the <tref>compact IRI</tref> cannot be used.</li>
- <li>Otherwise, if result is <tref>null</tref>, return the <tref>compact IRI</tref>; if it is
- not null, set the <code>term</code> member of <em>result</em> to the <tref>compact IRI</tref>
- and return <em>result</em>.</li>
- </ol>
- </li>
- <li>If the <em>vocabRelative</em> flag is set to <code>false</code> and a base <tref>IRI</tref> has
- been passed, transform <em>iri</em> to a <tref>relative IRI</tref>.</li>
- <li>Otherwise, if the <em>vocabRelative</em> flag is set to <code>true</code>, the
- <tref>active context</tref> has a <tref>vocabulary mapping</tref>, and <em>iri</em>
- begins with the IRI of the <tref>vocabulary mapping</tref> but is longer
- <ol class="algorithm">
- <li>Set <em>vocabIri</em> to the unmatched part of <em>iri</em>.</li>
- <li>If there does not exist an entry for <em>vocabIri</em> in the <tref>active context</tref>,
- return <em>vocabIri</em> if <em>result</em> is <tref>null</tref>; if it is not
- <tref>null</tref> set the <code>term</code> member of <em>result</em> to
- <em>vocabIri</em> and return <em>result</em>.</li>
- </ol>
- </li>
- <li>If <em>result</em> is <tref>null</tref>, return <em>iri</em> as is.</li>
- <li>Otherwise set the <code>term</code> member of <em>result</em> to <em>iri</em> and
- return <em>result</em>.</li>
- </ol>
-</section>
-
-<section>
- <h2>Inverse Context Creation</h2>
-
- <p>An <tref>active context</tref> as produced by the
- <a href="#context-processing">Context Processing</a> algorithm is very
- efficient for <a href="#iri-expansion">expanding</a>
- <tref title="term">terms</tref> and <tref title="compact IRI">compact IRIs</tref>
- to <tref title="IRI">IRIs</tref> but is of limited use for the opposite
- operation: <a href="#iri-compaction-algorithm">IRI compaction</a>. Hence,
- this algorithm introduces the notion of an <tref>inverse context</tref>
- which brings the same efficiency to <a href="#iri-compaction-algorithm">IRI compaction</a>.
- An <tdef>inverse context</tdef> is a tree of <tref title="JSON object">JSON objects</tref>
- which allow to efficiently select a <tref>term</tref> for a <tref>IRI</tref>-value
- pair. Consider the following <tref>context</tref>:</p>
-
- <pre class="example" data-transform="updateExample"
- title="A context containing of two terms and a property generator">
- <!--
- {
- "@context": {
- ****"name"****: "http://xmlns.com/foaf/0.1/name",
- ****"homepage"****: {
- "@id": "http://xmlns.com/foaf/0.1/homepage",
- "@type": "@id"
- },
- ****"gender"****: {
- "@id": [ "http://xmlns.com/foaf/0.1/gender", "http://schema.org/gender" ],
- "@language": "en"
- }
- }
- }
- -->
- </pre>
-
- <p>The corresponding <tref>inverse context</tref> looks as shown below. All entries of
- the <tref>context</tref> above are first indexed by <tref>IRI</tref>, followed by
- their <tref>container mapping</tref>, and finally by their
- <tref title="language mapping">language</tref> or <tref>type mapping</tref>. If a
- specific mapping is not set or <tref>null</tref>, the entry is indexed under the
- respective <code>@null</code> member instead.</p>
-
- <pre class="example" data-transform="updateExample"
- title="The inverse context corresponding to the context above">
- <!--
- {
- "http://xmlns.com/foaf/0.1/homepage": {
- "term": "homepage",
- "@null": {
- "@type": {
- "@id": {
- "term": ****"homepage"****
- }
- }
- }
- },
- "http://xmlns.com/foaf/0.1/gender": {
- "@null": {
- "@language": {
- "en": {
- "propertyGenerators": [ ****"gender"**** ]
- }
- }
- }
- },
- "http://xmlns.com/foaf/0.1/name": {
- "term": "name",
- "@null": {
- "@language": {
- "@null": {
- "term": ****"name"****
- }
- },
- "@null": {
- "@null": {
- "term": ****"name"****
- }
- }
- }
- },
- "http://schema.org/gender": {
- "@null": {
- "@language": {
- "en": {
- "propertyGenerators": [ ****"gender"**** ]
- }
- }
- }
- }
- }
- -->
- </pre>
-
- <p>Please note that the <tref>property generator</tref> <code>gender</code> and the <tref>term</tref>
- <code>name</code> are included twice in <tref>inverse context</tref>. While <code>gender</code>
- is included once for each <tref>IRI</tref> it is mapped to, <code>name</code> is included
- twice since it has neither a <tref>type mapping</tref> nor a <tref>language mapping</tref>.
- It can thus be used for <tref title="string">strings</tref> without an associated language
- (the first entry), or all other (untyped) <tref title="JSON-LD value">values</tref>.</p>
-
- <p>The following algorithm takes an <tref>active context</tref> and returns the corresponding
- <tref>inverse context</tref>.</p>
-
- <ol class="algorithm">
- <li>Set <em>defaultLanguage</em> to <tref title="active context">active context's</tref>
- <tref>default language</tref> if there is one; otherwise set it to <code>@null</code>.</li>
- <li>For each <tref>term definition</tref> in the <tref>active context</tref>
- perform the following steps:
- <ol class="algorithm">
- <li>If the <tref title="term">term's</tref> <tref>IRI mapping</tref> is set to
- <tref>null</tref> continue with the next <tref>term definition</tref>.</li>
- <li>Set <em>container</em> to the value of the <tref title="term">term's</tref>
- <tref>container mapping</tref> or <code>@null</code> if no such mapping exists.</li>
- <li>If the <tref>term</tref> is a <tref>property generator</tref>, set <em>termType</em>
- to <code>propertyGenerators</code>.</li>
- <li>Otherwise set set <em>termType</em> to <code>term</code> and append the
- <tref>term</tref> to the <code>term</code> member of the <tref>JSON object</tref> for
- the <tref title="term">term's</tref> IRI in <tref>inverse context</tref>
- (append <em>term</em> to <code>inverseContext[iri]['term']</code>).</li>
- <li>For each <em>iri</em> mapped to the <tref>term</tref>, perform the following steps:
- <ol class="algorithm">
- <li>If the <tref>term</tref> has a <tref>type mapping</tref> to <em>type</em>,
- append the <tref>term</tref> to
- <code>inverseContext[iri][container]['@type'][type][termType]</code> (e.g.,
- <code>inverseContext['http://...']['@list']['@type']['http://...']['term']</code>).</li>
- <li>Otherwise, if the <tref>term</tref> has a <tref>language mapping</tref> store the
- associated language in <em>language</em>, replacing <tref>null</tref> with
- <code>@null</code>. Then append the <tref>term</tref> to
- <code>inverseContext[iri][container]['@language'][language][termType]</code> (e.g.,
- <code>inverseContext['http://...']['@list']['@language']['de']['term']</code>).</li>
- <li>Otherwise append the <tref>term</tref> to
- <code>inverseContext[iri][container]['@null']['@null'][termType]</code> as well as
- <code>inverseContext[iri][container]['@language'][defaultLanguage][termType]</code>
- to take the <tref>default language</tref> into consideration for terms without
- explicit <tref>language mapping</tref>.</li>
- </ol>
- </li>
- </ol>
- </li>
- <li>Remove all but the shortest and lexicographically least <tref>term</tref> in each
- <code>term</code> member in <tref>inverse context</tref>. The result is thus a single
- <tref>string</tref> value.</li>
- <li>Finally, sort the <tref>array</tref> associated with every <code>propertyGenerators</code> member in
- <tref>inverse context</tref> lexicographically (shortest <tref title="term">terms</tref> come
- first).</li>
- </ol>
-</section>
-
-<section>
- <h2>Inverse Context Query Algorithm</h2>
-
- <p>It is possible that multiple <tref title="term">terms</tref> that differ
- in their <tref title="container mapping">container</tref>,
- <tref title="type mapping">type</tref>, or <tref>language mapping</tref> are
- mapped to the same <tref>IRI</tref>. The purpose of this algorithm is to query
- the <tref>inverse context</tref> to return either the best matching <tref>term</tref>,
- or a list of potential <tref title="property generator">property generators</tref>
- along with a <tref>term</tref> to fall back to if none of the
- <tref title="property generator">property generators</tref> can be applied.</p>
-
- <p>This algorithm takes an <em>inverseContextSubtree</em>, a <em>queryPath</em>
- as generated by the <a href="#iri-compaction-algorithm">IRI Compaction algorithm</a>
- and a <em>level</em> parameter which is initialized to <code>0</code> if nothing else
- is passed. The algorithm returns either a <tref>string</tref> representing the best matching
- <tref>term</tref> or a <tref>JSON object</tref> consisting of a
- <code>propertyGenerators</code> member, containing a sorted <tref>array</tref> of
- potential <tref title="property generator">property generators</tref>,
- and an optional <code>term</code> member containing a <tref>term</tref> to fall back
- to if none of the <tref title="property generator">property generators</tref>
- can be applied.</p>
-
- <ol class="algorithm">
- <li>Initialize <em>result</em> to <tref>null</tref>.</li>
- <li>If <em>level</em> equals <code>3</code>, i.e., the deepest nested
- <tref>JSON object</tref> in the <tref>inverse context</tref> has been reached,
- perform the following steps:
- <ol class="algorithm">
- <li>If <em>inverseContextSubtree</em> has a <code>propertyGenerators</code> member,
- copy that member into a new <tref>JSON object</tref> and store that object in
- <em>result</em>.</li>
- <li>If <em>inverseContextSubtree</em> has a <code>term</code> member and
- <em>result</em> is <tref>null</tref>, return the value of that member;
- otherwise <em>result</em> is a <tref>JSON object</tref>, copy the <code>term</code>
- member into <em>result</em> and return <em>result</em>.</li>
- </ol>
- </li>
- <li>Otherwise, for each <em>entry</em> of the <tref>array</tref> in <em>queryPath's</em>
- <em>level'd</em> position (<code>queryPath[level]</code>), perform the following steps:
- <ol class="algorithm">
- <li>If <em>inverseContextSubtree</em> has no <em>entry</em> member, continue with
- the next <em>entry</em>.</li>
- <li>Otherwise set <em>tmpResult</em> to the result of recursively invoking this
- algorithm passing the <em>entry</em> member of <em>inverseContextSubtree</em> as
- new <em>inverseContextSubtree</em>, <em>queryPath</em>, and <em>level</em> + <code>1</code>
- as new <em>level</em>.</li>
- <li>If <em>tmpResult</em> is a <tref>string</tref> and <em>result</em> is
- <tref>null</tref>, return <em>tmpResult</em>; otherwise, if <em>result</em> is
- not <tref>null</tref>, transform <em>tmpResult</em> to a <tref>JSON object</tref>
- whose <code>propertyGenerators</code> member is set to an empty <tref>array</tref>
- and whose <code>term</code> member is set to <em>tmpResult</em>.</li>
- <li>If <em>result</em> is <tref>null</tref>, replace it with <em>tmpResult</em>.</li>
- <li>Otherwise, append each item of the <code>propertyGenerator</code> member of
- <em>tmpResult</em> to the <code>propertyGenerator</code> member of <em>result</em>
- unless it is already in <em>result's</em> member. If <em>result</em> has no
- <code>term</code> member but <em>tmpResult</em> does, copy <em>tmpResult's</em>
- <code>term</code> member into <em>result</em>.</li>
- </ol>
- </li>
- <li>Return <em>result</em>.</li>
- </ol>
-</section>
-
-<section>
- <h2>Value Compaction</h2>
-
- <p>Expansion transforms all values into <tref>expanded form</tref>in JSON-LD. This algorithm
- does the opposite, it compacts an algorithm according the <tref>term definition</tref>
- of the passed <tref>active property</tref>. After the application of this algorithm a value
- is said to be in <tdef>compacted form</tdef>.</p>
-
- <p>This algorithm takes a <em>value</em>, an <tref>active context</tref>, an
- <tref>inverse context</tref>, an <tref>active property</tref>, and an optional
- <em>containerValue</em>.</p>
-
- <ol class="algorithm">
- <li>If a <em>containerValue</em> has been passed, the <tref>active property</tref> has a
- <tref>container mapping</tref> set to <code>@index</code> and <em>value</em>
- has an <code>@index</code> member which equals <em>containerValue</em>, remove that member.</li>
- <li>If <em>value</em> is a <tref>JSON object</tref> having a single member <code>@id</code>,
- return the result of performing <a href="#iri-compaction-algorithm">IRI Compaction</a> on that
- member's value.</li>
- <li>Otherwise, if <em>value</em> is a <tref>JSON object</tref> having a <code>@value</code>
- member, perform the following steps:
- <ol class="algorithm">
- <li>If the <tref>active property</tref> has a <tref>type mapping</tref> and <em>value</em>
- has a corresponding <code>@type</code> member, remove the <code>@type</code> member
- from <em>value</em>.</li>
- <li>Otherwise, if the <tref>active property</tref> has a <tref>language mapping</tref> and
- <em>value</em> has a corresponding <code>@language</code> member, remove the
- <code>@language</code> member from <em>value</em>.</li>
- <li>Otherwise, if a <em>containerValue</em> has been passed, the <tref>active property</tref>
- has a <tref>container mapping</tref> set to <code>@language</code>, and <em>value</em> has
- a <code>@language</code> member which equals <em>containerValue</em>, remove the
- <code>@language</code> member from <em>value</em>.</li>
- <li>Otherwise, if the <tref>active context</tref> has a <tref>default language</tref>
- <ol class="algorithm">
- <li>and the <em>value</em> has a corresponding <code>@language</code> member, remove the
- <code>@language</code> member from <em>value</em>.</li>
- <li>Otherwise, or if the value of <em>value's</em> <code>@value</code> member is a
- <tref>string</tref>, return <em>value</em>.</li>
- </ol>
- </li>
- <li>If <em>value</em> has just a <code>@value</code> member, return the value of that
- member.</li>
- </ol>
- </li>
- <li>Return <em>value</em> as is.</li>
- </ol>
-</section>
-
-<section>
- <h2>Find and Remove Property Generator Duplicates</h2>
-
- <p>This algorithm checks if a specific value exists for all <tref title="IRI">IRIs</tref>
- associated with a <tref>property generator</tref> and if so, it removes them. The
- algorithm takes five parameters: <em>element</em>, <em>property</em>, <em>value</em>,
- <tref>active context</tref>, <tref>active property</tref>.</p>
-
- <ol class="algorithm">
- <li>For each item <em>propertyGenerator</em> of the <tref>array</tref> which is the
- value of the <code>propertyGenerators</code> member of <tref>active property</tref> perform
- the following steps:
- <ol class="algorithm">
- <li>Check that a member exists for each <tref>IRI</tref> associated with the
- <em>propertyGenerator</em>. If <em>value</em> is not <tref>null</tref> also check
- whether each of those members contains <em>value</em>. Values are considered to be equal
- if they are of the same type and have the same value(s); <tref title="node object">node objects</tref>
- are considered to be equal if all members match, except if no <code>@id</code> member exists (i.e., it is
- an unlabeled <tref>blank node</tref>, in that case <tref title="node object">node objects</tref> are never
- considered to be equal.
- </li>
- <li>If that's not the case, continue with the next <em>propertyGenerator</em>.</li>
- <li>Otherwise, remove <em>value</em> from every member. If the resulting value
- of a member is an empty <tref>array</tref>, remove the member altogether
- from <em>element</em>.</li>
- <li>Return <em>propertyGenerator</em>.</li>
- </ol>
- </li>
- <li>Return the value of the <code>term</code> member of <tref>active property</tref>
- since no matching <tref>property generator</tref> has been found.</li>
- </ol>
-</section>
-
-<section>
- <h2>Flattening Algorithm</h2>
-
- <p>The algorithm takes two input variables, an <em>element</em> to flatten and a
- <em>context</em> used to compact the flattened document.</p>
-
- <ol class="algorithm">
- <li>Expand <em>element</em> according the
- <a href="#expansion-algorithm">Expansion algorithm</a>.</li>
- <li>Generate a <em>nodeMap</em> according the
- <a href="#node-map-generation">Node Map Generation algorithm</a>.</li>
- <li>Let <em>defaultGraph</em> be the value of the <code>@default</code> member of
- <em>nodeMap</em>; a <tref>JSON object</tref> representing the <tref>default graph</tref>.</li>
- <li>For each other <em>graphName</em>-<em>graph</em> pair in <em>nodeMap</em>
- perform the following steps:
- <ol class="algorithm">
- <li>If <em>defaultGraph</em> does not have a <em>graphName</em> member, create
- one and initialize its value to a <tref>JSON object</tref> consisting of an
- <code>@id</code> member whose value is set to <em>graphName</em>.</li>
- <li>Add an <code>@graph</code> member set to an empty <tref>array</tref>
- (referred to as <em>nodes</em>) to the <tref>JSON object</tref> which is the
- value of the <em>graphName</em> member of <em>nodeMap</em>.</li>
- <li>For each <em>id</em>-<em>node</em> pair in <em>graph</em> ordered by <em>id</em>,
- add <em>node</em> to the <em>nodes</em> <tref>array</tref>.</li>
- </ol>
- </li>
- <li>Initialize an empty <tref>array</tref> flattened.</li>
- <li>For each <em>id</em>-<em>node</em> pair in <em>defaultGraph</em> ordered by <em>id</em>,
- add <em>node</em> to <em>flattened</em>.</li>
- <li>If <em>context</em> equals <tref>null</tref>, return <em>flattened</em>.</li>
- <li>Otherwise, return the result of compacting <em>flattened</em> according the
- <a href="#compaction-algorithm">Compaction algorithm</a> passing <em>context</em>
- ensuring that the compaction result uses the <code>@graph</code> keyword (or its alias)
- at the top-level, even if the context is empty or if there is only one element to
- put in the <code>@graph</code> <tref>array</tref>. This ensures that the returned
- document has a deterministic structure.</li>
- </ol>
-</section>
-
-<section>
- <h2>Node Map Generation</h2>
-
- <p>This algorithm creates a <tref>JSON object</tref> <em>nodeMap</em> holding an indexed
- representation of the <tref title="JSON-LD graph">graphs</tref> and <tref title="node">nodes</tref>
- represented in the passed, expanded document. All <tref title="node">nodes</tref> that are not
- uniquely identified by an IRI get assigned a (new) <tref>blank node identifier</tref>.
- The resulting <em>nodeMap</em> will have a member for every graph in the document whose
- value is another object with a member for every <tref>node</tref> represented in the document.
- The default graph is stored under the <code>@default</code> member, all other graphs are
- stored under their graph name</tref>.</p>
-
- <p>The algorithm takes as input an expanded JSON-LD document <em>element</em> and a reference to
- a <tref>JSON object</tref> <em>nodeMap</em>. Furthermore it has the optional parameters
- <tref>active graph</tref> (which defaults to <code>@default</code>), an <tref>active subject</tref>,
- <tref>active property</tref>, and a reference to a <tref>JSON object</tref> <em>list</em>. The
- <em>nodeMap</em> must be initialized to a <tref>JSON object</tref> consisting of a single member
- whose name corresponds with <tref>active graph</tref> and whose value is an empty <tref>JSON object</tref>.</p>
-
- <ol class="algorithm">
- <li>If <em>element</em> is an array, process each entry in <em>element</em> recursively, using this algorithm
- and return.</li>
- <li>Otherwise <em>element</em> is a <tref>JSON object</tref>. Let <em>activeGraph</em> be the
- <tref>JSON object</tref> which is the value of the <tref>active graph</tref> member of
- <em>nodeMap</em>.</li>
- <li>If it has an <code>@type</code> member, perform for each <em>item</em> the following
- steps:
- <ol class="algorithm">
- <li>If <em>item</em> is a <tref>blank node identifier</tref>, replace it with a
- <a href="#generate-blank-node-identifier">new blank node identifier</a>.</li>
- <li>If <em>activeGraph</em> has no member <em>item</em>, create it and initialize its
- value to a <tref>JSON object</tref> consisting of a single member <code>@id</code>
- with the value <em>item</em>.</li>
- </ol>
- </li>
- <li>If <em>element</em> has an <code>@value</code> member, perform the following steps:
- <ol class="algorithm">
- <li>If no <em>list</em> has been passed, merge <em>element</em> into the
- <tref>active property</tref> member of the <tref>active subject</tref> in
- <em>activeGraph</em>.</li>
- <li>Otherwise, append <em>element</em> to the <code>@list</code> member of <em>list</em>.</li>
- </ol>
- </li>
- <li>Otherwise, if <em>element</em> has an <code>@list</code> member, perform
- the following steps:
- <ol class="algorithm">
- <li>Initialize a new <tref>JSON object</tref> <em>result</em> having a single member
- <code>@list</code> whose value is initialized to an empty <tref>array</tref>.</li>
- <li>Recursively call this algorithm passing the value of <em>element's</em>
- <code>@list</code> member as new <em>element</em> and <em>result</em> as <em>list</em>.</li>
- <li>If <tref>active property</tref> equals <tref>null</tref> or <code>@graph</code>,
- <a href="#generate-blank-node-identifier">generate a blank node identifier</a> <em>id</em>
- and store <em>result</em> as value of the member <em>id</em> in <em>activeGraph</em>.</li>
- <li>Otherwise, add <em>result</em> to the the value of the <tref>active property</tref> member
- of the <tref>active subject</tref> in <em>activeGraph</em>.</li>
- </ol>
- </li>
- <li>Otherwise <em>element</em> is a <tref>node object</tref>, perform the following
- steps:
- <ol class="algorithm">
- <li>If <em>element</em> has an <code>@id</code> member, store its value in <em>id</em> and remove
- the member from <em>element</em>. If <em>id</em> is a <tref>blank node identifier</tref>, replace it with
- <a href="#generate-blank-node-identifier">a new blank node identifier</a>.</li>
- <li>Otherwise <a href="#generate-blank-node-identifier">generate a new blank node identifier</a>
- and store it as <em>id</em>.</li>
- <li>If <em>activeGraph</em> does not contain a member <em>id</em>, create one and initialize
- it to a <tref>JSON object</tref> consisting of a single member <code>@id</code> whose
- value is set to <em>id</em>.</li>
- <li>If <tref>active property</tref> is not <tref>null</tref>, perform the following steps:
- <ol class="algorithm">
- <li>Create a new <tref>JSON object</tref> <em>reference</em> consisting of a single member
- <code>@id</code> whose value is <em>id</em>.</li>
- <li>If no <em>list</em> has been passed, merge <em>element</em> into the
- <tref>active property</tref> member of the <tref>active subject</tref> in
- <em>activeGraph</em>.</li>
- <li>Otherwise, append <em>element</em> to the <code>@list</code> member of <em>list</em>.</li>
- </ol>
- </li>
- <li>If <em>element</em> has an <code>@type</code> member, merge each value into the <code>@type</code>
- of <tref>active subject</tref> in <em>activeGraph</em>. Then remove the <code>@type</code> member
- from <em>element</em>.</li>
- <li>If <em>element</em> has an <code>@index</code> member, set the <code>@index</code>
- of <tref>active subject</tref> in <em>activeGraph</em> to its value. If such a member already
- exists in <tref>active subject</tref> and has a different value, raise a
- <code class="error">conflicting indexes</code> error. Otherwise continue and remove the
- <code>@index</code> from <em>element</em>.</li>
- <li>If <em>element</em> has an <code>@graph</code> member, recursively invoke this algorithm passing
- the value of the <code>@graph</code> member as new <em>element</em> and <em>id</em> as new
- <tref>active subject</tref>. Then remove the <code>@graph</code> member from <em>element</em>.</li>
- <li>Finally for each <em>property</em>-<em>value</em> pair in <em>element</em> ordered by
- <em>property</em> perform the following steps:
- <ol class="algorithm">
- <li>If no <em>property</em> member exists in the <tref>JSON object</tref> which is the
- value of the <em>id</em> member of <em>activeGraph</em> create the member and initialize
- its value to an empty <tref>array</tref>.</li>
- <li>Recursively invoke this algorithm passing <em>value</em> as new <em>element</em>, <em>id</em>
- as new <tref>active subject</tref>, and <em>property</em> as new <tref>active property</tref>.</li>
- </ol>
- </li>
- </ol>
- </li>
- </ol>
-</section>
-
- <section>
- <h2>RDF Conversion Algorithms</h2>
-
- <p>This section describes an algorithms to transform JSON-LD documents to an array of
- RDF <tref title="quad">quads</tref> and vice-versa. Note that many uses of JSON-LD
- may not require generation of RDF.</p>
-
- <p>The processing algorithms described in this section are provided in order to demonstrate
- how one might implement a JSON-LD to RDF processor. Conformant implementations are only
- required to produce the same type and number of <tref title="quad">quads</tref> but are
- not required to implement the algorithm exactly as described.</p>
-
- <p class="issue">This algorithm hasn't been updated yet.</p>
-
- <section>
- <h3>Convert to RDF Algorithm</h3>
- <p>
- The algorithm below is designed for in-memory implementations with random access to <tref>JSON object</tref> elements.
- </p>
- <p>
- A conforming JSON-LD processor implementing RDF conversion MUST implement a
- processing algorithm that results in the same set of RDF <tref title="quad">quads</tref> that the following
- algorithm generates.
- </p>
-
- <p>The algorithm takes four input variables: a <em>element</em> to be converted, an
- <tref>active subject</tref>, <tref>active property</tref> and <tref>graph name</tref>.
- To begin, the <tref>active subject</tref>, <tref>active property</tref> and <tref>graph name</tref>
- are set to <tref>null</tref>, and <em>element</em> is
- set to the result of performing the <a href="#expansion-algorithm">Expansion Algorithm</a> on
- the <tref>JSON-LD input</tref> which is expected to be a a well-formed JSON-LD document as defined in [[!JSON-LD]].
- This removes any existing context to allow the given context to be cleanly applied.</p>
-
- <ol class="algorithm">
- <li id="processing-step-associative">
- If <em>element</em> is a <tref>JSON object</tref>, perform the following steps:
- <ol class="algorithm">
- <li>Set <tref>active object</tref> to <tref>null</tref>.</li>
- <li>
- If <em>element</em> has a <code>@value</code> property:
- <ol class="algorithm">
- <li>If the value of <code>@value</code> is a <tref>number</tref>, set the
- <tref>active object</tref> to a <tref>typed value</tref> using a <tref>canonical lexical form</tref>
- of the value as defined in the section <a href="#data-round-tripping">Data Round Tripping</a>.
- Set datatype to the value of the <code>@type</code> property if it exists, otherwise
- either <code>xsd:integer</code> or <code>xsd:double</code>, depending
- on if the value contains a fractional and/or an exponential component.</li>
- <li>Otherwise, if the value of <code>@value</code> is <strong>true</strong> or <strong>false</strong>,
- set the <tref>active object</tref> to a <tref>typed value</tref> created from the
- <tref>canonical lexical form</tref> of the value. Set datatype to the value of the <code>@type</code>
- property if it exists, otherwise <code>xsd:boolean</code>.</li>
- <li>
- Otherwise, if <em>element</em> contains a <code>@type</code> property, set the
- <tref>active object</tref> to a <tref>typed value</tref>.
- </li>
- <li>
- Otherwise, if <em>element</em> contains a <code>@language</code> property, set the
- <tref>active object</tref> to a <tref>language-tagged string</tref>.
- </li>
- <li>
- Otherwise, set the <tref>active object</tref> to a <tref>typed value</tref>
- using <code>xsd:string</code> as the datatype.
- </li>
- </ol>
- </li>
- <li>
- If <em>element</em> has a <code>@list</code> property the value MUST be an <tref>array</tref>.
- Process its value as a list as described in <a href="#list-conversion">List Conversion</a> using
- the return value as the <tref>active object</tref>
- </li>
- <li>If <tref>active object</tref> is not <tref>null</tref>:
- <ol class="algorithm">
- <li>If neither <tref>active subject</tref> nor <tref>active property</tref> are <tref>null</tref>,
- generate a <tref>Quad</tref>
- representing <tref>active subject</tref>, <tref>active property</tref>,
- <tref>active object</tref>, and <tref>graph name</tref>.</li>
- <li>Return <tref>active object</tref>.</li>
- </ol>
- </li>
- <li id="processing-step-subject">If <em>element</em> has a <code>@id</code> property,
- the value MUST be a <tref>string</tref>, set the <tref>active subject</tref> to the previously
- expanded value (either a <tref>blank node</tref> or an <tref>IRI</tref>).</li>
- <li>
- Otherwise, if <em>element</em> does not have a <code>@id</code> property, set the <tref>active
- subject</tref> to newly generated <tref>blank node</tref>.</li>
- <li>
- Process each <em>property</em> and <em>value</em> in <em>element</em>, ordered by
- <em>property</em>, as follows:
- <ol class="algorithm">
- <li>
- If <em>property</em> is <code>@type</code>, set the <tref>active property</tref>
- to <code>rdf:type</code>.
- </li>
- <li>Otherwise, if <em>property</em> is <code>@graph</code>,
- process <em>value</em> algorithm recursively, using <tref>active subject</tref> as <tref>graph name</tref>
- and null values for <tref>active subject</tref> and <tref>active property</tref> and then
- proceed to next property.</li>
- <li>Otherwise, if <em>property</em> is a <tref>keyword</tref>, skip this step.</li>
- <li>Otherwise, set <tref>active property</tref> to the <tref>expanded IRI form</tref> of <em>property</em>.</li>
- <li>Process <em>value</em> recursively using this algorithm, passing copies of
- <tref>active subject</tref>, <tref>active property</tref> and <tref>graph name</tref>.
- </li>
- </ol>
- </li>
- <li>
- Set <tref>active object</tref> to <tref>active subject</tref>.
- </li>
- </ol>
- </li>
-
- <li>Otherwise, if <em>element</em> is an <tref>array</tref>, process each value in the <tref>array</tref>
- as follows, process <em>element</em> recursively using this algorithm, using copies of
- <tref>active subject</tref>, <tref>active property</tref>, and <tref>graph name</tref>.</li>
-
- <li>Otherwise, if <em>element</em> is a <tref>string</tref>, then the <tref>active property</tref>
- must be <code>rdf:type</code> so set the <tref>active object</tref> to an <tref>IRI</tref>.</li>
-
- <li>If any of these steps created an <tref>active object</tref> and neither <tref>active subject</tref>
- nor <tref>active property</tref> are <tref>null</tref>, generate a <tref>Quad</tref> using
- <tref>active subject</tref>,<tref>active property</tref>, <tref>active object</tref> and
- <tref>graph name</tref>.
- </li>
- <li>Return <tref>active object</tref>.</li>
- </ol>
- </section>
-
- <section id="list-conversion">
- <h3>List Conversion</h3>
-
- <p>List Conversion is the process of taking an <tref>array</tref> of values and adding them to a newly
- created <cite><a href="http://www.w3.org/TR/rdf-schema/#ch_collectionvocab">RDF Collection</a></cite> (see
- [[!RDF-SCHEMA]]) by linking each element of the list using <code>rdf:first</code> and <code>rdf:next</code>,
- terminating the list with <code>rdf:nil</code> using the following sequence:</p>
- <p>The algorithm is invoked with an <tref>array</tref> <em>array</em>, the <tref>active property</tref>
- and returns a value to be used as an <tref>active object</tref> in the calling location.</p>
- <div class="note">This algorithm does not support lists containing lists.</div>
-
- <p class="issue">This algorithm hasn't been updated yet.</p>
-
- <ol class="algorithm">
- <li>
- If <em>array</em> is empty return <code>rdf:nil</code>.
- </li>
- <li>
- Otherwise, generate a <tref>Quad</tref> using using the <tref>active subject</tref>, <tref>active property</tref>
- and a newly generated <tref>blank node</tref> identified as <em>first <tref>blank node</tref></em>.
- </li>
- <li>
- For each element in <em>array</em> other than the last element:
- <ol class="algorithm">
- <li>Create a processor state using
- <em>first blank node</em> as the <tref>active subject</tref>, and
- <code>rdf:first</code> as the <tref>active property</tref>.
- <ol class="algorithm">
- <li>Process the value starting at <a href="#processing-step-associative">Step 1</a>.</li>
- <li>Proceed using the previous <tref>processor state</tref>.</li>
- </ol>
- </li>
- <li>Unless this is the last element in <em>array</em>, generate a new <tref>blank node</tref> identified as
- <em>rest blank node</em>, otherwise use <code>rdf:nil</code>.</li>
- <li>Generate a new <tref>Quad</tref> using <em>first blank node</em>,
- <code>rdf:rest</code> and <em>rest blank node</em>.</li>
- <li>Set <em>first blank node</em> to
- <em>rest blank node</em>.</li>
- <li>Return <em>first blank node</em>.</li>
- </ol>
- </li>
- </ol>
- </section>
-
- <section>
- <h2>Convert from RDF Algorithm</h2>
- <p>In some cases, data exists natively in the form of triples or or <tref title="quad">quads</tref>;
- for example, if the data was originally represented in an RDF graph or triple/quad store. This
- algorithm is designed to simply translate an array of <tref title="quad">quads</tref> into a
- JSON-LD document.</p>
- <p>When expanding <tref title="typed value">typed values</tref> having a datatype of <code>xsd:string</code>,
- the <code>@type</code> MUST NOT be set to <code>xsd:string</code> and the resulting value
- MUST have only an <code>@value</code> property.</p>
-
- <p>The conversion algorithm takes a single parameter <em>input</em> in the form of an
- array of <tref>Quad</tref> representations.</p>
-
- <p class="issue">This algorithm hasn't been updated yet.</p>
-
- <ol class="algorithm">
- <li id="new_graph">Construct <em>defaultGraph</em> as a <tref>JSON object</tref>
- containing <em>nodes</em> and <em>listMap</em>, each an empty <tref>JSON object</tref>.</li>
- <li>Construct <em>graphs</em> as a <tref>JSON object</tref> containing <em>defaultGraph</em>
- identified by
- an empty <tref>string</tref>.</li>
- <li>For each <tref>quad</tref> in <em>input</em>:
- <ol class="algorithm">
- <li>Set <em>graph</em> to the entry in <em>graphs</em> identified
- by <em>name</em>, initializing it to a new entry using the mechanism
- described in <a href="#new_graph">Step 1</a>.</li>
- <li>If <em>property</em> is <code>rdf:first</code>,
- use the entry in <em>graph.listMap</em> indexed by <em>subject</em>,
- initializing it to a new <tref>JSON object</tref> if nesessary. Represent
- <em>object</em> in <tref>expanded form</tref>, as described in
- <a href="#value-expansion">Value Expansion</a>. Add the
- resulting <em>object representation</em> to the entry indexed by
- <em>first</em>, and skip to the next <tref>quad</tref>.</li>
- <li>If <em>property</em> is <code>rdf:rest</code>:
- <ol class="algorithm">
- <li>If <em>object</em> is a <tref>blank node</tref>, use the entry in
- <em>graph.listMap</em> indexed by <em>subject</em>, initializing it
- to a new <tref>JSON object</tref> if necessary. Add the <em>nominalValue</em> of
- <em>object</em> to the entry indexed by <em>rest</em>.
- </li>
- <li>Skip to the next <tref>quad</tref>.</li>
- </ol>
- </li>
- <li>If <em>name</em> is not <tref>null</tref>, and <em>defaultGraph.nodes</em>
- does not contain an entry for <em>name</em>,
- create a new entry for <em>name</em> from a new
- <tref>JSON object</tref> with key/value pair of <code>@id</code> and
- <em>name</em> represented in <tref>expanded IRI form</tref>.</li>
- <li>Set <em>value</em> as the entry from <em>graph.nodes</em> for
- <em>subject</em>, initializing it to a new
- <tref>JSON object</tref> with key/value pair of <code>@id</code> and
- <em>subject</em> represented in <tref>expanded IRI form</tref> if necessary.</li>
- <li>If <em>property</em> is <code>rdf:type</code>, <em>object</em> is not a <tref>JSON-LD value</tref>, and the
- <code class="idlMemberName"><a href="#widl-JsonLdOptions-useRdfType">useRdfType</a></code>
- option is not present or <tref>false</tref>:
- <ol class="algorithm">
- <li>Append <em>object</em> represented in <tref>expanded IRI form</tref> to the array value for the
- key <code>@type</code>, creating an entry in <em>value</em> if necessary.</li>
- </ol>
- </li>
-
- <li>Otherwise, if <em>object</em> is a <tref>typed value</tref> and the
- <code class="idlMemberName"><a href="#widl-JsonLdOptions-useNativeTypes">useNativeTypes</a></code>
- option is set to <tref>true</tref>:
- <ol class="algorithm">
- <li>Generate a <em>converted value</em>:
- <ol class="algorithm">
- <li>If the literal's type is <code>xsd:boolean</code>, the
- <em>converted value</em> is <tref>true</tref> if the literal
- matches the value <code>true</code> or <code>false</code> if
- the literal matches the value <code>false</code>.</li>
- <li>If the literal's type is <code>xsd:integer</code> or
- <code>xsd:double</code>, try to convert the literal to a
- JSON <tref>number</tref>. If the conversion is successful,
- store the result in <em>converted value</em>, otherwise
- set <em>converted value</em> to <em>value</em>.</li>
- <li>Otherwise, do not perform a conversion. Set
- the <em>converted value</em> to the <em>value</em>.</li>
- </ol>
- </li>
- <li>Append the <em>converted value</em> to the array value for the
- key, creating an entry in <em>value</em> if necessary.</li>
- </ol>
- </li>
-
- <li>Otherwise, if <em>object</em> is <code>rdf:nil</code>:
- <ol class="algorithm">
- <li>Let <em>key</em> be <em>property</em> expressed in <tref>expanded IRI form</tref>.</li>
- <li>Append an empty <code>@list</code> representation to the array value for
- <em>key</em>, creating an entry in <em>value</em> if necessary.</li>
- </ol>
- </li>
- <li>Otherwise,
- <ol class="algorithm">
- <li>Let <em>key</em> be <em>property</em> expressed in <tref>expanded IRI form</tref> and let
- <em>object representation</em>
- be <em>object</em> represented in <tref>expanded form</tref> as described in
- <a href="#value-expansion">Value Expansion</a>.</li>
- <li>If <em>object</em> is a <tref>blank node</tref>,
- use the entry in <em>graph.listMap</em> indexed by <em>object</em>,
- initializing it to a new <tref>JSON object</tref> if nesessary.
- Add an entry for <em>head</em> with <em>object representation</em>.</li>
- <li>Append <em>object representation</em> to the array value for
- <em>key</em>, creating an entry in <em>value</em> if necessary.</li>
- </ol>
- </li>
- </ol>
- </li>
- <li>For each <em>name</em> and <em>graph</em> in <em>graphs</em>:
- <ol class="algorithm">
- <li>For each <em>subject</em> and <em>entry</em> in <em>graph</em>
- where <em>entry</em> has both <em>head</em> and <em>first</em> keys:
- <ol class="algorithm">
- <li>Set <em>value</em> to the value of <em>head</em> in <em>entry</em>.</li>
- <li>Remove the entry for <code>@id</code> in <em>value</em>.</li>
- <li>Add an entry to <em>value</em> for <code>@list</code> initialized to a new array
- containing the value of <em>first</em> from <em>entry</em>.</li>
- <li>While <em>entry</em> has a key for <em>rest</em>:
- <ol class="algorithm">
- <li>Set <em>entry</em> to the value of <em>graph.listMap</em> for <em>entry.rest</em>.</li>
- <li>Add the value for <em>entry.first</em> to the list array.</li>
- </ol>
- </li>
- </ol>
- </li>
- </ol>
- </li>
- <li>Create <em>array</em> as an empty <tref>array</tref>.</li>
- <li>For each <em>subject</em> and <em>entry</em> in <em>defaultGraph.nodes</em>
- ordered by <em>subject</em>:
- <ol class="algorithm">
- <li>Add <em>entry</em> to <em>array</em>.</li>
- <li>If <em>graphs</em> has an entry for <em>subject</em>, add a property
- <code>@graph</code> in <em>entry</em> containing the ordered entries
- from <em>graphs[subject].nodes</em>.</li>
- </ol>
- </li>
- <li>Return <em>array</em> as the result.</li>
- </ol>
- </section>
-
- <section>
- <h3>Data Round Tripping</h3>
-
- <p>When <a href="#rdf-conversion">converting JSON-LD to RDF</a> JSON-native types such as
- <em>numbers</em> and <em>booleans</em> are automatically coerced to <strong>xsd:integer</strong>,
- <strong>xsd:double</strong>, or <strong>xsd:boolean</strong>. Implementers MUST ensure that the
- result is in <tref>canonical lexical form</tref>. A
- <tdef>canonical lexical form</tdef> is a set of literals from among the valid set of literals for
- a datatype such that there is a one-to-one mapping between the <tref>canonical lexical form</tref> and a value
- in the value space as defined in [[!XMLSCHEMA11-2]]. In other words, every value MUST be converted
- to a deterministic <tref>string</tref> representation.</p>
-
- <p>The canonical lexical form of an <em>integer</em>, i.e., a number without fractions
- or a number coerced to <strong>xsd:integer</strong>, is a finite-length sequence of decimal
- digits (<code>0-9</code>) with an optional leading minus sign; leading zeroes are prohibited.
- To convert the number in JavaScript, implementers can use the following snippet of code:</p>
-
- <pre class="example" data-transform="updateExample"
- title="Sample integer serialization implementation in JavaScript">
- <!--
- (value).toFixed(0).toString()
- -->
- </pre>
-
- <p>The canonical lexical form of a <em>double</em>, i.e., a number with fractions
- or a number coerced to <strong>xsd:double</strong>, consists of a mantissa followed by the
- character "E", followed by an exponent. The mantissa MUST be a decimal number. The exponent
- MUST be an integer. Leading zeroes and a preceding plus sign (<code>+</code>) are prohibited
- in the exponent. If the exponent is zero, it must be indicated by <code>E0</code>.
- For the mantissa, the preceding optional plus sign is prohibited and the decimal point is
- required. Leading and trailing zeroes are prohibited subject to the following: number
- representations must be normalized such that there is a single digit which is non-zero to the
- left of the decimal point and at least a single digit to the right of the decimal point unless
- the value being represented is zero. The canonical representation for zero is <code>0.0E0</code>.
- <strong>xsd:double</strong>'s value space is defined by the IEEE double-precision 64-bit
- floating point type [[!IEEE-754-1985]]; in JSON-LD the mantissa is rounded to 15 digits after the
- decimal point.</p>
-
- <p>To convert the number in JavaScript, implementers can use the following snippet of code:</p>
-
- <pre class="example" data-transform="updateExample"
- title="Sample floating point number serialization implementation in JavaScript">
- <!--
- (value).toExponential(15).replace(/(\d)0*e\+?/,'$1E')
- -->
- </pre>
-
- <p class="note">When data such as decimals need to be normalized, JSON-LD authors should
- not use values that are going to undergo automatic conversion. This is due to the lossy nature
- of <strong>xsd:double</strong> values. Authors should instead use the expanded object form to
- set the canonical lexical form directly.</p>
-
- <p>The canonical lexical form of the <em>boolean</em> values <code>true</code> and <code>false</code>
- are the strings <strong>true</strong> and <strong>false</strong>.</p>
-
- <p>When JSON-native <tref>number</tref>s, are type coerced, lossless data round-tripping can not
- be guaranted as rounding errors might occur. Additionally, only literals typed as
- <strong>xsd:integer</strong>, <strong>xsd:double</strong>, and <strong>xsd:boolean</strong> are
- automatically converted back to their JSON-native counterparts in when
- <a href="#rdf-conversion">converting from RDF</a>.</p>
-
- <p>Some JSON serializers, such as PHP's native implementation in some versions,
- backslash-escape the forward slash character. For example, the value
- <code>http://example.com/</code> would be serialized as <code>http:\/\/example.com\/</code>.
- This is problematic as other JSON parsers might not understand those escaping characters.
- There is no need to backslash-escape forward slashes in JSON-LD. To aid interoperability
- between JSON-LD processors, a JSON-LD serializer MUST NOT backslash-escape forward slashes.</p>
- </section>
- </section>
-</section>
-
-<section>
- <h2>The Application Programming Interface</h2>
-
- <p>This API provides a clean mechanism that enables developers to convert
- JSON-LD data into a a variety of output formats that are easier to work
- with in JavaScript. If a JavaScript JSON-LD API is provided, the entirety
- of the following API MUST be implemented.</p>
-
- <section>
- <h3>JsonLdProcessor</h3>
-
- <p>The JSON-LD Processor interface is the high-level programming structure
- that developers use to access the JSON-LD transformation methods.</p>
-
- <p>It is important to highlight that conformant <tref title="JSON-LD Processor">JSON-LD processors</tref>
- MUST NOT modify the input parameters.</p>
-
- <dl title="[Constructor] interface JsonLdProcessor" class="idl">
-
- <dt>void expand()</dt>
- <dd>
- <a href="#expansion">Expands</a> the given <code>input</code> according to
- the steps in the <a href="#expansion-algorithm">Expansion Algorithm</a>.
-
- <dl class="parameters">
- <dt>(object or object[] or DOMString) input</dt>
- <dd>The JSON-LD object or array of JSON-LD objects to perform the expansion upon or an
- <tref>IRI</tref> referencing the JSON-LD document to expand.</dd>
- <dt>JsonLdCallback callback</dt>
- <dd>A callback that is called when processing completed successfully
- on the given <code>input</code>, or a fatal error prevented
- processing from completing.</dd>
- <dt>optional JsonLdOptions? options</dt>
- <dd>A set of options to configure the used algorithms such. This allows, e.g.,
- to set the input document's base <tref>IRI</tref>.</dd>
- </dl>
- </dd>
-
- <dt>void compact()</dt>
- <dd>
- <a href="#compaction">Compacts</a> the given <code>input</code> using the
- <code>context</code> according to the steps in the
- <a href="#compaction-algorithm">Compaction Algorithm</a>.
-
- <dl class="parameters">
- <dt>(object or object[] or DOMString) input</dt>
- <dd>The JSON-LD object or array of JSON-LD objects to perform the compaction upon or an
- <tref>IRI</tref> referencing the JSON-LD document to compact.</dd>
- <dt>(object or DOMString) context</dt>
- <dd>The context to use when compacting the <code>input</code>; either in the
- form of an <tref>JSON object</tref> or as <tref>IRI</tref>.</dd>
- <dt>JsonLdCallback callback</dt>
- <dd>A callback that is called when processing completed successfully
- on the given <code>input</code>, or a fatal error prevented
- processing from completing.</dd>
- <dt>optional JsonLdOptions? options</dt>
- <dd>A set of options to configure the used algorithms such. This allows, e.g.,
- to set the input document's base <tref>IRI</tref>. This also includes
- the <code>optimize</code> flag, which, if set, will allow processor-specific
- optimization.</dd>
- </dl>
- </dd>
-
- <dt>void flatten()</dt>
- <dd>
- <a href="#flattening">Flattens</a> the given <code>input</code> and
- <a href="#compaction">compacts</a> it using the passed <code>context</code>
- according to the steps in the <a href="#flattening-algorithm">Flattening Algorithm</a>.
-
- <dl class="parameters">
- <dt>(object or object[] or DOMString) input</dt>
- <dd>The JSON-LD object or array of JSON-LD objects or an <tref>IRI</tref>
- referencing the JSON-LD document to flatten.</dd>
- <dt>(object or DOMString)? context</dt>
- <dd>The context to use when compacting the flattened <code>input</code>; either
- in the form of an <tref>JSON object</tref> or as <tref>IRI</tref>. If
- <tref>null</tref> is passed, the result will not be compacted but keept
- in expanded form.</dd>
- <dt>JsonLdCallback callback</dt>
- <dd>A callback that is called when processing completed successfully
- on the given <code>input</code>, or a fatal error prevented
- processing from completing.</dd>
- <dt>optional JsonLdOptions? options</dt>
- <dd>A set of options to configure the used algorithms such. This allows, e.g.,
- to set the input document's base <tref>IRI</tref>.</dd>
- </dl>
- </dd>
- </dl>
-
- </section>
-
- <section>
- <h3>Callbacks</h3>
-
- <p>JSON-LD processors utilize callbacks in order to return information in an
- asynchronous manner to calling applications. This section details the
- parameters sent to those callbacks.</p>
-
- <section>
- <h3>JsonLdCallback</h3>
- <p>The <a>JsonLdCallback</a> is called when an API method of
- <a>JsonLdProcessor</a> has been completed, either successfully or
- by a fatal error.</p>
-
- <dl title="callback JsonLdCallback = void" class="idl">
- <dt>JsonLdError error</dt>
- <dd>If the value is <tref>null</tref>, then no issue was detected
- during processing. Otherwise, a processing issue was detected and
- the details are contained within the <em>error</em> object.</dd>
- <dt>object or object[] document</dt>
- <dd>The processed JSON-LD document.</dd>
- </dl>
- </section>
- </section>
-
- <section>
- <h3>Data Structures</h3>
- <p>This section describes datatype definitions used within the JSON-LD API.</p>
-
- <section>
- <h3>JsonLdOptions</h3>
- <p>The <a>JsonLdOptions</a> type is used to pass various options to the <a>JsonLdProcessor</a> methods.</p>
- <dl title="dictionary JsonLdOptions" class="idl">
- <dt>DOMString base</dt>
- <dd>The Base IRI to use when expanding the document. This overrides the value of
- <em>input</em> if it is a <a>IRI</a>. If not specified and <em>input</em> is not
- an <a>IRI</a>, the base IRI defaults to the current document IRI if in a browser context,
- or the empty string if there is no document context.
- <p class="issue atrisk" title="Feature at risk">The default value of this option
- implies that all IRIs that cannot be compacted otherwise are transformed to relative IRIs
- during compaction. To avoid that data is being lost, developers thus have to store the
- base IRI along with the compacted document. This might be problematic in practice and
- thus the default behavior might be changed in future.</p>
- </dd>
- <dt>object or DOMString expandContext = null</dt>
- <dd>A context that is used to initialize the active context when expanding a document.</dd>
- <dt>boolean compactArrays = true</dt>
- <dd>If set to <code>true</code>, the JSON-LD processor replaces arrays with just
- one element with that element during compaction. If set to <code>false</code>,
- all arrays will remain arrays even if they have just one element.
- </dd>
- <dt>boolean optimize = false</dt>
- <dd>If set to <code>true</code>, the JSON-LD processor is allowed to
- optimize the output of the <a href="#compaction-algorithm">Compaction Algorithm</a>
- to produce even compacter representations. The algorithm for compaction
- optimization is beyond the scope of this specification and thus
- not defined. Consequently, different implementations MAY implement
- different optimization algorithms.
- </dd>
- <dt>boolean useRdfType = false</dt>
- <dd>If set to <code>true</code>, the JSON-LD processor will use the
- expanded <code>rdf:type</code> IRI as the property instead of
- <code>@type</code> when <a href="#convert-from-rdf-algorithm">converting from RDF</a>.
- </dd>
- <dt>boolean useNativeTypes = true</dt>
- <dd>If set to <code>true</code>, the JSON-LD processor will try to convert
- <tref title="typed value">typed values</tref> to JSON native types instead of using the
- expanded object form when <a href="#convert-from-rdf-algorithm">converting from RDF</a>.
- <code>xsd:boolean</code> values will be converted to <tref>true</tref> or <tref>false</tref>.
- <code>xsd:integer</code> and <code>xsd:double</code> values will be
- converted to
- <tref title="number">JSON numbers</tref>.
- </dd>
- </dl>
- </section>
-
- <section>
- <h3>JsonLdError</h3>
-
- <p>The <a>JsonLdError</a> type is used to report processing errors
- to a <a>JsonLdCallback</a>.</p>
-
- <dl title="dictionary JsonLdError" class="idl">
- <dt>JsonLdErrorCode code</dt>
- <dd>a string representing the particular error type, as described in
- the various algorithms in this document.</dd>
- <dt>DOMString? message</dt>
- <dd>an optional error message containing additional debugging information.
- The specific contents of error messages are outside the scope of this
- specification.</dd>
- </dl>
- </section>
-
- <section>
- <h3>JsonLdErrorCode</h3>
- <p>The <a>JsonLdErrorCode</a> represents the collection of valid JSON-LD error
- codes.</p>
-
- <dl title="enum JsonLdErrorCode" class="idl">
- <dt>invalid syntax</dt>
- <dd>The document could not be parsed as JSON.</dd>
- <dt>list of lists detected</dt>
- <dd>A list of lists was detected. List of lists are not supported in
- this version of JSON-LD due to the algorithmic complexity associated
- with conversion to RDF.</dd>
- <dt>invalid @index value</dt>
- <dd>An <code>@index</code> member was encountered whose value was
- not a <tref>string</tref>.</dd>
- <dt>conflicting indexes</dt>
- <dd>Multiple conflicting indexes have been found for the same node.</dd>
- <dt>invalid @id value</dt>
- <dd>An <code>@id</code> member was encountered whose value was not a
- <tref>string</tref>.</dd>
- <dt>invalid local context</dt>
- <dd>In invalid <tref>local context</tref> was detected.</dd>
- <dt>loading remote context failed</dt>
- <dd>There was a problem encountered loading a remote context.</dd>
- <dt>invalid remote context</dt>
- <dd>No valid context document has been found for a referenced,
- remote context.</dd>
- <dt>recursive context inclusion</dt>
- <dd>A cycle in remote context inclusions has been detected.</dd>
- <dt>invalid default language</dt>
- <dd>The value of the <tref>default language</tref> is not a <tref>string</tref>
- or <tref>null</tref> and thus invalid.</dd>
- <dt>invalid vocab mapping</dt>
- <dd>An invalid <tref>vocabulary mapping</tref> has been detected, i.e.,
- it is neither an <tref>absolute IRI</tref> nor <tref>null</tref>.</dd>
- <dt>keyword redefinition</dt>
- <dd>A <tref>keyword</tref> redefinition has been detected.</dd>
- <dt>invalid term definition</dt>
- <dd>An invalid <tref>term definition</tref> has been detected.</dd>
- <dt>invalid term IRI mapping</dt>
- <dd>A <tref>local context</tref> contains a <tref>term</tref> that
- has not been mapped to an <tref>absolute IRI</tref>.</dd>
- <dt>cyclic IRI mapping</dt>
- <dd>A cycle in <tref title="IRI mapping">IRI mappings</tref> has been detected.</dd>
- <dt>invalid type mapping</dt>
- <dd>An <code>@type</code> member in a <tref>term definition</tref>
- was encountered whose value could not be expanded to an
- <tref>absolute IRI</tref>.</dd>
- <dt>invalid language mapping</dt>
- <dd>An <code>@language</code> member in a <tref>term definition</tref>
- was encountered whose value was neither a <tref>string</tref> nor
- <tref>null</tref> and thus invalid.</dd>
- <dt>invalid container mapping</dt>
- <dd>An <code>@container</code> member was encountered whose value was
- not one of the following <tref title="string">strings</tref>:
- <code>@list</code>, <code>@set</code>, or <code>@index</code>.</dd>
- <dt>invalid property generator</dt>
- <dd>A non-<tref>string</tref> value has been detected in a
- <tref title="property generator">property generator's</tref>
- <tref>IRI mapping</tref>.</dd>
- <dt>invalid property generator IRI mapping</dt>
- <dd>Expanding all values of a
- <tref title="property generator">property generator's</tref>
- <tref>IRI mapping</tref> to <tref>absolute IRI</tref> failed.</dd>
- <dt>property generator in term definition</dt>
- <dd>A <tref>property generator</tref> was used in the
- <tref>IRI mapping</tref> of another <tref>term</tref> or
- <tref>property generator</tref>.</dd>
- <dt>invalid type value</dt>
- <dd>An invalid value for an <code>@type</code> member has been detected,
- i.e., the value was neither a <tref>string</tref> nor an <tref>array</tref>
- of <tref title="string">strings</tref>.</dd>
- <dt>invalid value object</dt>
- <dd>A <tdef>value object</tdef> with disallowed members has been
- detected.</dd>
- <dt>invalid value object value</dt>
- <dd>An invalid value for the <code>@value</code> member of a
- <tref>value object</tref> has been detected, i.e., it is neither
- a <tref>scalar</tref> nor <tref>null</tref>.</dd>
- <dt>invalid language tagged string</dt>
- <dd>A <tref>language-tagged string</tref> with disallowed members has
- been detected.</dd>
- <dt>invalid language value</dt>
- <dd>A <tref>language-tagged string</tref> with an invalid language
- value was detected.</dd>
- <dt>invalid typed value</dt>
- <dd>A <tref>typed value</tref> with disallowed members has been
- detected.</dd>
- <dt>invalid set or list object</dt>
- <dd>A <tdef>set object</tref> or <tref>list object</tref> with
- disallowed members has been detected.</dd>
- <dt>language map invalid value</dt>
- <dd>An invalid value in a <tdef>language map</tdef> was detected. It has
- to be a <tref>string</tref> or an <tref>array</tref> of
- <tref title="string">strings</tref>.</dd>
- <dt>compaction to list of lists</dt>
- <dd>The compacted document contains a list of lists as multiple
- lists have been compacted to the same term.</dd>
- </dl>
- </section>
-
- </section>
-</section>
-
-<section class="appendix">
- <h1>Acknowledgements</h1>
-
- <p>A large amount of thanks goes out to the JSON-LD Community Group
- participants who worked through many of the technical issues on the mailing
- list and the weekly telecons - of special mention are Niklas Lindström,
- François Daoust, Lin Clark, and Zdenko 'Denny' Vrandečić.
- The editors would like to thank Mark Birbeck, who provided a great deal of
- the initial push behind the JSON-LD work via his work on RDFj.
- The work of Dave Lehn and Mike Johnson are appreciated for reviewing,
- and performing several implementations of the specification. Ian Davis is
- thanked for his work on RDF/JSON. Thanks also to Nathan Rixham,
- Bradley P. Allen, Kingsley Idehen, Glenn McDonald, Alexandre Passant,
- Danny Ayers, Ted Thibodeau Jr., Olivier Grisel, Josh Mandel, Eric Prud'hommeaux,
- David Wood, Guus Schreiber, Pat Hayes, Sandro Hawke, and Richard Cyganiak
- or their input on the specification.</p>
-</section>
-
-</body>
-</html>