- Corrected and tested XPath expressions.
1 parent 808f859 commit a22ae1ce9ac7cdc65da521490018004b9be3b4ab
nstanger authored on 16 Sep 2011
Showing 1 changed file
View
128
extract_svg_layers.xsl
-->
<xsl:param name="layers">*</xsl:param>
<!--
A list of the base layer item IDs to extract. ONLY items that appear in this list will be extracted. Pass "*" to include all items (default).
A list of the *base layer* item IDs to extract. ONLY items that appear in this list will be extracted. Pass "*" to include all items (default).
-->
<xsl:param name="items">*</xsl:param>
 
<!-- Whenever you match any node or any attribute -->
<!-- Identity transformation. -->
<xsl:template match="@*|node()">
<!-- Copy the current node -->
<xsl:copy>
<!-- Including any attributes it has and any child nodes -->
</xsl:copy>
</xsl:template>
<!-- Always output the base layer. -->
<xsl:template match="svg:g[( @inkscape:groupmode = 'layer' ) and ( lower-case( @inkscape:label ) = lower-case( $base-layer ) )]" priority="10">
<!--
Always output the base layer.
XPath explanation
@inkscape:groupmode = 'layer'
This is a layer.
lower-case( @inkscape:label ) = lower-case( $base-layer )
This is the base layer.
-->
<xsl:template name="output-base-layer"
match="svg:g[ ( @inkscape:groupmode = 'layer' ) and
( lower-case( @inkscape:label ) = lower-case( $base-layer ) )
]" priority="10">
<!-- Copy the current node -->
<xsl:copy>
<!-- Including any attributes it has and any child nodes -->
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<!--
Ignore base layer items not included in the items list. The basic list of item types appears to be svg:rect, svg:text, svg:path (anything other than a rect or text) and svg:g (group).
Ignore base layer items not included in the items list. The basic list of item types appears to be svg:rect, svg:text, svg:path (anything other than a rect or text) and svg:g (group). We only consider "top-level" elements within the layer, otherwise the number of potential element IDs could explode massively. This could will be tricky if we ever decide that we want to omit an item that appears inside a group.
XPath explanation
@inkscape:groupmode = 'layer'
See output-base-layer template above.
( lower-case( @inkscape:label ) = lower-case( $base-layer ) ) or ( $layers = '*' )
Either this is the base layer, or we're outputting all layers anyway.
.../element()[...]
All immediate child elements of the base layer.
contains( 'svg:g|svg:path|svg:rect|svg:text', string( node-name ( . ) ) )
The current child element is one those listed.
not( contains( lower-case( $items ), lower-case( @id ) ) )
The current child node's ID isn't in the items list.
$items != '*'
We're not outputting all items.
-->
<xsl:template match="svg:g[( @inkscape:groupmode = 'layer' ) and ( ( lower-case( @inkscape:label ) = lower-case( $base-layer ) ) or ( $layers = '*' ) )]//(svg:g | svg:rect | svg:path | svg:text)[not( contains( lower-case( $items ), lower-case( @id ) ) ) and ( $items != '*' )]" />
 
 
<!-- Ignore layers that aren't in the list of layers. -->
<xsl:template match="svg:g[( @inkscape:groupmode = 'layer' ) and not( contains ( $layers, @inkscape:label ) ) and ( $layers != '*') )]" />
<xsl:template name="ignore-items"
match="svg:g[ ( @inkscape:groupmode = 'layer' ) and
( ( lower-case( @inkscape:label ) = lower-case( $base-layer ) ) or
( $layers = '*' )
)
]/element()[ contains( 'svg:g|svg:path|svg:rect|svg:text', string( node-name ( . ) ) ) and
not( contains( lower-case( $items ), lower-case( @id ) ) ) and
( $items != '*' )
]" />
<!--
Ignore layers that aren't in the list of layers.
XPath explanation
@inkscape:groupmode = 'layer'
See output-base-layer template above.
$layers != '*'
We're not outputting all layers
not( contains ( $layers, @inkscape:label ) )
The layer's label isn't in the list of layers.
-->
<xsl:template name="ignore-layers"
match="svg:g[ ( @inkscape:groupmode = 'layer' ) and
( $layers != '*') and
not( contains ( $layers, @inkscape:label ) )
]" />
<!--
Ensure that extracted layers are always visible, regardless of their setting in the original file.
XPath explanation
@inkscape:groupmode = 'layer'
See output-base-layer template above.
@style[. = 'display:none']
This layer is invisible.
-->
<xsl:template match="svg:g[@inkscape:groupmode = 'layer']/@style[. = 'display:none']">
<xsl:template name="make-layers-visible" match="svg:g[@inkscape:groupmode = 'layer']/@style[. = 'display:none']">
<xsl:attribute name="style">
<xsl:text>display:inline</xsl:text>
</xsl:attribute>
</xsl:template>