TheRoadrunner
TheRoadrunner

Reputation: 1499

XSLT generated SVG with right namespace

Sorry if I am asking a newbie question, but namespaces are really puzzling to me.

I'm trying to generate a number of SVG documents from a single XML/XSLT.

My stylesheet:

<xsl:stylesheet version="2.0"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:svg="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink"
    xmlns="http://www.w3.org/2000/svg"
    >
    <xsl:output method="xml" indent="yes" name="xml" cdata-section-elements="style"/>
    <xsl:template match="/">
        <xsl:apply-templates select="//root/menu"/>
    </xsl:template>
    <xsl:template match="menu">
        <xsl:variable name="filename" select="concat(@name,'.svg')"/>
        <xsl:result-document href="{$filename}" format="xml">
            <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" baseProfile="basic" id="svg-root" width="482" height="600">
              <defs>
                <style type="text/css"><![CDATA[rect {       
                 fill: white;        
                 fill-opacity:1;
continues...

This works and produces the following output:

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.1" baseProfile="basic" id="svg-root" width="482" height="600">
    <defs>
        <style type="text/css"><![CDATA[rect {       
                     fill: white;        
                     fill-opacity:1;        
continues...

But I want to be able to specify height and width attributes based on calculated content

I have tried to create "<svg>" as <xsl:element name="svg"><xsl:attribute name="xmlns">http://www.w3.org/2000/svg </xsl:attribute></xsl:element>

This fails as it (xmlspy) won't let me assign the xmlns attribute.

If I don't specify a namespace on the root (svg), xmlns is automagically added to the root <svg> node and all first-level sub nodes are applied with namespace references like the following (see <defs>)

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" baseProfile="basic" id="svg-root" width="482" height="600">
    <defs xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xs="http://www.w3.org/2001/XMLSchema">
        <style type="text/css"><![CDATA[rect {       
                     fill: white;        
                     fill-opacity:1;        
continues...

How can I specify the needed namespaces on the root svg element and at the same time calculate the values for height and width without superfluous namespace references on first-level sub-branches?

Upvotes: 0

Views: 1236

Answers (1)

C. M. Sperberg-McQueen
C. M. Sperberg-McQueen

Reputation: 25054

Look up attribute-value templates, and read about them. Use them to calculate the values of height and width instead of using hard-coded values. So your current literal result element becomes something like:

<xsl:variable name="width"
     select="$raw-width * $compression-factor 
             + $fudge"/>            
<svg xmlns="http://www.w3.org/2000/svg" 
     xmlns:xlink="http://www.w3.org/1999/xlink" 
     version="1.1" 
     baseProfile="basic" 
     id="svg-root" 
     width="{$width}" 
     height="{$width * 1.61803}">

You can also use element and attribute constructors if you like; your attempt to do so went astray because you tried to create a namespace declaration using an xsl:attribute constructor, but the attribute constructor can only create a general attribute, not a namespace attribute. You would want something like this:

<xsl:variable name="width"
     select="$raw-width * $compression-factor 
             + $fudge"/>         
<xsl:element name="svg"
             namespace="http://www.w3.org/2000/svg">
  <xsl:attribute name="version"
                 select="'1.1'"/>
  <xsl:attribute name="baseProfile"
                 select="'basic'"/> 
  <xsl:attribute name="id"
                 select="'svg-root'"/> 
  <xsl:attribute name="width"
                 select="$width"/> 
  <xsl:attribute name="height"
                 select="$width * 1.61803"/> 

Upvotes: 1

Related Questions