Conditional template

Map JSON content by following a conditional template.

The following list is an example of a conditional mapping by guessing the data type.

Source code of the preceding working example

Json:

{
	"subject": [
		{
			"foo": "bar",
			"bar": "hello world"
		},
		{
			"foo": "https://example.com",
			"bar": "hello world"
		}
	]
}

Html:

<ul data-wb-json='{
	"url": "demo/conditional-1.json#/subject",
	"mapping": [
		{
			"template": "[data-text]",
			"test": "fn:guessType",
			"expect": "xsd:string",
			"assess": "/foo",
			"mapping": [
				{ "selector": "[data-foo]", "value": "/foo" },
				{ "selector": "[data-bar]", "value": "/bar" }
			]
		},
		{
			"template": "[data-link]",
			"test": "fn:guessType",
			"expect": "xsd:anyURI",
			"assess": "/foo",
			"mapping": [
				{ "selector": "a", "value": "/foo", "attr": "href" },
				{ "selector": "a", "value": "/bar" }
			]
		}
	]
}'>
	<template data-text>
		<li><span data-foo></span> - <span data-bar></span></li>
	</template>
	<template data-link>
		<li><a href></a></li>
	</template>
</ul>

Through the following example, it also show the use of these, not limited to, configurations. A complete list of all configuration is available through the data-json plugin documentation.

Configuration streamline
(Boolean: true or false) This flag indicate the data-json plugin will apply the template via the mapping object directly without trying to iterate the data source.
Mapping object assess
(JSON Pointer) This the value to take for performing the conditional evaluation. Alternatively, it will take the value from the value property. Another difference is the assess would not be iterated compared to value which would be iterated for the inner mapping.

Note: The conditional template will consider the data associated to the property @value to be seen as the value of it's corresponding parent. Some of the example below to leverage that auto-mapping feature which do help for an interoperability with typed object as per defined in the JSON-LD standard.

Source code of the JSON file used by the working exmaple on this page

File: conditional-1.json

{
	"subject": [
		{
			"foo": "bar",
			"bar": "hello world"
		},
		{
			"foo": "https://example.com",
			"bar": "hello world"
		}
	],
	"list": [
		{
			"@type": "xsd:string",
			"@value": "string"
		},
		{
			"@type": "xsd:double",
			"@value": 123.45
		},
		{
			"@type": "xsd:boolean",
			"@value": true
		},
		{
			"@type": "xsd:anyURI",
			"@value": "https://example.com"
		},
		{
			"@type": "xsd:string",
			"@value": "second string"
		}
	],
	"text": {
		"alpha": "alpha",
		"beta": "beta",
		"gamma": "gamma",
		"delta": "delta"
	}
}

File: conditional-2.json

{
	"alpha": [ "alpha" ],
	"beta": "beta",
	"gamma": { "@value": "gamma" },
	"delta": { "@type": "rdfs:Resource", "@value": "delta" },
	"epsilon": "epsilon",
	"zeta": true,
	"eta": "http://example.com",
	"theta": 123.45,
	"iota": {
		"@type": [ "rdfs:Resource", "xsd:string" ],
		"@value": "iota"
	},
	"kappa": {
		"lamdba": "mu"
	},
	"nu": {
		"@type": "@json",
		"@value": {
			"xi": "xi",
			"omicron": "omicron",
			"pi": "pi"
		}
	},
	"rho": {
		"@type": "@json",
		"@value": {
			"sigma": "sigma",
			"tau": "tau",
			"upsilon": "upsilon"
		}
	},
	"sigma": {
		"alpha": "sigma",
		"gamma": "sigma"
	},
	"undefined": "tau",

	"text": {
		"zeta": "zeta",
		"eta": "eta",
		"theta": "theta",
		"kappa": "kappa"
	}
}

Test functions that extract a testable value

Those test require a data pointer either provided with the value property which would also iterate or with assess which don't iterate.

fn:isArray
Boolean returning if the tested value is an array or not.
fn:isLiteral
Boolean returning if the tested value is an literal or not. A literal value is considered to be defined and not an object.
fn:getType
Return type of the value set via the @type property or its corresponding javascript typeof value.
fn:guessType

The template parser will try to guess the data type of the tested value.

This test function will return:

  • rdfs:Container when the value is an array.
  • rdfs:Literal for any value that is literal. A literal value is considered to be defined and not an object.
  • rdfs:Resource when the value is an JSON object without any defined type.
  • xsd:anyURI when the value is a string which start with non-spaced letter and digit immediately followed by colon ":" like https://example.com
  • xsd:string when the value is a string and don't look to be an URI.
  • xsd:boolean when the value is a boolean with the value set to true or false
  • xsd:double when the value is a JSON number
  • The value set via the @type sub property
  • undefined when the value is undefined
fn:getValue
Return value as the testable value.

Example of each test function

Demo of each test function.

Expectation of the preceding demo.

  • fn:isArray: alpha
  • fn:isLiteral: beta
  • fn:isLiteral: gamma
  • fn:getType: delta
  • fn:getType: epsilon
  • fn:getType: zeta
  • fn:guessType: alpha
  • fn:guessType: beta
  • fn:guessType: gamma
  • fn:guessType: eta
  • fn:guessType: beta
  • fn:guessType: gamma
  • fn:guessType: zeta
  • fn:guessType: theta
  • fn:guessType: delta
  • fn:guessType: sigma
  • fn:guessType: tau
  • fn:getValue: kappa
Source code
<div class="row">
	<div class="col-md-6">
		<p>Demo of each test function.</p>
		<ul data-wb-json='{
			"url": "demo/conditional-2.json",
			"streamline": true,
			"mapping": [
				{
					"template": "[data-isarray]",
					"test": "fn:isArray",
					"assess": "/alpha",
					"mapping": [
						{ "selector": "span", "value": "/alpha/0" }
					]
				},
				{
					"template": "[data-isliteral]",
					"test": "fn:isLiteral",
					"assess": "/beta",
					"mapping": [
						{ "selector": "span", "value": "/beta" }
					]
				},
				{
					"template": "[data-isliteral]",
					"test": "fn:isLiteral",
					"assess": "/gamma",
					"mapping": [
						{ "selector": "span", "value": "/gamma" }
					]
				},
				{
					"template": "[data-gettype]",
					"test": "fn:getType",
					"assess": "/delta",
					"expect": "rdfs:Resource",
					"mapping": [
						{ "selector": "span", "value": "/delta" }
					]
				},
				{
					"template": "[data-gettype]",
					"test": "fn:getType",
					"assess": "/epsilon",
					"expect": "string",
					"mapping": [
						{ "selector": "span", "value": "/epsilon" }
					]
				},
				{
					"template": "[data-gettype]",
					"test": "fn:getType",
					"assess": "/zeta",
					"expect": "boolean",
					"mapping": [
						{ "selector": "span", "value": "/text/zeta" }
					]
				},
				{
					"template": "[data-guesstype]",
					"test": "fn:guessType",
					"assess": "/alpha",
					"expect": "rdfs:Container",
					"mapping": [
						{ "selector": "span", "value": "/alpha/0" }
					]
				},
				{
					"template": "[data-guesstype]",
					"test": "fn:guessType",
					"assess": "/beta",
					"expect": "rdfs:Literal",
					"mapping": [
						{ "selector": "span", "value": "/beta" }
					]
				},
				{
					"template": "[data-guesstype]",
					"test": "fn:guessType",
					"assess": "/gamma",
					"expect": "rdfs:Literal",
					"mapping": [
						{ "selector": "span", "value": "/gamma" }
					]
				},
				{
					"template": "[data-guesstype]",
					"test": "fn:guessType",
					"assess": "/beta",
					"expect": "xsd:anyURI",
					"mapping": [
						{ "selector": "span", "value": "/beta" }
					]
				},
				{
					"template": "[data-guesstype]",
					"test": "fn:guessType",
					"assess": "/gamma",
					"expect": "xsd:anyURI",
					"mapping": [
						{ "selector": "span", "value": "/gamma" }
					]
				},
				{
					"template": "[data-guesstype]",
					"test": "fn:guessType",
					"assess": "/eta",
					"expect": "xsd:anyURI",
					"mapping": [
						{ "selector": "span", "value": "/text/eta" }
					]
				},
				{
					"template": "[data-guesstype]",
					"test": "fn:guessType",
					"assess": "/beta",
					"expect": "xsd:string",
					"mapping": [
						{ "selector": "span", "value": "/beta" }
					]
				},
				{
					"template": "[data-guesstype]",
					"test": "fn:guessType",
					"assess": "/gamma",
					"expect": "xsd:string",
					"mapping": [
						{ "selector": "span", "value": "/gamma" }
					]
				},
				{
					"template": "[data-guesstype]",
					"test": "fn:guessType",
					"assess": "/eta",
					"expect": "xsd:string",
					"mapping": [
						{ "selector": "span", "value": "/text/eta" }
					]
				},
				{
					"template": "[data-guesstype]",
					"test": "fn:guessType",
					"assess": "/zeta",
					"expect": "xsd:boolean",
					"mapping": [
						{ "selector": "span", "value": "/text/zeta" }
					]
				},
				{
					"template": "[data-guesstype]",
					"test": "fn:guessType",
					"assess": "/theta",
					"expect": "xsd:double",
					"mapping": [
						{ "selector": "span", "value": "/text/theta" }
					]
				},
				{
					"template": "[data-guesstype]",
					"test": "fn:guessType",
					"assess": "/delta",
					"expect": "rdfs:Resource",
					"mapping": [
						{ "selector": "span", "value": "/delta/@value" }
					]
				},
				{
					"template": "[data-guesstype]",
					"test": "fn:guessType",
					"assess": "/sigma",
					"expect": "rdfs:Resource",
					"mapping": [
						{ "selector": "span", "value": "/sigma/alpha" }
					]
				},
				{
					"template": "[data-guesstype]",
					"test": "fn:guessType",
					"assess": "/tau",
					"expect": "undefined",
					"mapping": [
						{ "selector": "span", "value": "/undefined" }
					]
				},
				{
					"template": "[data-getvalue]",
					"test": "fn:getValue",
					"assess": "/kappa",
					"operand": "eq",
					"expect": { "lamdba": "mu" },
					"mapping": [
						{ "selector": "span", "value": "/text/kappa" }
					]
				}
			]
		}'>
			<template data-isarray>
				<li><code>fn:isArray</code>: <span></span></li>
			</template>
			<template data-isliteral>
				<li><code>fn:isLiteral</code>: <span></span></li>
			</template>
			<template data-gettype>
				<li><code>fn:getType</code>: <span></span></li>
			</template>
			<template data-guesstype>
				<li><code>fn:guessType</code>: <span></span></li>
			</template>
			<template data-getvalue>
				<li><code>fn:getValue</code>: <span></span></li>
			</template>
		</ul>
	</div>
	<div class="col-md-6">
		<p>Expectation of the preceding demo.</p>
		<ul>
			<li><code>fn:isArray</code>: alpha</li>
			<li><code>fn:isLiteral</code>: beta</li>
			<li><code>fn:isLiteral</code>: gamma</li>
			<li><code>fn:getType</code>: delta</li>
			<li><code>fn:getType</code>: epsilon</li>
			<li><code>fn:getType</code>: zeta</li>
			<li><code>fn:guessType</code>: alpha</li>
			<li><code>fn:guessType</code>: beta</li>
			<li><code>fn:guessType</code>: gamma</li>
			<li><code>fn:guessType</code>: eta</li>
			<li><code>fn:guessType</code>: beta</li>
			<li><code>fn:guessType</code>: gamma</li>
			<li><code>fn:guessType</code>: zeta</li>
			<li><code>fn:guessType</code>: theta</li>
			<li><code>fn:guessType</code>: delta</li>
			<li><code>fn:guessType</code>: sigma</li>
			<li><code>fn:guessType</code>: tau</li>
			<li><code>fn:getValue</code>: kappa</li>
		</ul>
	</div>
</div>

Operand function

Operand functions that check the testable value.

softEq (default)
Check if the value is equivalent equal to the expectation optionally either in an array value. When no expectation provide, return true if the testable value exist.
eq
Check if the value equal the expectation. Including when the value is an object.
neq
Check if the value is not equal the expectation. Including when the value is an object.
in
Check if the value (or array of value) is in the expectation (or array of expectation)
nin
Check if the value (or array of value) is not in the expectation (or array of expectation)

Example of operand

Demo of each test function.

Expectation of the preceding demo.

  • eq: delta
  • eq: kappa
  • eq: iota
  • neq: delta
  • in: iota
  • nin: iota
Source code
<div class="row">
	<div class="col-md-6">
		<p>Demo of each test function.</p>
		<ul data-wb-json='{
			"url": "demo/conditional-2.json",
			"streamline": true,
			"mapping": [
				{
					"template": "[data-eq]",
					"test": "fn:guessType",
					"assess": "/delta",
					"operand": "eq",
					"expect": "rdfs:Resource",
					"mapping": [
						{ "selector": "span", "value": "/delta/@value" }
					]
				},
				{
					"template": "[data-eq]",
					"test": "fn:getValue",
					"assess": "/kappa",
					"operand": "eq",
					"expect":  { "lamdba": "mu" },
					"mapping": [
						{ "selector": "span", "value": "/text/kappa" }
					]
				},
				{
					"template": "[data-eq]",
					"test": "fn:guessType",
					"assess": "/iota",
					"operand": "eq",
					"expect": [ "rdfs:Resource", "xsd:string" ],
					"mapping": [
						{ "selector": "span", "value": "/iota/@value" }
					]
				},
				{
					"template": "[data-neq]",
					"test": "fn:guessType",
					"assess": "/delta",
					"operand": "neq",
					"expect": "rdfs:Literal",
					"mapping": [
						{ "selector": "span", "value": "/delta/@value" }
					]
				},
				{
					"template": "[data-in]",
					"test": "fn:guessType",
					"assess": "/iota",
					"operand": "in",
					"expect": "xsd:string",
					"mapping": [
						{ "selector": "span", "value": "/iota/@value" }
					]
				},
				{
					"template": "[data-nin]",
					"test": "fn:guessType",
					"assess": "/iota",
					"operand": "nin",
					"expect": "rdfs:Literal",
					"mapping": [
						{ "selector": "span", "value": "/iota/@value" }
					]
				}

			]
		}'>
			<template data-eq>
				<li><code>eq</code>: <span></span></li>
			</template>
			<template data-neq>
				<li><code>neq</code>: <span></span></li>
			</template>
			<template data-in>
				<li><code>in</code>: <span></span></li>
			</template>
			<template data-nin>
				<li><code>nin</code>: <span></span></li>
			</template>
		</ul>
	</div>
	<div class="col-md-6">
		<p>Expectation of the preceding demo.</p>
		<ul>
			<li><code>eq</code>: delta</li>
			<li><code>eq</code>: kappa</li>
			<li><code>eq</code>: iota</li>
			<li><code>neq</code>: delta</li>
			<li><code>in</code>: iota</li>
			<li><code>nin</code>: iota</li>
		</ul>
	</div>
</div>

The mapping function: Alternative

This special mapping function allow to configure a list of mapping where it's going to execute only the first children passing its test condition.

Demo of the alternative function.

Expectation of the preceding demo.

  • First template: gamma
Source code
<div class="row">
	<div class="col-md-6">
		<p>Demo of the alternative function.</p>
		<ul data-wb-json='{
			"url": "demo/conditional-2.json",
			"streamline": true,
			"mapping": [
				{
					"@type": "rdf:Alt",
					"mapping": [
						{
							"template": "[data-first]",
							"test": "fn:guessType",
							"assess": "/gamma",
							"expect": "rdfs:Literal",
							"mapping": [
								{ "selector": "span", "value": "/gamma" }
							]
						},
						{
							"template": "[data-second]",
							"test": "fn:guessType",
							"assess": "/eta",
							"expect": "xsd:anyURI",
							"mapping": [
								{ "selector": "span", "value": "/eta" }
							]
						}
					]
				}
			]
		}'>
			<template data-first>
				<li>First template: <span></span></li>
			</template>
			<template data-second>
				<li>Second template: <span></span></li>
			</template>

		</ul>
	</div>
	<div class="col-md-6">
		<p>Expectation of the preceding demo.</p>
		<ul>
			<li>First template: gamma</li>
		</ul>
	</div>
</div>

Show template content conditionally

Display template content without using it to map json data.

Demo:

Expectation of the preceding demo.

Working

Source code
<div class="row">
	<div class="col-md-6">
		<p>Demo:</p>
		<div data-wb-json='{
				"url": "demo/conditional-2.json",
				"streamline": true,
				"mapping": [
					{
						"template": "[data-show-conditional-only]",
						"test": "fn:isLiteral",
						"assess": "/beta",
						"mapping": null
					}
				]
			}'>
			<template data-show-conditional-only>
				<p>Working</p>
			</template>
		</div>
	</div>
	<div class="col-md-6">
		<p>Expectation of the preceding demo.</p>
		<p>Working</p>
	</div>
</div>

Location of the merged template

By default, when the configuration is not streamlined, the content created with the initial template are appended to the element.

For inner template, through mapping configuration, and when the plugin configuration streamline flag is on, the content created with the template are added just before that template. However, you can use the flag "append" to append from the parent element of the template.

Rendering example of a template specified via mapping by default.

Demo (Default, inserted in-place):

Expectation of the preceding demo.

  • xsd:string: string
  • xsd:string: second string
  • xsd:double: 123.45
  • xsd:boolean: true
  • xsd:anyURI: https://example.com

Demo (With append flag):

Expectation of the preceding demo.

  • xsd:string: string
  • xsd:double: 123.45
  • xsd:boolean: true
  • xsd:anyURI: https://example.com
  • xsd:string: second string
Source code
<div class="row">
	<div class="col-md-6">
		<p>Demo (Default, inserted in-place):</p>
		<ul data-wb-json='{
			"url": "demo/conditional-1.json#/list",
			"mapping": [
				{
					"template": "[data-string]",
					"test": "fn:guessType",
					"assess": "/",
					"expect": "xsd:string",
					"mapping": [
						{ "selector": "span", "value": "/" }
					]
				},
				{
					"template": "[data-double]",
					"test": "fn:guessType",
					"assess": "/",
					"expect": "xsd:double",
					"mapping": [
						{ "selector": "span", "value": "/" }
					]
				},
				{
					"template": "[data-boolean]",
					"test": "fn:guessType",
					"assess": "/",
					"expect": "xsd:boolean",
					"mapping": [
						{ "selector": "span", "value": "/" }
					]
				},
				{
					"template": "[data-anyuri]",
					"test": "fn:guessType",
					"assess": "/",
					"expect": "xsd:anyURI",
					"mapping": [
						{ "selector": "span", "value": "/" }
					]
				}
			]
		}'>
			<template data-string>
				<li><code>xsd:string</code>: <span></span></li>
			</template>
			<template data-double>
				<li><code>xsd:double</code>: <span></span></li>
			</template>
			<template data-boolean>
				<li><code>xsd:boolean</code>: <span></span></li>
			</template>
			<template data-anyuri>
				<li><code>xsd:anyURI</code>: <span></span></li>
			</template>
		</ul>
	</div>
	<div class="col-md-6">
		<p>Expectation of the preceding demo.</p>
		<ul>
			<li><code>xsd:string</code>: string</li>
			<li><code>xsd:string</code>: second string</li>
			<li><code>xsd:double</code>: 123.45</li>
			<li><code>xsd:boolean</code>: true</li>
			<li><code>xsd:anyURI</code>: https://example.com</li>
		</ul>
	</div>
</div>

<div class="row">
	<div class="col-md-6">
		<p>Demo (With <code>append</code> flag):</p>
		<ul data-wb-json='{
			"url": "demo/conditional-1.json#/list",
			"mapping": [
				{
					"template": "[data-string]",
					"test": "fn:guessType",
					"assess": "/",
					"expect": "xsd:string",
					"append": true,
					"mapping": [
						{ "selector": "span", "value": "/" }
					]
				},
				{
					"template": "[data-double]",
					"test": "fn:guessType",
					"assess": "/",
					"expect": "xsd:double",
					"append": true,
					"mapping": [
						{ "selector": "span", "value": "/" }
					]
				},
				{
					"template": "[data-boolean]",
					"test": "fn:guessType",
					"assess": "/",
					"expect": "xsd:boolean",
					"append": true,
					"mapping": [
						{ "selector": "span", "value": "/" }
					]
				},
				{
					"template": "[data-anyuri]",
					"test": "fn:guessType",
					"assess": "/",
					"expect": "xsd:anyURI",
					"append": true,
					"mapping": [
						{ "selector": "span", "value": "/" }
					]
				}
			]
		}'>
			<template data-string>
				<li><code>xsd:string</code>: <span></span></li>
			</template>
			<template data-double>
				<li><code>xsd:double</code>: <span></span></li>
			</template>
			<template data-boolean>
				<li><code>xsd:boolean</code>: <span></span></li>
			</template>
			<template data-anyuri>
				<li><code>xsd:anyURI</code>: <span></span></li>
			</template>
		</ul>
	</div>
	<div class="col-md-6">
		<p>Expectation of the preceding demo.</p>
		<ul>
			<li><code>xsd:string</code>: string</li>
			<li><code>xsd:double</code>: 123.45</li>
			<li><code>xsd:boolean</code>: true</li>
			<li><code>xsd:anyURI</code>: https://example.com</li>
			<li><code>xsd:string</code>: second string</li>
		</ul>
	</div>
</div>

Mapping of a @json (or rdf:JSON) value

Allow to display in a textual form @json typed value or rdf:JSON value which are the exact same. The test function for data type will always return the RDF form of the type @json which is rdf:JSON

Demo of mapping @json and rdf:JSON data

Expectation of the preceding demo.

{"xi":"xi","omicron":"omicron","pi":"pi"}
{"sigma":"sigma","tau":"tau","upsilon":"upsilon"}
Source code
<div class="row">
	<div class="col-md-6">
		<p>Demo of mapping <code>@json</code> and <code>rdf:JSON</code> data</p>
		<div data-wb-json='{
			"url": "demo/conditional-2.json",
			"streamline": true,
			"mapping": [
				{
					"template": "[data-json-content]",
					"test": "fn:guessType",
					"assess": "/nu",
					"expect": "rdf:JSON",
					"mapping": [
						{ "selector": "data", "value": "/nu" },
						{ "selector": "data", "value": "/nu", "attr": "value" }
					]
				},
				{
					"template": "[data-json-content]",
					"test": "fn:guessType",
					"assess": "/rho",
					"expect": "rdf:JSON",
					"mapping": [
						{ "selector": "data", "value": "/rho" },
						{ "selector": "data", "value": "/rho", "attr": "value" }
					]
				}
			]
		}'>
			<template data-json-content>
				<pre><code><data value></data></code></pre>
			</template>
		</div>
	</div>
	<div class="col-md-6">
		<p>Expectation of the preceding demo.</p>
		<pre><code><data value='{"xi":"xi","omicron":"omicron","pi":"pi"}'>{"xi":"xi","omicron":"omicron","pi":"pi"}</data></code></pre>
		<pre><code><data value='{"sigma":"sigma","tau":"tau","upsilon":"upsilon"}'>{"sigma":"sigma","tau":"tau","upsilon":"upsilon"}</data></code></pre>
	</div>
</div>

Extension of test function and operand

The data-json plugin has been adapted to allow extension of it's test function and list of operand. And it is not possible to override any existing one.

If the custom test function and operand defined uniquely on this page are positive, the following will be emphasised text with the content set to "beta":

Source code
<script>
window[ "wb-data-json" ] = {
	functionForTest: {
		"myCustomTest": function( value, rawValue ) {
			if ( value === "beta" ) {
				return "foo";
			}
			return value;
		}
	},
	functionForOperand: {
		"myCustomOperand": function( value, expect ) {
			if ( value === "foo" && expect === "bar" ) {
				return true;
			} else {
				return false;
			}
		}
	}
};
</script>

<p data-wb-json='{
	"url": "demo/conditional-2.json",
	"streamline": true,
	"mapping": [
		{
			"template": "[data-custom]",
			"test": "myCustomTest",
			"value": "/beta",
			"operand": "myCustomOperand",
			"expect": "bar",
			"mapping": [
				{ "selector": "strong", "value": "/" }
			]
		}
	]
}'>If the custom test function and operand defined uniquely on this page are positive, the following will be emphasised text with the content set to "beta":
	<template data-custom>
		<strong></strong>
	</template>
</p>
Date modified: