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 sections 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
bridgeheads. 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 |