← all demos
xsl:stylesheet(
exclude-result-prefixes="dbe f fp m map v vp xs",
version="3.0",
xmlns:dbe="http://docbook.org/ns/docbook/errors",
xmlns:f="http://docbook.org/ns/docbook/functions",
xmlns:fp="http://docbook.org/ns/docbook/functions/private",
xmlns:m="http://docbook.org/ns/docbook/modes",
xmlns:map="http://www.w3.org/2005/xpath-functions/map",
xmlns:v="http://docbook.org/ns/docbook/variables",
xmlns:vp="http://docbook.org/ns/docbook/variables/private",
xmlns:xs="http://www.w3.org/2001/XMLSchema",
xmlns:xsl="http://www.w3.org/1999/XSL/Transform")
xsl:include(href="../environment.xsl")
vp:strmatch := '^(\$\P{Zs}+)\s*=\s*(.+)$'
vp:varmatch := '^(\$\P{Zs}+)$'
vp:profile-variables as map(*) := map:merge(($vp:dynamic-parameters, $dynamic-profile-variables))
vp:profile-value-map as map(xs:QName, xs:string*) :=
xsl:map
xsl:map-entry(key="xs:QName('xml:lang')", select="fp:profile-tokens($profile-lang)")
xsl:map-entry(
key="QName('','revisionflag')",
select="fp:profile-tokens($profile-revisionflag)")
xsl:map-entry(key="QName('','role')", select="fp:profile-tokens($profile-role)")
xsl:map-entry(key="QName('','arch')", select="fp:profile-tokens($profile-arch)")
xsl:map-entry(key="QName('','audience')", select="fp:profile-tokens($profile-audience)")
xsl:map-entry(key="QName('','condition')", select="fp:profile-tokens($profile-condition)")
xsl:map-entry(key="QName('','conformance')", select="fp:profile-tokens($profile-conformance)")
xsl:map-entry(key="QName('','os')", select="fp:profile-tokens($profile-os)")
xsl:map-entry(
key="QName('','outputformat')",
select="fp:profile-tokens($profile-outputformat)")
xsl:map-entry(key="QName('','revision')", select="fp:profile-tokens($profile-revision)")
xsl:map-entry(key="QName('','security')", select="fp:profile-tokens($profile-security)")
xsl:map-entry(key="QName('','userlevel')", select="fp:profile-tokens($profile-userlevel)")
xsl:map-entry(key="QName('','vendor')", select="fp:profile-tokens($profile-vendor)")
xsl:map-entry(key="QName('','wordsize')", select="fp:profile-tokens($profile-wordsize)")
vp:profile-attributes := map:keys($vp:profile-value-map)
match / -> document-node():
has-profile as string* :=
foreach map:keys($vp:profile-value-map):
<-- map:get($vp:profile-value-map, .)
choose:
when not(f:is-true($dynamic-profiles)) and empty($has-profile):
<-- .
else:
xsl:document
apply
match *:
choose:
when fp:profile-suppress(.):
else:
copy:
apply @*,node()
match attribute()|text()|comment()|processing-instruction():
copy
function fp:profile-tokens(profile as string*) -> string*:
foreach tokenize($profile, $profile-separator):
<-- if (normalize-space(.) = ''
or matches(., $vp:strmatch)
or matches(., $vp:varmatch))
then ()
else normalize-space(.)
function fp:dynamic-profile-tokens(profile as string*) -> string*:
foreach tokenize($profile, $profile-separator):
<-- if (matches(., $vp:strmatch)
or matches(., $vp:varmatch))
then .
else ()
function fp:profile-suppress(context as element()) -> boolean:
profile as map(xs:QName, item()+) :=
xsl:map
foreach $context/@*[node-name(.) = $vp:profile-attributes]:
name := node-name(.)
value := map:get($vp:profile-value-map, $name)
if f:is-true($dynamic-profiles) or exists($value):
xsl:map-entry(key="$name", select="(., $value)")
choose:
when map:size($profile) = 0:
<-- false()
else:
suppress as QName* :=
foreach map:keys($profile):
value := string(map:get($profile, .)[1])
tokens := subsequence(map:get($profile, .), 2)
ptokens := fp:profile-tokens($value)
if exists($tokens) and exists($ptokens)
and not($tokens = $ptokens):
xsl:message(use-when="'profile-suppress' = $v:debug")
"Suppressed"
<-- if ($context/@xml:id)
then node-name($context) || '/' || $context/@xml:id
else node-name($context)
<-- ':', $tokens, '!=', fp:profile-tokens($value)
<-- .
choose:
when exists($suppress):
<-- true()
when not(f:is-true($dynamic-profiles)):
<-- false()
else:
include as boolean* :=
foreach map:keys($profile):
value := map:get($profile, .)[1]
tokens := fp:dynamic-profile-tokens(string($value))
foreach $tokens:
if false() = fp:dynamic-include($context, .):
xsl:message
"Exclude"
<-- if ($context/@xml:id)
then node-name($context) || '/' || $context/@xml:id
else node-name($context)
<-- ':', .
if not(false() = fp:dynamic-include($context, .)):
xsl:message
"Include"
<-- if ($context/@xml:id)
then node-name($context) || '/' || $context/@xml:id
else node-name($context)
<-- ':', .
<-- fp:dynamic-include($context, .)
<-- false() = $include
function fp:dynamic-include(context as element(), expr as string) -> boolean?:
choose:
when matches($expr, $vp:strmatch):
var := replace($expr, $vp:strmatch, '$1')
value := replace($expr, $vp:strmatch, '$2')
<-- fp:check-profile($context, $var, $value)
when matches($expr, $vp:varmatch):
<-- fp:check-profile($context, $expr, ())
else:
<-- error($dbe:DYNAMIC-PROFILE-SYNTAX-ERROR,
'Unparseable: ' || $expr)
function fp:check-profile -> boolean?:
param context as element()
param variable as string
param expected-value as string?
expected-value := if ((starts-with($expected-value, '''')
and ends-with($expected-value, ''''))
or
(starts-with($expected-value, '"')
and ends-with($expected-value, '"')))
then substring($expected-value, 2, string-length($expected-value) - 2)
else $expected-value
xsl:try
actual-value as item()* :=
xsl:evaluate(
context-item="$context",
namespace-context="$context",
with-params="$vp:profile-variables",
xpath="$variable")
choose:
when exists($expected-value):
<-- $expected-value = ($actual-value ! string(.))
when ('no','false','0') = ($actual-value ! string(.)):
<-- false()
when ('yes','true','1') = ($actual-value ! string(.)):
<-- true()
else:
<-- true() = ($actual-value ! boolean(.))
xsl:catch(xmlns:err="http://www.w3.org/2005/xqt-errors")
xsl:message(select="$err:code, $err:description")
choose:
when $dynamic-profile-error = 'ignore':
<-- ()
when $dynamic-profile-error = 'include':
<-- true()
when $dynamic-profile-error = 'exclude':
<-- false()
when $dynamic-profile-error = 'error':
<-- error($dbe:DYNAMIC-PROFILE-EVAL-ERROR,
'Dynamic profiling error: ' || $variable)
else:
<-- error($dbe:INVALID-DYNAMIC-PROFILE-ERROR,
'Invalid $dynamic-profile-error: ' || $dynamic-profile-error)