bridgehead
Elements into section
ElementsYou have a DocBook document which contains several
bridgehead
elements. The bridgehead
has to
be transformed into the correct section
structure.
A bridgehead
element is a “free-floating
heading”. In most cases it is a bad idea as it is
difficult to handle in XSLT. To create the correct section
hierarchy, a stylesheet need to collect all nodes between a
bridgehead
element and the next one. The following
stylesheet uses a set difference method:
bridgehead
Element into
a section
Element<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:d="http://docbook.org/ns/docbook" xmlns="http://docbook.org/ns/docbook" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:import href="copy.xsl"/> <xsl:output indent="yes"/> <xsl:strip-space elements="*"/> <xsl:preserve-space elements="d:screen d:programlisting d:literallayout"/> <xsl:template match="d:section[d:bridgehead]"> <!-- All nodes inside our section: --> <xsl:variable name="node1" select="node()"/> <!-- All nodes --> <xsl:variable name="node2" select="d:bridgehead[1]| d:bridgehead[1]/following-sibling::node()"/> <!-- Copy our section with all attributes, apply the set difference and investigate the first bridgehead --> <xsl:copy> <xsl:copy-of select="@*"/> <xsl:apply-templates select="$node1[count(.|$node2) != count($node2)]"/> <xsl:apply-templates select="d:bridgehead[1]"/> </xsl:copy> <xsl:text> </xsl:text> </xsl:template> <xsl:template match="d:bridgehead"> <!-- All nodes who follow bridgeheads: --> <xsl:variable name="node1" select="following-sibling::node()"/> <!-- All nodes who follow the next bridgehead including the next bridgehead. The next bridgehead element is included as we don't want it in the set difference: --> <xsl:variable name="node2" select="following-sibling::d:bridgehead[1]| following-sibling::d:bridgehead[1]/following-sibling::node()"/> <!-- Create the section element with all attributes and apply standard rules for the diff set --> <xsl:element name="section"> <xsl:copy-of select="@*"/> <xsl:text> </xsl:text> <xsl:element name="title"> <xsl:apply-templates select="node()"/> </xsl:element> <xsl:apply-templates select="$node1[count(.|$node2) != count($node2)]"/> </xsl:element> <!-- Process the next bridgehead --> <xsl:apply-templates select="following-sibling::d:bridgehead[1]"/> </xsl:template> </xsl:stylesheet>
The solution is unfortunately not very trivial in XSLT 1.0.
The template rule d:section[d:bridgehead]
matches
only section
s which contain one or more
bridgehead
elements.
The
template rule performs the following steps:
Collect all nodes inside a section
and save it
in variable node1
.
Collect all nodes who follows the next
bridgehead
including the next
bridgehead
itself and save it in variable
node2
.
Creates a section
element and copy all
attributes from the bridgehead
element.
Creates a title
element and apply the content
from the bridgehead
element. This copies the
content from bridgehead
.
Calculates the set difference between
node1
and node2
. This
weird expression is needed in XSLT 1.0 to create a node set
which contains only those nodes up to the first
bridgehead
.
Handle the first bridgehead
element which is
covered by our bridgehead
template rule.
The bridgehead
template rule is responsible for
transforming the current bridgehead
element into a
section
. It is also responsible for the next
bridgehead
s. The rule performs the following
steps:
Collect all nodes following of the current
bridgehead
element and save it in variable
node1
.
Collect all nodes following of the next
bridgehead
element including the next
bridgehead
element itself. Save the node set in
variable node2
.
Creates a section
element and copy all
attributes from the bridgehead
element.
Creates a title
element and apply the content
from the bridgehead
element. This copies the
content from bridgehead
.
Calculate the set difference between
node1
and node2
and
apply the correct template rule (usually they are just
copied).
Close the section
element and handle the next
bridgehead
element.
Project@GitHub | Issue#8 |