The TemplateMetadata
class generates the metatada from an XML templates using special annotations.
(/^?{propertyPrefix}:{propertySuffix}[*]?)+
or =any constant
or (NOW|URI|URL|METAURL|OAIID|OAIURL|RANDOM|SEQ|CURNODE)
Extracts values to be placed in the template.
Extracts an RDF property values according to a given path, e.g. /acdh:hasTitle
.
Prefixes are defined in the YAML configuration of a given metadata format.
The direction of the property can be reversed by prefixing it with a ^
,
e.g. /^acdh:isPartOf
fetches all children of a given resource.
Paths can be of arbitrary length, e.g. /acdh:isPartOf/acdh:hasContributor/acdh:hasTitle
.
A *
after the property name indicates it should be followed recursively until
it is possible, e.g. /acdh:isPartOf*/acdh:hasTitle
extracts the title of a highest-level parent.
Extracted values are then (all annotations below are optional):
- filtered according to the corresponding
match
annonation - modified according to the corresponding
replace
annonation - formatted according to the corresponding
format
annonation - mapped according to the corresponding
map
annonation - aggregated according to the corresponding
aggregate
annonation
Used a given constact value, e.g. =foo
fetches a value of foo
.
A typical use case is a conjunction of multiple metatada properties, e.g.
<period val1="acdh:hasCoverageStartDate" format1="D:Y"
val2="=-"
val3="acdh:hasCoverageEndDate" format3="D:Y"/>
See also the action
annotation description.
Returns one of special values:
NOW
the current date and timeURI
,URL
the repository-native resource identifierMETAURL
the URL fetching resource's metadataOAIID
the resource id used as its OAI-PMH idOAIURL
an URL of an OAI-PMH request fetching a given resource metadata in the current formatRANDOM
a random numberSEQ
a sequential unique numberCURNODE
an URI of the current metadata node - see theforeach
annotation description
regular expression
Skips values which do not match a given regular expression,
e.g. ^foo
skips all values which do not begin with foo
.
The regular expression is evaluted with the umsD
modifiers.
For the complete reference of the regular expressions syntax supported please look here.
regular expression replace expression
Requires a corresponding match
annotation.
Performs a regular expressions search and replace operation, e.g.
match=".*bar.*" replace="BAR"
onfoo bar baz
will result infoo BAR baz
match="foo(.*)baz" replace="\\1" on
foo bar bazwill result in
bar`
For the complete reference of the regular expressions syntax supported please look here.
For the complete reference of the replace expression syntax please look here.
The match
annotation is passed as the $pattern
, the replace
annotation as the $replacement
and the RDF property value as the $subject
.
regular expression
Skips values which match a given regular expression,
e.g. ^foo
skips all values which begin with foo
.
The regular expression is evaluted with the umsD
modifiers.
For the complete reference of the regular expressions syntax supported please look here.
Can be combined with match
. In such a case both conditions must be fulfilled.
[DUbcdeEfFgGhHosuxX]:{format-specific parameters}
Formats value according to a given rule:
D:{format}
formats as date where theformat
is described here, e.g.D:Y-m
formats the value as a 4-digit year and month separated by a-
.U:
URL-encodes the value[bcdeEfFgGhHosuxX]:{flags}{width}[.]{precision}
formats the value using the sprintf syntax, e.g.d:04
prepends a decimal number with0
until it is at least four characters long (turning45
into0045
but leaving12345
intact),f:.2
rounds a floating point number to two decimal digits precision andx:
formats a number in a hex notation (turning31
into1f
)
/{propertyPrefix}:{propertySuffix}
or mapName
/{propertyPrefix}:{propertySuffix}
treats value as a resolvable IRI. Tries to download an RDF data from it and then extracts a given RDF property values. If the original value can not be resolved or does not point to an RDF dataset, it is skipped. Similarly if a downloaded dataset does not contain the indicated RDF property, the value is skipped. Typically used for values being SKOS concept IRIs.mapName
applies a static map defined in the YAML config. If a value does not exist in the map, it is skipped.
(min|max)(,{langCode})?
Aggregates values into a single one.
If the language code is provided, the aggregation is performed only on values in this language. If there are no values in the requested language, aggregation is performed on all of them.
E.g. min,en
on "bar"@de
, "baz"@en
and "foo"@en
will result with "baz"@en
while min
will result in "bar"@de
.
as = xml|text|@{propertyName}
, action = append|overwrite
Defines the place and way where the value should be stored.
as | action | description |
---|---|---|
xml | append | appends the value to the template tag content without XML entities escaping |
xml | overwrite | overwrites the template tag content with the value without XML entities escaping |
text | append | appends the value to the template tag content applying XML entities escaping |
text | overwrite | overwrites the template tag content with the value applying XML entities escaping |
@{propertyName} | append | appends the value to the given tag's attribute value |
@{propertyName} | overwrite | overwrites the given tag's attribute with the value |
The default values are as="text" action="append"
.
Examples:
-
sets the tag value to the first existing property value out of
<a val1="/acdh:foo" action1="overwrite" val2="/acdh:bar" action2="overwrite" val3="/acdh:baz" action3="overwrite"/>
acdh:baz
,acdh:bar
andacdh:foo
(checked exactly in this order). -
results in
<a val="=<b>foo</b>" as="xml"/> <a val="=<b>foo</b>"/>
<a><b>foo></b></a> <a><b>foo</b></a>
-
results in
<a val1="foo" as1="@someAttr" val2="bar" as2="@someAttr"/>
<a someAttr="foobar"/>
if empty|overwrite
Defines if xml:lang
attribute based on the value's lang tag should be added to the tag.
Please note there can be multiple val
attributes per tag and only one final xml:lang
attribute value.
if empty
sets the xml:lang
only for a non-empty lang tag while overwrite
creates an empty xml:lang
attribute if the value has no lang tag.
e.g.
<a val="acdh:hasTitle" lang="if empty"/>
<b val="acdh:hasTitle" lang="overwrite"/>
applied to metadata like <someSubject> acdh:hasTitle "foo", "bar"@de .
results in
<a>foo</a>
<a xml:lang="de">bar</a>
<b xml:lang="">foo</b>
<b xml:lang="de">bar</b>
while
<a val1="acdh:hasTitle" lang="if empty"
val2="acdh:hasAltTitle" lang="if empty"/>
<b val1="acdh:hasTitle" lang="if empty"
val2="acdh:hasAltTitle" lang="overwrite"/>
applied to metadata like
<someSubject> acdh:hasTitle "foo"@en ;
acdh:hasAlTitle "bar"@de .
results in
<a xml:lang="en">foobar</a>
<b xml:lang="de">foobar</b>
required|optional
default required
Controls the behaviour when some val
attributes of the same tag fetch values while other not.
If any of val
attributes fetching no values is required, then all values of all val
attributes are discarded, e.g.
<a val1="acdh:foo" required1="required"
val2="acdh:bar"/>
<b val1="acdh:foo" required1="optional"
val2="acdh:bar"/>
applied to metadata like
<someSubject> acdh:bar "first value", "second value" .
ends up with (note the <a>
tag skipped in the output because the non-existent acdh:foo
RDF property was marked as required
)
<b>first value</b>
<b>second value</b>
remove
- On tags without the
if
andforeach
annotation.
By default if there are no values to display, the original tag from the template is preserved. Useremove="remove"
to drop it. - On tags with the
foreach
annotation.
Removes the tag from the output, e.g.will result in output like<a foreach="/acdh:hasTitle><b val="CURNODE"/></a>
while<a><b>foo</b></a> <a><b>bar</b></a>
will result in output like<a foreach="/acdh:hasTitle remove="remove"><b val="CURNODE"/></a>
<b>foo</b> <b>bar</b>
- On tags with the
if
annotation Removes the tag from the output, e.g.will result in output like<a if="any(acdh:hasTitle)"><b val="/acdh:hasTitle"/></a>
while<a> <b>foo</b> <b>bar</b> </a>
will result in output like<a if="any(acdh:hasTitle)" remove="remove"><b val="CURNODE"/></a>
<b>foo</b> <b>bar</b>
(/^?{propertyPrefix}:{propertySuffix}[*]?)+
Creates a copy of the tag children for every value extracted according to a given path.
For the path syntax description please see at the val
annotation description.
Note this annotation changes the subject (active node) in the RDF graph to the currently processed value.
E.g. display a compound descritpion of all authors:
<a foreach="/acdh:hasAuthor">
<uri val="CURNODE"/>
<!-- note this path is relative to the author resource and not /acdh:hasAuthor/acdh:hasTitle -->
<title val="/acdh:hasTitle"/>
<memberOf val="/acdh:isMemberOf/acdh:hasTitle"/>
<a>
Please note it is possible to refer back to the previous node, e.g. if we want to display only authors having a homepage:
<a foreach="/acdh:hasAuthor/acdh:hasHomepage">
<uri val="/^acdh:hasHomepage"/>
<title val="/^acdh:hasHomepage/acdh:hasAuthor"/>
<homepage val="CURNODE"/>
<a>
If the foreach
is combined with the if
in a single tag, the if
statement is evaluated in the foreach
"source" resource context. What you typically want is to evalute the if
in the context of resources
the foreach
iterates trough. To achieve that, use a following syntax:
<doesnotmatter foreach="/acdh:hasAuthor" remove="remove">
<a if="some condition - see the if docs">
<uri val="/^acdh:hasHomepage"/>
<title val="/^acdh:hasHomepage/acdh:hasAuthor"/>
<homepage val="CURNODE"/>
</a>
</doesnotmatter>
Skips evaluation of child tags if a given condition is not fulfilled.
It is a logical expression constructed from terms joined with AND
, OR
, NOT
and parenthesis.
A term consists of:
- an aggregation (
any
,none
,every
) - an RDF property using the
prefix:suffix
syntax - optional operator and value
- operator is one of
==
,!=
,starts
,ends
,contains
,>
,<
,>=
,<=
,regex
- value is single- or double-quited literal value or an RDF property in the
prefix:suffix
format or a special value ofOAIID
,URI
/URL
(see theval
attribute documentation) or a special value ofPARENT
(meaning last direct parent of the previousforeach
; if there is noforeach
, then its equivalent toURI
/URL
)
- operator is one of
E.g.
if="any(rdf:type == acdh:Collection)"
if resource of typeacdh:Collection
if="none(arche:id starts acdhi:cmdi)"
if no identifier in theacdhi:cmdi
namespaceif="any(rdf:hasRawBinarySize) OR none(acdh:hasLicenseSummary)"
if there is anyacdh:hasRowBinarySize
RDF property value or noacdh:hasLicenseSummary
property
Please note that if you combine if
and foreach
in a one tag, then the if
is evaluated in the
original resource context. See the foreach
description for more detailed disccussion.
Using XML entities it is possible to include subtemplates, e.g.
- main template:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE doc [ <!ENTITY Agent SYSTEM "agent.xml"> ]> <root> <authors foreach="acdh:hasAuthor" remove="true">&Agent;</authors> <contributors foreach="acdh:hasAuthor" remove="true">&Agent;</contributors> </root>
agent.xml
<?xml version="1.0" encoding="UTF-8"?> <agent> <title val="acdh:hasTitle"/> <memberOf val="acdh:isMemberOf/acdh:hasTitle"/> </agent>