SGML templating builds on SGML's NOTATION
and LINK
concepts
(explained below) and allows parametric inclusion of other
SGML files/resources (templates), such that entity references
in templates are expanded into values provided from the invocation
context.
Parameters can be provided either
from data attributes (attributes specified for data entities)
from content attributes (attributes specified on element in the main file which are expanded by templates)
from external resources such as SQL or SPARQL queries, web services, etc.
A link process, in SGML, is a general term for any kind of processing performed by code "linked" (as in dynamic link library) to a SGML parser library. The term "link process" as used in SGML has nothing to do with hyperlinks, and is better understood as a kind of stylesheet similar to a CSS stylesheet.
A link process declaration (LPD) is a declaration set (a syntactical construct that can appear in a document prolog along with a DTD) declaring properties for link processes and their values. These properties are declared as link attributes, re-using standard attribute list declaration syntax.
Link attributes are associated with content elements in the same
way as plain content attributes, but aren't serialized to output.
Values for link attributes are determined either by #FIXED
default
values declared for the respective attribute in ATTLIST
declarations
in the link process declaration, or can be determined in a
state-dependent way based on link sets declared in the link
process declaration.
A link set is a rule that associates link attribute values to
a particular element appearing in the content, potentially
with filtering rules that further restrict the elements to which
the rule(s) apply. Link attributes determined via link sets,
unlike link attributes merely defaulted by a #FIXED
link atttribute declaration, can be given values
depending on where the element to apply to appears within content.
For example, link sets can specify that list items with odd ordinal numbers should be rendered differently from those with even ordinals. This is achieved by using two link sets, each associating different link attribute values to the same list item content element, and by telling the processor to use the other link set as applicable link set ("current link set") once a link attribute has been determined.
Link attributes are not included in the output document of SGML processing; instead, in sgmljs.net, link attributes determine templates and template parameters to apply on the respective elements to which the link attribute is assigned by link processing, and the SGML processing output for those elements is determined by the template (note there are additional ways for a template to influence output, such as via result elements on explicit link rules that don't select a template, and via entity preemption; these are explained in detail further down).
While implicit link processes are restricted to associate link attributes to content attribute as described, explict link processes can be used to produce entirely new SGML documents driven by source elements. Explicit link processes will only produce result elements if explictly told to do through link rules, but, unlike implicit link don't copy source markup to result markup, hence can filter (omit) source content which implicit link by themselves can't do.
Link processes can be chained to form a pipeline of link processes where the output of one link process serves as the source content for the next chained link process (subject to the restrictions explained below). In this way, link processing can perform fairly rich document preparation and extraction tasks such as generating an outline for navigation, perform paging, format search results, add boilerplate content, etc.
Apart from implicit and explicit link processes, SGML also offers simple processes. A simple link process contains global properties of a link process, rather than properties of individual elements; syntactically, a simple link process is declared as a special kind of implicit link process where link attributes are only declared on the document element (the root element of the document).
For a LPD to be processed and have any effect, it must be active.
A link process is activated by supplying its name as an invocation
parameter to the active_lpds
command-line parameter in
command-line processing. In web templating, link processes
having the name web
and http
are activated by default,
if present in a document to serve.
An implicit LPD has the following form
<!LINKTYPE lpd-name dtd-name #IMPLIED [
[entity-declarations]
link-attribute-declarations
<!LINK #INITIAL link-rule [link-rule] ...>
[<!LINK link-name link-rule [link-rule] ...>
<!LINK link-name link-rule [link-rule] ...> ...]
]>
where link-rule is an item of the form
element [#POSTLINK target] [#USELINK target] [ attr=value ... ]
or
(element1|element2|...) [#POSTLINK target] [#USELINK target] [ attr=value ... ]
Note that in this syntax description for a link rule the square braces around attribute specifications are verbatim SGML code text.
#POSTLINK
and #USELINK
targets and attribute specifications are optional.
is the name of the link process to declare; the name must be distinct from every other declaration set name (LPD or DTD) in the document
is the declaration set name of the DTD containing the elements on which link attributes are being declared
is one or more (general, parameter, or data) entity declaration; see entity preemption
An (implicit or explicit, but not simple) link process
declaration must include a single #INITIAL
link set
declaration, and can optionally contain additional named
link set declarations
Link attributes don't get output as content attributes, but are used to associate processing properties with source elements; in particular, if a link process assigns a template to a link attribute, then the respective element on which the template is assigned is replaced by the template content for output, possibly with further link attributes as template parameters.
Otherwise, an implicit link produces its input sequence of elements and other markup constructs to the output markup unchanged. But note that, like for all link processes, Entity Preemption can also influence the output of an implicit link process.
For example, the following (simplified HTML) document
contains an LPD that will assign "body value" to the
html
content element, and "p value" to the p
content element:
<!doctype html [
<!element html (head?,body)>
<!element body (p*)>
]>
<!linktype l [
<!attlist (html|p) linkattribute cdata #implied>
<!link #initial html #uselink inbody [ linkattribute="body value" ]>
<!link #inbody p [ linkattribute="p value" ]>
]>
<html>
<body>
<p>Hello</p>
</body>
</html>
Starting in the #INITIAL
link set (where "body value" is determined
as link attribute), the #USELINK
rule takes the link processor to the
inbody
link set, where "p value" is determined as link attribute on the
p
element.
Note that #USELINK
is pointless here, and only used for demonstrating
the syntax and general operation of implicit link processing; in the
example, the rule for p
could have as well been included in the #INITIAL
link set with the same result.
An explicit LPD declares a link process that transforms source markup declared in a source DTD to result markup declared in result DTD. The result DTD can be the same as the source DTD, or can be different.
If it is different and multiple DTDs are involved in an explicit link process, the SGML prolog contains multiple DTDs such as in the following example:
<!doctype A [
...
]>
<!doctype B [
...
]>
<!linktype atob A B [
...
]>
In the example, the declaration for the explicit LPD atob
specifies
that it transforms source markup declared in declaration set A
to
result markup declared in declaration set B
.
If an explicit LPD's source and result DTD is the same, no additional DTD for the result markup needs to be declared in the document prolog, and the declaration of the explicit LPD takes the following form:
<!linktype name A A [
...
]>
ie. source and result declaration set name are the same in the link process declaration.
Like an implicit LPD, link attributes are used to associate processing properties with source elements; in particular, if a link process assigns a template to a link attribute, then the respective element on which the template is assigned is replaced by the template content for output, possibly with further link attributes as template parameters. If on the other hand the source element is matched by a link rule, but no template is determined for the source element, then the content is replaced by the matching link rule's result element and result attribute specification.
Note that if a template is assigned, the result attributes for the element specified in the link rule, if any, are ignored, and any output is determined by the template instead.
An explicit LPD performs tag inference and validation of its produced result markup against the result DTD, just as if the result markup were parsed, rather than generated.
Note that other SGML processing systems might not perform inference and validation on the result markup of an explicit LPD.
The syntax of an explicit LPD is very similar to that for
implicit LPDs, except that a source and
result declaration set must be specified (instead of just
a declaration set and #IMPLIED
, as in implicit LPDs), and
that a link rule maps a source to a target element
specification, rather than containing just a single element
and link attribute specification as in implicit LPDs):
<!LINKTYPE lpd-name source-dtd-name result-dtd-name [
[entity-declarations]
link-attribute-declarations
<!LINK #INITIAL link-rule [link-rule] ...>
[<!LINK link-name link-rule [link-rule] ...>
<!LINK link-name link-rule [link-rule] ...> ...]
]>
where link rule is an item of the form
element [#POSTLINK target] [#USELINK target] [ attr=value ... ]
result-element [ result-attr=value ... ]
or
(element1|element2|...) [#POSTLINK target] [#USELINK target] [ attr=value ... ]
result-element [ result-attr=value ... ]
is the name of the link process to declare; the name must be distinct from every other declaration set name (LPD or DTD) in the document
is the declaration set name of the DTD containing the elements which appear as source elements in link rules, and on which link attributes are being declared
is the declaration set name of the DTD containing the elements which appear as result elements in link rules, and which will be produced from link rule applications
is one or more (general, parameter, or data) entity declaration; see entity preemption
is the name of an element in the source-dtd-name declaration set, which will be matched against a source content element
is the name of an element in the result-dtd-name declaration set which will be produced as result element for every matching (source) element; the result attributes and child content for the produced element are determined either by a template, if a template is implied by the link attributes on the link rule, or, if no template is implied by the link attributes, by the result attributes, if any, specified on the link rule
is an result attribute to produce unless a template is applied to produce the result element's attributes and child content
Unlike an implicit link process, an explicit link process only produces result elements to it's output for those source elements which have matching context-dependent link rules applied; if the current link set in an explicit link process hasn't a matching rule for the source content at the context position, no result element is produced.
When no element of a source document can be matched at all by link rules, an explicit link process produces a document containing just an empty result document element, having the result document type name as element name.
A link rule in an explicit link set can also use the special token
#IMPLIED
instead of either the source or result element (but not both);
see link rules with #IMPLIED
source element
and link rules with #IMPLIED
result element.
Explicit Link rules having the form
#IMPLIED [#POSTLINK target] [#USELINK target] [ attr=value ... ]
result-element [ result-attr=value ... ]
(using #IMPLIED
as source element) will create an
additional element with the respective result element name and result
attributes when it is in the current link set, and any start-element
event is encountered.
A link rule having #IMPLIED
as its source element must be the only
link rule in it's containing named link set, and must have a #USELINK
target declared.
Contained in a named link set, it is only reached from a preceding sibling
or parent element's link rule application transitioning to it by
referencing it in its #USELINK
or #POSTLINK
target.
Once the result element for a rule is produced, the link state immediately
transitions to the link set referenced in its #USELINK
target. If the
transitioned-to link set, in turn, contains a link rule having #IMPLIED
as its source element, then the result element of that link rule is
also produced to the output, and so on, until a link set is reached
which doesn't contain a link rule that has #IMPLIED
as its source
element.
In this way, rules with #IMPLIED
source elements can be used to
produce arbitrary many nested elements.
It's an error if, when transitioning to a #USELINK
target of a
link set having a rule with #IMPLIED
source element, the
transitioned-to target has already been transitioned to before
in the chain of followed #USELINK
targets; ie. the chain
of #USELINK
targets traversed must not form a cycle.
Explicit Link rules having the following form
element [#POSTLINK target] [#USELINK target] [ attr=value ... ] #IMPLIED
or
(element1|element2|...) [#POSTLINK target] [#USELINK target] [ attr=value ... ] #IMPLIED
(using #IMPLIED
as result element) will produce the source element
as result element, if it is allowed to occur directly at the context
position in the result document according to the result DTD. Unlike with
regular result elements, tag inference is not performed. If the element
is not allowed to occur at the context position (or if the element isn't
allowed to occur anywhere) in the result markup, it is silently ignored
and not produced to the output.
If the result element is produced to the output, any source
attributes allowed to occur in the result element are copied over
from the source element to the result element, too. To assess if a source
attribute is allowed to occur in the result element, the link processor
considers only the name but not the declared value of the attribute. It's
an error if, when a link rule with an implied result element matches, an
attribute is specified or implied in content, and an attribute with
the same name is declared in the result DTD, and the value specified
or implied for the content attribute isn't a valid attribute value for the
result attribute (for example, if the result element declares an attribute
with declared value NUMBER
, and the corresponding source attribute with
the same name is declared CDATA
and doesn't contain a string that
can be parsed as NUMBER
).
A result element is allowed to occur in the result markup according to the standard rules for tag validation; ie. if either
it is accepted as regular content token at the result context position, or
it is accepted as an included element at the result context position, or
the result context position has declared content ANY
, and the element
isn't in the set of excluded elements at the result context position, or
the result context position refers to an implied-ANY
element
(ie. an element not declared in the result DTD, and treated as if it were
declared ANY
because IMPLYDEF ELEMENT YES
is specified or implied in/by
the SGML declaration)
Simple LPDs contain only a single link attribute declaration and/or entity declarations:
<!LINKTYPE lpd-name #SIMPLE #IMPLIED [
[entity-declarations]
[link-attribute-declaration]
]>
(having SIMPLE #IMPLIED
in place of the source and result DTD name,
respectively),
Link attributes must be declared on the document element (the root element) of the base DTD (the first DTD) in the containing document. Template notations in simple LPDs aren't supported; instead, simple LPDs are used to provide document-wide properties in a simple item-value format to auxiliary purposes such as e.g. HTTP delivery parameters.
Simple links can also be used for entity preemption.
The prolog of an SGML file can contain multiple document type declarations and link process declarations. More than a single explicit link process (or none at all) can be active at any point in time. If multiple link processes are active, the result markup of a link process is used as input markup to another link process, in turn, such that multiple active link processes can form a pipelie of link processes, with the ultimate result markup that of the link process placed last in the chain. To form a pipeline, the result document type of the first link process must match the source document type of the second. However, only a single implicit link process can be active at any point in time. If one or more explicit link processes are active, a single implicit link process can be active in addition; the single active implicit link process, if any, is always the last link process in a pipeline of possibly more than a single link process.
Activation of a link process can be requested from the SGML processor by supplying the name(s) of link processes to activate (provided the name list meets the above criteria). Practically, when invoked via the command line, a command line argument is supplied listing the link process(es) to activate.
Alternatively, the SGML processor can be told to determine a link pipeline based on a requested target document type name. When the SGML processor is told to produce a given target document type name, it considers the base document type and the explicit link processes declared in the document to arrive at a pipeline of one or more link processes to activate that produces the requested target document type name.
For example, the prolog of the following document declares
the lnk1
, lnk2
, and lnk3
link processes, along with
document type names for the base document type and the
document types produced as intermediate results of the
link processes:
<!DOCTYPE doc [
<!ELEMENT doc - - (#PCDATA)>
]>
<!DOCTYPE out [
<!ELEMENT out - - (#PCDATA)>
]>
<!DOCTYPE out2 [
<!ELEMENT out2 - - (#PCDATA)>
]>
<!DOCTYPE out3 [
<!ELEMENT out3 - - (#PCDATA)>
]>
<!LINKTYPE lnk1 doc out [
<!-- ... -->
<!LINK #INITIAL doc out>
]>
<!LINKTYPE lnk2 out out2 [
<!-- ... -->
<!LINK #INITIAL out out2>
]>
<!LINKTYPE lnk3 out2 out3 [
<!-- ... -->
<!LINK #INITIAL out2 out3>
]>
<doc>Text</doc>
When the SGML processor is instructed to produce markup
with the out3
target document type name, it will
activate the lnk1
, lnk2
, and lnk3
link process
resulting in out3
markup as ultimate result markup.
Note the ability to activate a particular number of link processes, such as 3 in this case, is determined by the processors hard limit of supported simultaneous link processes.
As an additional feature of LPDs, any LPD (including simple LPDs) can declare entities. Entities declared in a LPD override ("preempt") those declared in the document's DTD having the same name (but LPDs can also contain private entities that don't preempt DTD entities).
For example, the following document contains a very basic simple LPD in addition to a DTD:
<!doctype html [
<!entity visitor-name "Unknown">
]>
<!linktype myformat #simple #implied [
<!entity visitor-name "Chef">
]>
<html>
<body>
<p>Hello, &visitor-name</p>
</body>
</html>
The effective value of the visitor-name
entity is Chef
, when the
myformat
LPD is active.
More generally, the effective value for a given entity is declared by the entity declaration that gets processed first. When processing a document, SGML first processes all active LPDs, in the order they appear in the document prolog; then SGML processes the base (first) DTD. SGML performs these steps in a separate pass before considering other markup declarations. Therefore, a link declaration set may reference parameter entities declared in a DTD, or in an active link set declaration preceding it in the document prolog. Moreover, a DTD can reference parameter entities declared in an active link declaration set.
As a special rule, sgmljs.net tolerates parameter entity
references in marked section keywords in link declaration
sets without a prior declaration as of the order described above.
The replacement text of those (yet) unresolved parameter entities
is considered the empty string until a declaration is established
(in the described order). Moreover, while marked sections with an
empty keyword are treated as if INCLUDE
were used as keyword,
marked sections within link process declarations are treated
as if IGNORE
were used as keyboard.
This feature can be used to obtain replacement text for parameter entity references from a DTD, without having to declare (and thus preempt) those in a LPD.
For example, in the following document, when the L
link process is active, the replacement text for %e
(and thus e
) will be from DTD
, because the replacement
text for the include-ignore
parameter entity is only
established in the DTD, thus will be treated as IGNORE
in the marked section within the link declaration set:
<!DOCTYPE D [
<!ELEMENT D - - (#PCDATA)>
<!ENTITY % include-ignore "INCLUDE">
<!ENTITY % e "from DTD">
<!ENTITY e "%e">
]>
<!LINKTYPE L #SIMPLE #IMPLIED [
<![ %include-ignore [
<!ENTITY % e "from LPD">
]]>
<!ATTLIST D a CDATA #FIXED "a">
]>
<D>&e</D>
There's a special portability idiom to achieve the same result using third-party SGML software (SP/OpenSP) which treat entity preemption slightly different:
<!DOCTYPE D [
<!ELEMENT D - - (#PCDATA)>
<!ENTITY % include-ignore "INCLUDE">
<!ENTITY % e "from DTD">
<!ENTITY e "%e">
]>
<!LINKTYPE L #SIMPLE #IMPLIED [
<![ %include-ignore [
<!ENTITY % include-ignore "IGNORE">
<![ %include-ignore [
<!ENTITY % e "from LPD">
]]>
]]>
<!ATTLIST D a CDATA #FIXED "a">
]>
<D>&e</D>
IDLINK
linkset
Implicit and explicit LPDs can contain a single IDLINK
link set
declared as follows
<!IDLINK link-rule [link-rule] ...>
where link rule is an item of the form
id element [#POSTLINK target] [#USELINK target] [ attr=value ... ]
(for implicit LPDs), or
id element [#POSTLINK target] [#USELINK target] [ attr=value ... ]
result-element [ result-attr=value ... ]
(for explicit LPDs).
Link rules in IDLINK
sets are matched on elements of the respective type when the element
has an ID
attribute declared in the DTD, and the ID
value specified on the element matches
the id
declared in the link rule.
Elements matching a link rule in the IDLINK
link set have their link and
result attributes always determined by the matching link rule in the IDLINK
link set in preference to any matching link rules in the current link set.
At any point in time when processing a SGML document, a link process
has a current link set; the initial current link set at the start
of the document is the #INITIAL
link set.
When processing an element, the link process inspects the current link set to check if it contains one or more link rules for the element being processed, ie. if the name of the element to process occurs as the element (or as one of the elements in the name group) of a link rule. If so, it proceeds with link rule selection and link attribute determination as described below.
Otherwise, if an element isn't matched by any link rule in the current link set, no link attributes are inferred for that element.
Note that the SGML standard describes a fallback mechanism where link attributes are determined by a parent or predecessor link set, but neither sgmljs.net nor other SGML software implements this behaviour.
Once a link processor has established that a link set contains link rules for the element being processed, it determines the specific link rule (of potentially multiple link rules) to apply as follows:
if the current link set has a single link rule for the element to process, then that single link is selected
if it has multiple link rules for the element to process (ie. if the element to process appears as element or in the name group of more than one link rule), the link attribute specifications of the applicable link rules are checked to select a single rule; if any link rule specifies a link attribute with the same name as a content attribute on the respective element, and the content attribute value for the current element has the same value as specified in the link rule, then the first such rule, in the order specified in the link set, is selected; as a special rule, a content attribute that is declared, but not specified in content, matches a link attribute rule specifying an empty string literal value for that attribute
To ensure that a single link rule can always be selected by the above algorithm, sgmljs.net performs the following checks, depending on "strict" or "non-strict" (the default) processing mode.
In strict mode, sgmljs.net checks that any link rule specifying a link attribute having the same name as a DTD attribute is part of a set of multiple rules for the respective element in the link set, and that for any link set with multiple link rules for the same element,
each link rule, of the multiple link rules applying to the same element, has one or more link attributes specified (as required by standard SGML syntax), and, moreover,
each link rule, of the multiple link rules applying to the same element except the last, specifies at least one attribute that has the same name as a content attribute declared on the respective element in the DTD, and
the last link rule (in the order appearing in the link set) doesn't have link attributes specified that have the same name as a DTD attribute.
In non-strict mode, sgmljs.net checks that
each link rule, up to the last, of mutliple link rules applying to the same element, has one or more link attributes specified,
like above, each link rule, of the multiple link rules applying to the same element except the last, specifies at least one attribute that has the same name as a content attribute declared on the respective element in the DTD, and
the last link rule doesn't have link attributes specified at all.
Link attribute value(s) specified in the selected rule, if any, are implied as link attribute values(s) for the element being processed.
If no value for a link attribute (ie. of those declared as attributes for the element in the LPD) is specified in the link rule, then the attribute default declared in the attribute declaration in the LPD, if any, is implied as value for that link attribute.
If the selected link rule contains a #POSTLINK
clause, the target
link set name of the #POSTLINK
clause is set as the current link set
for any elements after the end-element event of the current element has
been processed; ie. the #POSTLINK
target applies to immediately following
sibling elements, and their descendant elements (until another #USELINK
or #POSTLINK
target is set as the current element). On the end-element event
for the parent element of the current element, the current link set is reset
to that of the parent element, or the parent element's #POSTLINK
target,
if it has one.
If the selected link rule contains a #USELINK
clause, the target
link set name of the #USELINK
clause is set as the current link set
for any child element of the current element; otherwise, the current
link set name isn't changed for child element content.
A #USELINK
or #POSTLINK
target may specify #EMPTY
in place of
a link set name, in which case no output markup events are generated
for child content or following-sibling content, respectively, of the
element being processed.
When #EMPTY
is the current link set, neither start-element events
nor character data events are produced to the output; otherwise,
character data is delivered to the output provided it is accepted
at the output context position, even when the containing element
wasn't covered by a link rule in an explicit link process, and
hence didn't produce a result markup element.
In sgmljs.net SGML, consistent with the SGML standard, a #USELINK
or #POSTLINK
target must not specify #INITIAL
in place of a
link set name. Other SGML systems might support #INITIAL
in
place of a named link set, in which case the current link set of the
child content, or following-sibling content, respectively, is set to
the #INITIAL
link set containing the link rules effective at the
document element of the document being processed.
A link attribute having NOTATION declared value, when determined to have a value in the link attribute determination step described anove, can specify special processing. In sgmljs.net SGML, when a NOTATION declared link attribute is assigned the name of a notation having the SGML public identifier, then the assigned notation's system identifier is used as a template notation.
When the assigned notation has data attributes with the same name as link attributes declared on the element on which the notation is assigned as template, then the link attribute values are supplied as the respective data attributes for the notation/template application. Moreover, the processor passes child content of the element on which templating is invoked to the template processing context.
The DAFE feature allowing data attributes to have their values populated by content or link attributes is part of ISO/IEC 10744 (HyTime 2nd ed.).
See the next chapter for template processing details.
sgmljs.net SGML applies an additional feature of DAFE (also as specified by ISO/IEC 10744):
If a notation is applied in a link process, the
special NotNames
link attribute is evaluated, and is
expected to specify space-separated pairs of attribute
names where the respective first attribute name is the
name of a data attribute for the notation applied, and
the second is the name of a link attribute which should
serve as the source attribute for that data attribute
(eg. in this capacity, NotNames
can populate data attributes
from link attributes with different names). Note, however,
sgmljs.net SGML does not support general aliasing and
renaming attributes for use as data attributes. Only the
two following special values for NotNames
are supported:
`#NOTCONT <attribute>`
and
`<attribute> #CONTENT`
If the token #NOTCONT
is used in place of the first
attribute, then sgmljs.net SGML populates the notational
content from the specified attribute name.
If the token #CONTENT
is used in place of the second
attribute, then sgmljs.net SGML populates the specified
attribute with the element text content of the context
element where it is applied.
As an example for the former, the following declares a
notation and arranges for the content
data attribute
to be provided as notational content:
<!NOTATION nt ...>
<!ATTLIST #NOTATION nt
content CDATA #IMPLIED
NotNames CDATA #FIXED "#NOTCONT content">
This chapter introduces SGML templates. SGML templates provide a more advanced technique of transcluding content from foreign documents or other resources (in addition to plain parsed references) with support for supplying template parameters from the document where the template is transcluded.
SGML templates do not introduce new SGML syntax, but makes use of SGML notations and other SGML constructs.
Any plain SGML document can be used as SGML template. A template SGML document typically (but not necessarily) will use system-specific entities in uppercase letters to refer to values obtained from the environment/document where the template is transcluded.
For example, the following hypothetical SGML document, greeting.sgm
can be used as a template receiving the guest-name
and
number-of-new-messages
parameters (using #CONREF
entity expansion
as explained above):
<!doctype div system [
<!entity GUEST-NAME system>
<!entity NUMBER-OF-NEW-MESSAGES system>
]>
<div>Hello, &GUEST-NAME. You have &NUMBER-OF-NEW-MESSAGES new messages</div>
A document, master.sgm
, making use of the above template can look like this
<!doctype html [
<!attlist div template entity #conref>
<!entity msg "placeholder message">
]>
<!linktype web #simple #implied [
<!notation sgml
public "ISO 8879:1986//NOTATION Standard Generalized Markup Language (SGML)//EN">
<!entity msg system "greeting.sgm" ndata sgml [ guest-name="Max" number-of-new-messages=3 ]>
]>
<html>
<body>
<div template=msg>
</body>
</html>
The SGML processor, when processing the master.sgm
file with the web
link process activated (and when told to output HTML), will produce the
following output:
<!doctype html>
<html>
<body>
<div>Hello, Max. You have 3 new messages</div>
</body>
</html>
In the example shown the SGML processor performs the following steps
to produce the output (making use of #CONREF
entity peemption):
the DTD for the file being processed, master.sgm
, declares a
content reference (#CONREF
) attribute with ENTITY
declared
value for the template
attribute on the div
element; this
tells the processor to treat div
elements as EMPTY
when the
template
attribute is used
the declaration for the msg
entity in the LPD preempts
(overrides) the declaration in the DTD so the dummy declaration
for msg
in the DTD gets ignored; the msg
entity
is declared in the LPD as an entity in the sgml
notation,
which, in turn, by reference to the SGML public identifier
ISO//...
, indicates to the processor to handle the notation
as SGML template
the processor, when encountering the div
attribute, will
start an SGML processing sub-context using msg
's system
identifier greeting.sgm
as file to process; the guest-name
and number-of-new-messages
processing parameters, supplied
via data attribute on the msg
entity declaration,
are declared as the GUEST-NAME
and NUMBER-OF-NEW-MESSAGES
system-specific entities, respectively, in the template's DTD,
for reference from template content
Note that GUEST-NAME
and NUMBER-OF-NEW-MESSAGES
must
be uppercase; this is because SGML's default settings
SYNTAX NAMECASE GENERAL YES
and SYNTAX NAMECASE ENTITY NO
treat attribute names (and element, notation names, and
name tokens in enumerated attributes) as if an uppercase
value had been specified even if a lowercase or mixed-case
spelling had been used, whereas for entity names no case-folding
is applied (they're treated as-is and eg. ent
is a different
entity than ENT
). Since templating exposes attributes of
a master document as system-specific entities in a template
document, unless settings for SYNTAX NAMECASE GENERAL
and SYNTAX NAMECASE ENTITY
are set explicitly to match,
the template will receive system-specific entities in
uppercase (case-normalized) form. Hencee, it is recommended
to always use template parameters in all-uppercase spelling
which avoids any problems.
Note case-folding of attributes (and elements and notations etc.) is not visibile when outputting HTML (the default), as HTML serializiation will always output the lowercase form for names (the preferred form for HTML), even if internally any name is case-folded to the uppercase form.
The same template as in the previous example, greeting.sgm
, can
alternatively be invoked as a template notation (instead of as
an entity as shown in master.sgm
) like this:
<!doctype html [
<!-- can be left empty -->
]>
<!linktype web html #implied [
<!notation sgml
public "ISO 8879:1986//NOTATION Standard Generalized Markup Language (SGML)//EN">
"greeting.msg">
<!attlist #notation sgml
guest-name cdata #implied
number-of-new-messages cdata #implied>
<!attlist div
n notation (sgml) #fixed sgml
guest-name cdata #fixed "Max"
number-of-new-messages cdata #fixed "3">
]>
<html>
<body>
<div guest-name="Max" number-of-new-messages="3"></div>
</body>
</html>
The SGML processor will process the document as follows, producing the same output as in the previous example:
the processor handles notations declared by reference to
the SGML public identifier as template notation and uses the
system identifier greeting.sgm
of the template notation as
template file name; moreover, template parameters are represented
as data attributes declared on the template notation
the LPD assigns the sgml
notation to the n
link attribute,
informing the processor that it should apply the greeting.msg
template on every div
element
the LPD also assigns the guest-name
and number-of-messages
link attribute with the #FIXED
values from the link attribute
declarations
the processor extracts data attributes as template parameters
from link attributes having the same name as data attributes;
ie. the template parameter guest-name
is populated from the
link attribute guest-name
Alternatively, and more usefully, template parameters can be extracted from content attributes as follows:
<!doctype html [
<!attlist div
guest-name cdata #implied
number-of-new-messages cdata #implied>
]>
<!linktype web html #implied [
<!notation sgml
public "ISO 8879:1986//NOTATION Standard Generalized Markup Language (SGML)//EN"
"greeting.sgm">
<!attlist #notation sgml
guest-name cdata #implied
number-of-new-messages cdata #implied>
<!attlist div
n notation (sgml) #fixed sgml
guest-name cdata #implied
number-of-new-messages cdata #implied>
]>
<html>
<body>
<div guest-name="Max" number-of-new-messages="3"></div>
</body>
</html>
As an extension of the example before, in particular, the document body may
contain multiple div
elements with different attributes, which will result
in multiple template applications to be produced to the output. For example,
...
<html>
<body>
<div guest-name="Max" number-of-new-messages="3"></div>
<div guest-name="Maria" number-of-new-messages="5"></div>
</body>
</html
will produce
...
<html>
<body>
<div>Hello, Max. You have 3 new messages</div>
<div>Hello, Maria. You have 5 new messages</div>
</body>
</html
So that the SGML processor can supply a template parameter from a content attribute,
the content attribute (DTD attribute) must be declared on the element on which the template is applied, and
a data attribute having the same name as the content attribute must be declared on the template notation,
and (as already shown in the notation examples before)
a NOTATION
link attribute must be declared on the element,
and assigned a notation that is declared using
the SGML public identifier, or a notation that derives
from a notation using the SGML public identifier (see below)
the template notation must declare a system identifier for locating the template.
As shown in the example before, sgmljs.net recognizes those notations as templates notations that are declared with the SGML public identifier
ISO 8879:1986//NOTATION Standard Generalized Markup Language (SGML)//EN
When declaring more than one template notation, multiple notation names and declarations must be used so that the system identifiers containing the file names for each template can contain paths to the different locations of the respective template notations, and so that different sets of data attributes can be declared as required.
There is an alternative to declaring the SGML public identifier directly on a notation for it to be treated as template notation:
<!notation sgml
public "ISO 8879:1986//NOTATION Standard Generalized Markup Language (SGML)//EN">
<!notation mytemplate system "my-template.sgm">
<!attlist #notation mytemplate superdcn name #fixed sgml>
This declares the sgml
notation by just using the SGML public identifier,
ie. omitting the system identifier, then declares a template notation,
mytemplate
, in a separate declaration. The mytemplate
notation is recognized
by sgmljs.net as a SGML template notation because it has the superdcn
attribute
declared, and the value of the superdcn
atttribute is set (as #FIXED
value)
to the name of a notation declared with the SGML public identifier.
When using a template notation in content, as shown in the example where
the template extracts content attributes, a template notation can also
receive child content of the element on which the template is invoked.
The template receives child content of the master context via it's
standard input, and can access it using the <osfd>0
system identifier.
For example, when using the following fragment in the same context as above
<div guest-name="Max" number-of-new-messages="3">
<p><h3>Message 1</h3><p>Bla bla blah ... </p>
<p><h3>Message 2</h3><p>...</p>
<p><h3>Message 3</h3><p>...</p>
</div>
the following template references the child content of the div
element from the master context via the content
entity as follows
(adding a h2
before it):
<!doctype #implied system [
<!entity content system "<osfd>0">
<!entity guest-name system>
<!entity number-of-new-messages system>
]>
<div>Hello, &guest-name. You have &number-of-new-messages new messages</div>
<h2>Details</h2>
&content
</div>
Since child content of elements on which templates are implied
are captured as notational content for supply to subsequent
processing pipeline stages, link rules descending from a state
where a template is applied, as transitioned-to via #USELINK
targets from a link rule that implies a template, are not reached.
Once a template is applied, no further link state propagation is
performed on child content of the element on which the template is
applied within the invoking link process. Link rules implying
templates are effectively treated as though they were declared
with #USELINK #EMPTY
.
Output of a template application is produced in a separate SGML processing context invocation on the template notation or entity as main file, and such that each data attribute declared and supplied in the master context can be accessed as a system-specific general or parameter entity.
Child content of the element on which the template is applied
is captured in the master context as the sequence of normalized
markup events (generated according to the master context's parsing
rules declared in markup and SGML declarations), and is serialized
to a character stream which is supplied to the template via <osfd>0
.
A template produces an element with the same name as that on which the template is applied. Moreover, generated template child content must be valid in the master context into which it is included.
The master context supplies the element on which a template is applied as the target document type name to the template processing sub-context (see Multiple link processes).
The sub-context will then either
parse the template document with respect to its base
document type, if the base document type name matches the requested
target document type name, or if the base document type
name is #IMPLIED
, or
otherwise, determine a link pipeline from the link processes declared in the template document, and from those supplied as implied link processes from the master context, (see Use of templates in multi-stage processing pipelines) such that the result document element of the link pipeline matches the requested target document type name (eg. the element on which the template is applied in the master processing context)
The SGML processor enforces this by requiring that the template
uses <!DOCTYPE ... SYSTEM ..
as DTD, ie. the template
must include the markup declarations of the master context
by referencing a system-specific external subset
that the master context sets up for the template context.
The template may declare its DTD either using
<!DOCTYPE element SYSTEM ...
,
where element
is the element
on which the template is applied, or
<!DOCTYPE #IMPLIED SYSTEM ...
, which makes the template
processing context determine the document element from the
first content element in the template document (which must
be the element on which the template is applied)
By the resolution rules for system-specific entities, the template processing context picks up the prescribed markup declarations that the master context has created via a file name generated from the template document element.
For example, if the template document element is div
,
the template processing context accesses the external subset
by reading the file div.dtd
. The file is looked up in a
directory that the master context created and supplied for the
template invocation, and in which it has placed the div.dtd
file containing markup declarations that the template are
parsed with and that the template has to conform to.
As a consequence, if the template doesn't use the expected element for its document element (the element name on which the template is applied), it will fail to locate the file for the external subset in the directory provided by the invoking master context.
Markup declarations received by a template processing context from an invoking master context don't contain entity declarations, short reference map declarations, and short reference use declarations. Moreover, parameter entity reference in the received declaration set are pre-expanded into the replacement values used by the master context.
The following restrictions apply to documents included as strict templates:
documents included as strict templates cannot declare
and/or use data entities; normally, data entity references (other
than for CDATA
data entities) are serialized as-is (as reference,
rather than as expanded text) to the output, but a template's
data entities aren't declared in the master's DTD, nor are
the data entities declared in a master's DTD visible to
the template so references to data entities are rejected
in template content
documents included as strict templates cannot use
referential attributes (those with #CURRENT
default, or with
ID
, IDREF
, IDREFS
, ENTITY
, ENTITIES
, or NOTATION
declared value) because these interfere with the master's
context such that invalid markup could be produced
an element on which a strict template is applied must have declared exclusion exceptions that are at least as strict as those effective on the element in the master context where the template is applied, if any; that is, the exclusion exceptions declared in the master context's DTD on the element on which a strict template is applied must exclude all elements which are contextually excluded at the position where the template is applied in the invoking master context (ie. not only on the element directly but also on it's parent elements)
documents included as strict template shouldn't use
element declarations; declaring and using new elements from
within a template will produce invalid markup if the
master context hasn't the IMPLYDEF ELEMENT YES
feature;
note the master context is expected to enforce this by
declaring e.g. a content model on the element on which the
template is applied (rather than allowing ANY
content on
it); by declaring a content model on the template element,
template processing can't place elements that are undeclared
in the master as template child content; note that
template processing itself (when not constrained by the master DTD)
does not enforce that no element is used which is
declared in the template and this enforcement must be
expressed by the master DTD
documents included as strict templates don't apply short reference replacement, unless short reference map and short reference use declarations are present in the internal subset or other explicit declarations in the strict template.
Note documents included as strict template can (by default)
declare and introduce new attributes, since the
IMLYDEF ATTLIST YES
feature is set by default, and
output serialization will always produce a normalized
attribute specification output (such that e.g. short forms
of attribute specification in a template are always serialized
in canonical form to the output, irrespective of what short
forms are supported in the master context output).
In "lax" templates, the template doesn't have to declare it's
DTD using <!DOCTYPE ... SYSTEM ...
, but must use an external
subset with the same system identifier as the external
subset that the invoking master context uses.
The template accesses any markup declarations that it shares with the invoking master context via regular processing of markup declarations in the shared external subset. Parameter entity reference in the external subset are not pre-expanded, but are expanded in the template processing context. Note this means that expanded values for parameter entities in the template processing context could be different from those of the master processing context.
Lax templates, in general, aren't guaranteed to produce content that is valid according to the DTD of the invoking master process; instead, this must be ensured by proper DTD and/or template authoring.
A driving use case for lax templates is to propagate context-sensitive exclusion exceptions into template processing contexts. In order to make use of this, the used DTD must play along (have a placeholder where exceptions are to be inserted), and we need a way to materialize, into a data attribute, the exclusions effective at a given template expansion place.
The intent of the following hypothetical markup declarations
is to allow <script>
anywhere inside <sub>
except
when descending from <usercontent>
. The template is invoked
on <sub>
, thus allowing <script>
and we want to make it so
that it isn't allowed in the markup declarations the template
is using:
<!-- doc.dtd -->
<!element doc - - (sub|p|usercontent)+>
<!element sub - - (p+) +(script)>
<!element p O O (b|i|#pcdata)+>
<!element b - - (#pcdata)>
<!element i - - (#pcdata)>
<!element script - - cdata>
<!attlist sub ref entity #conref>
<!element usercontent - - (sub+) -(script)>
<!-- master.sgm -->
<!doctype test system "doc.dtd" [
<!entity template "doesn't matter">
]>
<!linktype lnk [
<!entity template system "template.sgm" ndata sgml>
]>
<doc><sub>blabla</sub><usercontent><sub ref=template></usercontent></doc>
<!-- (lax) template.sgm -->
<!doctype test system "doc.dtd">
<sub>formatted user contributed content</sub>
To implement enforcement of the contextual constraints on sub
,
as used in child content of usercontent
elements, we change
the DTD to use the script_or_noscript
parameter entity for
holding the exception string used in the DTD, ie. +(script)
in
the master's view of the DTD, and -(script)
in the templates
view, supplying the exception string
-(script)` as template
parameter in the latter case:
<!-- doc.dtd -->
<!element doc - - (sub|p|usercontent)+>
<!entity % script_or_noscript "+(script)">
<!element sub - - (p+) %script_or_noscript>
<!element p O O (b|i|#pcdata)+>
<!element b - - (#pcdata)>
<!element i - - (#pcdata)>
<!element script - - cdata>
<!attlist sub ref entity #conref>
<!element usercontent - - (sub+) -(script)>
<!-- master.sgm -->
<!doctype test system "doc.dtd" [
<!entity template "doesn't matter">
]>
<!linktype lnk [
<!notation template_notation public "... SGML pubid ...">
<!attlist #notation template_notation script_or_noscript cdata #required>
<!entity template system "template.sgm" ndata template_notation [script_or_noscript="-(script)">
]>
<doc><sub>blabla</sub><usercontent><sub ref=template></doc>
<!-- (lax) template.sgm -->
<!doctype test system "doc.dtd" [
<!entity % script_or_noscript system>
]>
<sub>formatted user contributed content</sub>
Note that if we had placed +(script)
on doc
, and don't
the template wouldn't be allowed to use <script>
either
because it's only introduced on doc
and the template
doesn't start on <doc>
hence can't use <script>
Similarly, other limitations of strict templates can be
solved using parameter entity techniques such as
changing REFID
attributes (in the master's DTD view) into
enumerated value attributes (in the template's view), or
changing ID
attributes into #FIXED
attributes.
Strict templates using an empty document prolog (which is interpreted
as <!doctype #implied system>
when the IMPLYDEF DOCTYPE YES
feature
is active) can be specified inline, rather than in an external file,
like this (using a literal storage manager FSI):
<!doctype doc [
<!element doc - - (sub+)>
<!element sub - - (#pcdata)>
<!attlist sub ref entity #conref>
<!entity e system "doesn't matter">
]>
<!linktype lnk #simple #implied [
<!notation sgml public "ISO 8879:1986//NOTATION Standard Generalized Markup Language (SGML)//EN">
<!entity e system "<literal><sub>text from referenced entity</sub>" ndata sgml>
]>
<doc><sub ref=e></doc>
Inline templates can reference template parameters as general entity
references: when IMPLYDEF ENTITY YES
is effective, any undeclared entity
is implicitly declared system-specific, ie. treated as if it were declared
<!ENTITY ent SYSTEM>
. So if a template doesn't make use of parameter
entities or other markup declarations, it can omit the document prolog and
still reference template parameters. Note that parameter entities are not
subject to IMPLYDEF ENTITY
and must always be explicitly declared.
A template is processed in an isolated SGML processing context: the result of a template application can always be produced by processing the applied template SGML document in isolation, with supply of the same system-specific entities to the processing context as in a template application from an invocation context.
As a consequence, since the result markup of a template application is not fed-back into the invocation context. unlike result markup generated directly by link rules without templating, the result of a template application is not visible to the invocation processing context where the template is applied.
As a natural extension to the basic model for executing templates in processing sub-contexts by propagating DTD declarations into the sub-context, pipelining template result markup into downstream link processes is realized as propagating and activating link processing rules captured from a template invocation context into the processing subcontext executed on templates for link processing subcontexts.
An (explicit) link process, when part of a pipeline of multiple link processes, considers the activated link process following after it in the pipeline, if any, and derives a new link process from subsequent link process declarations and state at the context position as follows:
the current link state (the link rules declared for
the current link set name at the context position where
the template is applied) is reproduced as #INITIAL
link set in the subcontext for the respective stage;
if the current link set is a named link set (eg.
not the #INITIAL
link set), the declaration is
replicated in addition
effective notation and link attribute declarations of the link process in the context of the invocation are copied over to the target link set declaration
For example, in the following document, the lnk2
(implicit) link process follows the lnk1
(explicit)
process:
<!DOCTYPE a [
<!ELEMENT (a|b) - - ANY>
]>
<!DOCTYPE x [
<!ELEMENT (x|y) - - ANY>
]>
<!LINKTYPE lnk1 a x [
<!NOTATION t SYSTEM "t.sgm"
PUBLIC "ISO 8879:1986//NOTATION Standard Generalized Markup Language (SGML)//EN">
<!ATTLIST b template NOTATION (t) #IMPLIED>
<!LINK #INITIAL
a x -- map a to x --
b [ template=t ] y -- apply t on b -->
]>
<!LINKTYPE lnk2 x #IMPLIED [
<!NOTATION x SYSTEM "s.sgm"
PUBLIC "ISO 8879:1986//NOTATION Standard Generalized Markup Language (SGML)//EN">
<!ATTLIST y template NOTATION (s) #IMPILIED>
<!LINK #INITIAL x #USELINK in-x-content>
<!LINK in-x-content y [ template=s ]>
]>
<a><b></b></a>
If both the lnk1
and lnk2
processes are activated,
when lnk1
applies the t
template on the b
element
from input markup, the current link set of the lnk2
link process at the context position is the in-x-content
link set. lnk1
replaces the b
element by the result
of processing the following document:
<DOCTYPE y>
<!LINKTYPE lnk2 y #IMPLIED [
<!NOTATION x SYSTEM "s.sgm"
PUBLIC "ISO 8879:1986//NOTATION Standard Generalized Markup Language (SGML)//EN">
<!ATTLIST y template NOTATION (s) #IMPILIED>
<!LINK #INITIAL in-x-content y [ template=s ]>
<!LINK in-x-content y [ template=s ]>
<y></y>
with activated link process lnk2
, honoring the link process
automaton state at the context position.
Note propagation of explicit link processes to template subcontexts is only available in sgmljs.net Pro.
For explicit link processes as the second or subsequent link process following a link process applying a template, the following restrictions apply
the result document type name of any active explicit link process following a link process containing a template application must be the same as the source document type name, and
the link rule at the context position of any explicit link process following a template application must be an identiy mapping, eg. the target element must be the same as the source element
Link rules to inherit can branch on a filter attribute
or IDLINK
in such a way that the link state transitions to
a new current link set via #POSTLINK
. Therefore, link/template
processing captures the link state of an inherited link process
at the context position, honoring the current link state in
the chained link process.
For example, consider a link set declaration for lpd2
using #POSTLINK
to toggle between link states to apply
(further) templating on content received
from upstream processing such that different templates
are applied on occurence of x
elements with odd and
even count, respectively:
<!LINKTYPE lnk2 out #IMPLIED [
<!NOTATION odd
P PUBLIC "ISO 8879:1986//NOTATION Standard Generalized Markup Language (SGML)//EN"
"odd.sgm">
<!NOTATION even
PUBLIC "ISO 8879:1986//NOTATION Standard Generalized Markup Language (SGML)//EN"
"even.sgm">
<!ATTLIST x template NOTATION (odd|even) #IMPLIED>
<!LINK #INITIAL out #USELINK odd>
<!LINK odd x #POSTLINK even [ template=odd ]>
<!LINK even x #POSTLINK odd [ template=even ]>
]>
A template invocation in the lnk1
link process (coming
before the shown lnk2
link process) considers the link
state transitioned to on the templated element in the
inherited implicit link process, and will prepare a
link process declaration reflecting odd
or even
link rules in the propagated #INITIAL
link set.
Anticipating #POSTLINK
rules, however, is limited in that
the link state in the invocation context's idea of the
lpd2
link state is only driven by a bare element token
eg. without attributes, which would make a difference
if attributes are used as filter attributes, or matching
IDLINK
apply in the processing sub-context.
As a customization feature, a link process declared in an SGML document invoked as template with the same name as an inherited/activated LPD will result in the inherited markup declaration to be ignored, and the markup declarations present in the document prolog for the respective link declaration set to be used instead.
With regular propagation of link process declarations in sub-contexts (without overriding inherited markup in the template's document prolog), since only ever at most a single implicit link process is derived and propagated to sub-contexts, the result doctype of a link process declaration is always the same as its source doctype.
However, when using a custom LPD overriding the link process declarations inherited from a master context, no checking of the type of link process and its result markup document type is performed - an LPD overriding an inherited template can be an explicit link, hence can be declared to produce a document type different from the one expected at the context position in the invocation context, and thus produce invalid markup with respect to the master context document type.
CONREF
preemption and templating in pipelined templates
Note it's not necessary to handle #CONREF
templates in
chained subcontexts (and hence not necessary to propagate entity
declarations to subcontexts). This is because #CONREF
element
markup events are forwarded to subsequent pipeline stages/link
processes only with implicit LPDs. But SGML only allows
a single implicit LPD in a chain, and only as the last stage.
If a preempted #CONREF
entity is expanded in an explicit LPD,
on the other hand, then new result markup is created, and #CONREF
is not
handled on result markup of explicit links, being required to
come from actual content markup.
Templates can also be used for formatting query results from SQL or SPARQL databases.
SQL and SPARQL endpoints deliver query results in a tabular fashion, ie. as ordered result set of tuples (or rows), where a tuple is a set of item-value pairs mapping query column names to result value strings.
In query result formatting, the SGML processor invokes template processing on every row of a result set, and concatenates the produced markup of the (potentially more than one) template invocations into result markup.
Formatting query results involves
a query as a CDATA
data entity in a query notation (ie. either
in the SQL or he SPARQL notation as declared using either
the +//IDN sgml-cms.net//NOTATION sql-query
or the +//IDN sgml-cms.net//NOTATION sparql-query
public identifier, respectively), and
a formatting template which receives and accesses bound
column values as (system-specific) entities, and which
is specified on the query template as value of a
NOTATION
attribute.
For example, the following file, biblio.sparql
, contains
a SPARQL query for fetching bibliography data from an external
data source (in the vocabulary used by the Zotero blbliography
management application):
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX res: <http://purl.org/vocab/resourcelist/schema#>
PREFIX z: <http://www.zotero.org/namespaces/export#>
PREFIX dcterms: <http://purl.org/dc/terms/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT DISTINCT $item $resource $resourcetype $title $givenname $surname $name
FROM <zotero-bilbliography.rdf>
WHERE {
$item rdf:type z:UserItem.
$item res:resource $resource.
$resource rdf:type $resourcetype.
OPTIONAL {$resource dcterms:title $title}
OPTIONAL {$resource dcterms:creator $creator}
OPTIONAL {$creator rdf:type foaf:Person}
OPTIONAL {$creator foaf:givenname $givenname}
OPTIONAL {$creator foaf:surname $surname}
OPTIONAL {$creator foaf:name $name}
}
The following SGML document executes the query against the
zotero-bibliography.rdf
RDF file containing bibliography data
exported from Zotero, and formats the results via an inline
template:
<!DOCTYPE HTML [
<!ELEMENT HTML O O (DIV|P)+>
<!ELEMENT DIV - O (#PCDATA|P|SPAN)+>
<!ELEMENT P O O (#PCDATA|A)+>
<!ELEMENT SPAN - - (#PCDATA)>
<!ATTLIST SPAN PROPERTY CDATA #IMPLIED>
<!ELEMENT A - - (#PCDATA)>
<!ATTLIST A HREF CDATA #IMPLIED TITLE CDATA #IMPLIED>
<!ENTITY bibliography_rdf_graph_ns "http://zotero.org/users/local/Rk1rxAG1/items/">
<!ENTITY bibliography_rdf_graph_location "zotero-bibliography.rdf">
<!ATTLIST DIV REF ENTITY #CONREF PROPERTY CDATA #IMPLIED>
<!ENTITY bibliography "placeholder">
]>
<!LINKTYPE BIBLIOGRAPHY #SIMPLE #IMPLIED [
<!NOTATION SGML PUBLIC "ISO 8879:1986//NOTATION Standard Generalized Markup Language (SGML)//EN">
<!NOTATION BIBLIO PUBLIC "+//IDN sgml-cms.net//NOTATION sparql-query">
<!ATTLIST #NOTATION BIBLIO
SUPERDCN NAME #FIXED SGML
TEMPLATE NAME #REQUIRED
ENDPOINT CDATA #FIXED "roqet --quiet --results tsv --exec">
<!NOTATION BIBLIOENTRY
SYSTEM '<literal>
<div property="dcterms:creator">
<span property="foaf:givenname">&givenname</span>
<span property="foaf:surname">&surname</span>
<span property="foaf:name">&name</span></div>'>
<!ATTLIST #NOTATION BIBLIOENTRY
SUPERDCN NAME #FIXED SGML
GIVENNAME CDATA #IMPLIED
SURNAME CDATA #IMPLIED
NAME CDATA #IMPLIED>
<!ENTITY BIBLIOGRAPHY SYSTEM "biblio.sparql" NDATA BIBLIO [ TEMPLATE=BIBLIOENTRY ]>
]>
<html>
...
<h2>Bibliography</h2>
<div ref=bibliography>
</html>
As shown in the following sections, SPARQL and SQL queries can also be supplied inline as notational content (rather than via an external file).
Data attributes of a query notation (other than the template
data
attribute which is treated special as described) are supplied as
substitution variables to the SPARQL or SQL query processor and can be
referenced in the query notation code text in a similar way as entity
references in SQL code text.
For example, the following declaration of a SPARQL query notation
takes the color
query parameter and substitutes the supplied value
in place of the &color
parameter reference:
<!notation sgml ...>
<!notation query public "+//IDN sgml-cms.net//NOTATION sparql-query">
<!attlist #notation query
superdcn name #fixed sgml
template name #required
color cdata #required>
<!entity flower-by-color-query system "<literal>
PREFIX plants: <http://plants.org/plants-vocabulary-1.0/>
SELECT ?flower
WHERE { ?flower :color &color }"
ndata query [ template=... color="yellow" ]>
]>
Note that even though the &
(ampersand) character is used in SGML,
SPARQL, and SQL in a similar way, recognition and interpretation of
"entity references" in query notation content is still handled in a
query-notation specific way.
Note query parameters are supplied to the query processor and are not automatically supplied to the query result formatting template.
The SPARQL processor used by sgmljs.net will evaluate SPARQL queries against a local default tuple store (ie. database); see SPARQL examples on how to supply a specific SPARQL endpoint (IP address or DNS name or a particular RDF file) to query.
The same technique used for SPARQL can also be used with SQL. For example, the
following document formats the results of an inline SQL query to query
all stored names when using GENDER_CD
0 as query parameter (it also
demonstrates use of connection parameters):
<!DOCTYPE HTML [
<!ELEMENT HTML O O (DIV|P)+>
<!ELEMENT DIV - O (#PCDATA|P|SPAN)+>
<!ELEMENT P O O (#PCDATA|A)+>
<!ELEMENT SPAN - - (#PCDATA)>
<!ELEMENT A - - (#PCDATA)>
<!ATTLIST DIV REF ENTITY #CONREF PROPERTY CDATA #IMPLIED>
<!ENTITY femalenames "placeholder">
]>
<!LINKTYPE LISTBOOKS #SIMPLE #IMPLIED [
<!NOTATION SGML PUBLIC "ISO 8879:1986//NOTATION Standard Generalized Markup Language (SGML)//EN">
<!NOTATION SQLQUERY PUBLIC "+//IDN sgml-cms.net//NOTATION sql-query">
<!ATTLIST #NOTATION SQLQUERY
SUPERDCN NAME #FIXED SGML
TEMPLATE NAME #REQUIRED
GENDER_CD CDATA #REQUIRED
SQLITE_DB_FILE CDATA #REQUIRED>
<!NOTATION NAMEENTRY SYSTEM '<literal><div><span>&name</span></div>'>
<!ATTLIST #NOTATION NAMEENTRY
SUPERDCN NAME #FIXED SGML
NAME CDATA #IMPLIED>
<!ENTITY femalenames SYSTEM "<literal>
set colsep ' '
set underline off
connect 'Driver=SQLite;Database=&sqlite_db_file'
select name from names_tbl where gender_cd = cast('&gender_cd' as decimal);"
NDATA SQLQUERY [ TEMPLATE=NAMEENTRY GENDER_CD="0" SQLITE_DB_FILE="/Users/guesswho/Repositories/markdown-awk/test/test.db" ]>
]>
<html>
<div ref=femalenames>
</html>
When supplying values to SQL, the SGML processor will allways escape single quotes occuring in supplied values into double quotes.
SQL queries should always use received values as string literals, ie. in single quotes.