Skip to content

Instantly share code, notes, and snippets.

@gimsieke
Created August 15, 2020 16:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gimsieke/24acca99f88ff232ed453d9177700472 to your computer and use it in GitHub Desktop.
Save gimsieke/24acca99f88ff232ed453d9177700472 to your computer and use it in GitHub Desktop.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:split="http://www.le-tex.de/XSLT/split"
exclude-result-prefixes="xs split"
version="3.0">
<xsl:mode name="preprocess" on-no-match="shallow-copy"/>
<xsl:mode name="main" on-no-match="shallow-copy"/>
<xsl:mode name="postprocess" on-no-match="shallow-copy"/>
<xsl:use-package name="http://www.le-tex.de/XSLT/split"
package-version="1.0"/>
<xsl:template match="*" mode="preprocess">
<xsl:element name="{local-name()}">
<xsl:apply-templates select="@* | node()" mode="#current"/>
</xsl:element>
</xsl:template>
<xsl:template match="/">
<xsl:variable name="preprocessed" as="element(*)">
<xsl:apply-templates mode="preprocess"/>
</xsl:variable>
<xsl:apply-templates select="$preprocessed" mode="main"/>
</xsl:template>
<xsl:template match="*:title//text()" mode="preprocess">
<xsl:analyze-string regex=":" select=".">
<xsl:matching-substring>
<sep/>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:template>
<xsl:template match="title" mode="main">
<xsl:variable name="chunks" as="document-node(element(split:chunks))">
<xsl:apply-templates select="." mode="split:split-entrypoint">
<xsl:with-param name="group-start-exp" select="'self::sep'"/>
<xsl:with-param name="keep-splitting-node" select="false()"/>
<xsl:with-param name="chunk-name-exp" select="'if (self::sep) then ''subtitle'' else ''title'''"/>
</xsl:apply-templates>
</xsl:variable>
<xsl:apply-templates mode="postprocess" select="$chunks/split:chunks/split:chunk/title"/>
</xsl:template>
<xsl:template match="split:chunk/title" mode="postprocess">
<xsl:element name="{name(..)}">
<xsl:apply-templates select="@* | node()" mode="#current"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
<?xml version="1.0" encoding="UTF-8"?>
<xsl:package
name="http://www.le-tex.de/XSLT/split"
package-version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:split="http://www.le-tex.de/XSLT/split"
exclude-result-prefixes="xs split"
version="3.0">
<xsl:mode name="split:split" visibility="private"/>
<xsl:mode name="split:split-entrypoint" visibility="final"/>
<xsl:template match="*" mode="split:split-entrypoint">
<xsl:param name="leaves-exp" as="xs:string"
select="'outermost(descendant::node()[not(has-children(.))])'"/>
<xsl:param name="group-start-exp" as="xs:string"/>
<xsl:param name="chunk-name-exp" as="xs:string"/>
<xsl:param name="keep-splitting-node" as="xs:boolean" select="true()"/>
<xsl:document>
<split:chunks>
<xsl:variable name="context" select="." as="element()"/>
<xsl:for-each-group select="split:eval-xpath(., $leaves-exp)"
group-starting-with="node()[split:node-matches-xpath(.,
$group-start-exp)]">
<split:chunk>
<xsl:attribute name="n" select="position()"/>
<xsl:if test="$chunk-name-exp">
<xsl:attribute name="name">
<xsl:evaluate xpath="$chunk-name-exp" context-item="."/>
</xsl:attribute>
</xsl:if>
<xsl:apply-templates select="$context" mode="split:split">
<xsl:with-param name="restricted-to" tunnel="yes"
select="for $n in (
current-group()/ancestor-or-self::node()
except .[not($keep-splitting-node)]
)
return generate-id($n)"/>
</xsl:apply-templates>
</split:chunk>
</xsl:for-each-group>
</split:chunks>
</xsl:document>
</xsl:template>
<xsl:function name="split:node-matches-xpath" as="xs:boolean"
visibility="private">
<xsl:param name="_node" as="node()"/>
<xsl:param name="xpath" as="xs:string"/>
<xsl:sequence select="exists(split:eval-xpath($_node, $xpath))"/>
</xsl:function>
<xsl:function name="split:eval-xpath" as="item()*" visibility="private">
<xsl:param name="context" as="node()"/>
<xsl:param name="xpath" as="xs:string"/>
<xsl:evaluate xpath="$xpath" context-item="$context" as="node()*"/>
</xsl:function>
<xsl:template match="@* | node()" mode="split:split" priority="-1">
<xsl:copy>
<xsl:apply-templates select="@*, node()" mode="#current"/>
</xsl:copy>
</xsl:template>
<xsl:template match="node()" mode="split:split">
<xsl:param name="restricted-to" as="xs:string+" tunnel="yes"/>
<xsl:if test="generate-id() = $restricted-to">
<xsl:next-match/>
</xsl:if>
</xsl:template>
</xsl:package>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment