Newer
Older
XML / extract_svg_layers.xsl
<?xml version="1.0" encoding="utf-8"?>

<!--
	Extract named layers of an SVG file into an new SVG file. This is particularly useful for images that have a base layer of objects with various different overlays. The entire image can be created as one file with each overlay on a separate layer, then only the required overlay layers plus the base layer are output.
	
	The base layer is assumed to be named "Base Layer" (case-insensitive).
	
	Arguments
		$base-layer: The case-insensitive name of the base layer, which will always be included. Omit if there is no base layer.
		
		$layers: A list of case-insensitive layer names. You can use any character as a separator, as long as it doesn't appear in any of the layer names. Comma would be usual. Pass "*" to include all layers (this obviously rules out "*" as an layer name!).
		
		$items: A list of case-insensitive SVG item IDs to extract from the base layer. ONLY these items are extracted from the base layer; everything else in the base layer is ignored. Pass "*" to include all items (this obviously rules out "*" as an item ID!).
-->
	
<xsl:stylesheet
	version="2.0"
	xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
	xmlns:exsl="http://exslt.org/common"
	xmlns:svg="http://www.w3.org/2000/svg"
	xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape">


	<xsl:output method="xml" encoding="UTF-8" standalone="no" />


	<!--
		The case-insensitive name of the base layer. Everything in the base layer will be included in the output, unless the $items parameter is set (see below).
	-->
	<xsl:param name="base-layer" />
	
	<!--
		The names of the layers to extract. Normally comma-separated, but any separator should work, as long as it doesn't appear in any of the layer names. Watch out for blanks in layer names when passing this from the command line! Note that the base layer is ALWAYS included in the output. Pass "*" to include all layers (default).
	-->
	<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).
	-->
	<xsl:param name="items">*</xsl:param>
	

	<!-- Whenever you match any node or any attribute -->
	<xsl:template match="@*|node()">
		<!-- Copy the current node -->
		<xsl:copy>
			<!-- Including any attributes it has and any child nodes -->
			<xsl:apply-templates select="@*|node()" />
		</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">
		<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).
	-->
	<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 != '*') )]" />
	
	
	<!--
		Ensure that extracted layers are always visible, regardless of their setting in the original file.
	-->
	<xsl:template match="svg:g[@inkscape:groupmode = 'layer']/@style[. = 'display:none']">
		<xsl:attribute name="style">
			<xsl:text>display:inline</xsl:text>
		</xsl:attribute>
	</xsl:template>
	
	
</xsl:stylesheet>