Skip to content
Permalink
93de43745e
Switch branches/tags

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?
Go to file
 
 
Cannot retrieve contributors at this time
291 lines (276 sloc) 9 KB
<?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>