Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
eoa-publication-model/stylesheets/rng_to_odd/rng_to_analysis/rng_to_dnf.xsl
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
291 lines (276 sloc)
9 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> | |
<stylesheet version="2.0" | |
xmlns="http://www.w3.org/1999/XSL/Transform" | |
xmlns:rng="http://relaxng.org/ns/structure/1.0" | |
xmlns:eoa="http://www.edition-open-access.de/ns" | |
xmlns:xs="http://www.w3.org/2001/XMLSchema" | |
exclude-result-prefixes="rng eoa xs" | |
> | |
<template | |
mode="rng_dnf_finish" | |
match="rng:group" | |
> | |
<variable name="new_children" as="element()*"> | |
<for-each select="*"> | |
<choose> | |
<!-- flatten nested groups --> | |
<when test="self::rng:group"> | |
<variable name="sub_group"> | |
<apply-templates mode="rng_dnf_finish" select="."/> | |
</variable> | |
<copy-of select="$sub_group/*/*"/> | |
</when> | |
<!-- do not copy "rng:empty" elements: --> | |
<when test="not(self::rng:empty)"> | |
<apply-templates mode="rng_dnf_finish" select="."/> | |
</when> | |
</choose> | |
</for-each> | |
</variable> | |
<copy> | |
<apply-templates mode="rng_dnf_finish" select="@*"/> | |
<copy-of select="$new_children"/> | |
<!-- if this is an empty group, write exactly ONE 'rng:empty' element --> | |
<if test="count($new_children[not(self::rng:empty)]) = 0"> | |
<element name="empty" namespace="{$rng_namespace}"/> | |
</if> | |
</copy> | |
</template> | |
<!-- throw error, if there are any non-toplevel 'rng:choice' elements --> | |
<template | |
mode="rng_dnf_finish" | |
match="rng:choice[not(parent::rng:element) and not(ancestor-or-self::rng:attribute)]" | |
> | |
<sequence select="eoa:error('rng_to_dnf', 'rng_dnf_finish: found choice which is not toplevel. (This indicates an internal error in the dnf calculation)')"/> | |
</template> | |
<template mode="rng_dnf_finish" match="@* | node()"> | |
<copy> | |
<apply-templates mode="rng_dnf_finish" select="@* | node()"/> | |
</copy> | |
</template> | |
<!-- replace "a?" ('rng:optional') by "(a | epsilon)" --> | |
<template | |
mode="rng_dnf_prepare" | |
match="rng:optional" | |
> | |
<element name="choice" namespace="{$rng_namespace}"> | |
<choose> | |
<when test="count(*) > 1"> | |
<element name="group" namespace="{$rng_namespace}"> | |
<copy-of select="*"/> | |
</element> | |
</when> | |
<otherwise> | |
<copy-of select="*"/> | |
</otherwise> | |
</choose> | |
<element name="empty" namespace="{$rng_namespace}"/> | |
</element> | |
</template> | |
<template mode="rng_dnf_prepare" match="@* | node()"> | |
<copy> | |
<apply-templates mode="rng_dnf_prepare" select="@* | node()"/> | |
</copy> | |
</template> | |
<!-- transform rng to "Disjunctive Normal Form" (DNF), e.g.: | |
(a|b)c(d|e) -> (acd) | (bcd) | (ace) | (bce) | |
--> | |
<template | |
mode="rng_to_dnf" | |
match="rng:choice[not(ancestor-or-self::rng:attribute)]" | |
> | |
<param name="depth" as="xs:string" select="''"/> | |
<variable name="normalized_children" as="element()*"> | |
<apply-templates mode="rng_to_dnf" select="*"> | |
<with-param name="depth" as="xs:string" select="concat($depth, ' ')"/> | |
</apply-templates> | |
</variable> | |
<copy> | |
<copy-of select="@*"/> | |
<for-each select="$normalized_children[not(self::rng:choice or self::rng:optional)]"> | |
<copy-of select="."/> | |
</for-each> | |
<for-each select="$normalized_children[self::rng:choice]"> | |
<copy-of select="*"/> | |
</for-each> | |
<!-- | |
<for-each select="$normalized_children[self::rng:optional]"> | |
<copy-of select="*"/> | |
</for-each> | |
--> | |
</copy> | |
</template> | |
<template | |
mode="rng_to_dnf" | |
match="*[not(ancestor-or-self::rng:attribute) and not(self::rng:define | self::rng:element | self::rng:choice)]" | |
> | |
<param name="depth" as="xs:string" select="''"/> | |
<variable name="this" select="."/> | |
<variable name="normalized_children" as="element()*"> | |
<apply-templates mode="rng_to_dnf" select="*"> | |
<with-param name="depth" as="xs:string" select="concat($depth, ' ')"/> | |
</apply-templates> | |
</variable> | |
<choose> | |
<when test="not($normalized_children[self::rng:choice])"> | |
<!-- debug output --> | |
<sequence select="eoa:debug('rng_to_dnf', concat( | |
$depth, | |
'rng_to_dnf: ', | |
parent::*/parent::*/name(), '/', | |
parent::*/name(), '[', parent::*/position(), ']', '/', | |
name(),'[',position(),']', | |
' - just copy!' | |
))"/> | |
<copy> | |
<copy-of select="@*"/> | |
<copy-of select="$normalized_children"/> | |
<copy-of select="text()"/> | |
</copy> | |
</when> | |
<otherwise> | |
<variable | |
name="all_sub_choices_count" | |
as="xs:integer*" | |
select=" | |
for $i in $normalized_children[self::rng:choice or self::rng:optional] return ( | |
if ($i[self::rng:choice]) | |
then count( $i/* ) | |
else 2 | |
) | |
" | |
/> | |
<variable | |
name="all_sub_choices" | |
as="xs:string*" | |
select="eoa:all_seqs($all_sub_choices_count)" | |
/> | |
<!-- debug output --> | |
<sequence select="eoa:debug( 'rng_to_dnf', concat( | |
$depth, | |
'rng_to_dnf: ', | |
parent::*/parent::*/name(), '/', | |
parent::*/name(), '[', parent::*/position(), ']', '/', | |
name(),'[',position(),']', | |
' - children: ', | |
string-join($normalized_children/name(), ','), | |
' - all_sub_choices_count: ', | |
string-join($all_sub_choices_count, ','), | |
'. all_sub_choices: ', | |
string-join($all_sub_choices, ',') | |
))"/> | |
<element name="choice" namespace="{$rng_namespace}"> | |
<for-each select="$all_sub_choices"> | |
<variable name="sub_choice" | |
select="for $t in tokenize(.,' ') return xs:integer($t)" | |
as="xs:integer*" | |
/> | |
<!-- debug output --> | |
<call-template name="eoa:debug"> | |
<with-param name="module" select="'rng_to_dnf'"/> | |
<with-param name="message"> | |
<text>current subchoice: </text> | |
<value-of select="$sub_choice" separator=","/> | |
<value-of select="$newline"/> | |
<text>names: </text> | |
<value-of select="$normalized_children/name()" separator=","/> | |
</with-param> | |
</call-template> | |
<element name="group" namespace="{$rng_namespace}"> | |
<!-- | |
--> | |
<call-template name="rng_to_dnf_helper"> | |
<with-param name="sub_elements" select="$normalized_children" as="element()*"/> | |
<with-param name="choice_numbers" select="$sub_choice" as="xs:integer*"/> | |
</call-template> | |
</element> | |
</for-each> | |
</element> | |
</otherwise> | |
</choose> | |
</template> | |
<!-- given a list of 'sub_element's insert them | |
where in the case of 'rng:choice' elements choosing | |
the subelement based on the 'choice_numbers' given | |
--> | |
<template name="rng_to_dnf_helper" as="element()*"> | |
<param name="sub_elements" as="element()*"/> | |
<param name="choice_numbers" as="xs:integer*"/> | |
<choose> | |
<when test="$sub_elements[1]/self::rng:choice"> | |
<copy-of select="$sub_elements[1]/*[$choice_numbers[1]]"/> | |
<call-template name="rng_to_dnf_helper"> | |
<with-param name="sub_elements" select="$sub_elements[position() != 1]" as="element()*"/> | |
<with-param name="choice_numbers" select="$choice_numbers[position() != 1]" as="xs:integer*"/> | |
</call-template> | |
</when> | |
<when test="$sub_elements[1]/self::rng:optional"> | |
<!-- print optional content --> | |
<if test="$choice_numbers[1] = 1"> | |
<copy-of select="$sub_elements[1]/*"/> | |
</if> | |
<call-template name="rng_to_dnf_helper"> | |
<with-param name="sub_elements" select="$sub_elements[position() != 1]" as="element()*"/> | |
<with-param name="choice_numbers" select="$choice_numbers[position() != 1]" as="xs:integer*"/> | |
</call-template> | |
</when> | |
<when test="count($sub_elements)"> | |
<copy-of select="$sub_elements[1]"/> | |
<call-template name="rng_to_dnf_helper"> | |
<with-param name="sub_elements" select="$sub_elements[position() != 1]" as="element()*"/> | |
<with-param name="choice_numbers" select="$choice_numbers" as="xs:integer*"/> | |
</call-template> | |
</when> | |
<when test="count($choice_numbers)"> | |
<sequence select="eoa:error('rng_to_dnf', 'rng_to_dnf_helper: choice numbers left')"/> | |
</when> | |
</choose> | |
</template> | |
<!-- default rule: just copy element --> | |
<template mode="rng_to_dnf" match="node() | @*"> | |
<copy> | |
<apply-templates mode="rng_to_dnf" select="@*|node()"/> | |
</copy> | |
</template> | |
<!-- return all indices where a sequence is non-zero, e.g. | |
indices_from_bin_seq((1, 0, 1)) = (1,3) | |
--> | |
<function name="eoa:indices_from_bin_seq" as="xs:integer*"> | |
<param name="subset" as="xs:integer*"/> | |
<for-each select="$subset"> | |
<if test=". = 1"> | |
<value-of select="position()"/> | |
</if> | |
</for-each> | |
</function> | |
<function name="eoa:all_seqs" as="xs:string*"> | |
<param name="input" as="xs:integer*"/> | |
<!-- | |
<message>all_seqs: <value-of select="$input"/></message> | |
--> | |
<choose> | |
<when test="count($input) = 0"> | |
<value-of select="()"/> | |
</when> | |
<otherwise> | |
<for-each select="1 to $input[1]"> | |
<variable name="leading" as="xs:string" select="xs:string(.)"/> | |
<!-- | |
<message>debug:<value-of select="."/></message> | |
--> | |
<variable name="rest" as="xs:string*" select="eoa:all_seqs($input[position() != 1])"/> | |
<choose> | |
<when test="count($rest) > 1"> | |
<for-each select="$rest"> | |
<value-of select="concat($leading,' ', .)"/> | |
</for-each> | |
</when> | |
<otherwise> | |
<value-of select="$leading"/> | |
</otherwise> | |
</choose> | |
</for-each> | |
</otherwise> | |
</choose> | |
</function> | |
</stylesheet> |