Contents

1.0 - Introduction
2.0 - Source code
3.0 - An SVG to XAML converter in code
4.0 - SVG to XAML using graphics editor Inkscape
5.0 - XAML to SVG conversion
6.0 - Conclusion
7.0 - References


Download source code test environment (Visual Studio 2008, C#): Solution_SVGToXAML_02.zip [43 kB].
Download test files (SVG, XAML, XSL stylesheets): Testfiles_SVGToXAML_02.zip [145 kB].
Download source code converter (Visual Studio 2008, C#): Solution_Converter_03.zip [68 kB].

Environment: .NET Framework 3.5 / Windows Forms / WPF.



1.0 - Introduction

SVG (Scalable Vector Graphics) is a successful W3C specification for creating vector graphics, supported in desktop and mobile browsers from Firefox and Opera.
XAML (XML Application Markup Language) on the other hand is a specification from Microsoft for making graphics and user interfaces. It is used in WPF applications (Windows Presentation Foundation), XPS (XML Paper Specification) and Silverlight or it can be used as 'loose' XAML for images. Browsers that support XAML are Firefox and Internet Explorer.
SVG and XAML have much in common, they are both based on XML and use the same kind of 'language' to describe objects [1][2][3].




Fig. 1.1 - An SVG image created in vector graphics editor Inkscape and converted to XAML with XSLT.


Because of the similarity between the two formats it is possible to make converters between them. Popular SVG to XAML and XAML to SVG converters are made by Toine de Greef [4]. They are based on XSL stylesheet transformation (XSLT) and are used in Moonlight [6], Inkscape [7] and other applications. The stylesheets are available free of charge and you are allowed to modify them.

Here we will look at SVG to XAML conversion from code (C#) in particular, by applying a stylesheet, and also by using vector graphics editor Inkscape. The results are compared.


2.0 - Source code

There are various sources for the SVG to XAML converter stylesheet from Toine de Greef. First of all of course as download from his website [4], but it is also possible to use the source from Moonlight [5] or from the Inkscape installation [7].
For our experiment we will borrow the stylesheet from vector graphics editor Inkscape. Inkscape has SVG as native format but it can also save or open drawings directly as XAML. This allows us to do two tests, by making a converter in code (C#) using the stylesheet and XSLT, and by saving a drawing directly from Inkscape as XAML.

When Inkscape is installed on Windows, the stylesheets svg2xaml.xsl and xaml2svg2.xsl for converting SVG to and from XAML can be found in:

C:\Program Files\Inkscape\share\extensions\

The svg2xaml.xsl stylesheet has one support file colors.xml, the xaml2svg2.xsl stylesheet has a number of support files in the \xaml2svg subdirectory.
Here, we will only use the svg2xaml.xsl and colors.xml files (included in the download).

This stylesheets can be used free of charge, in the source we read:


Copyright (c) 2005-2007 Toine de Greef (a.degreef@chello.nl)

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.


Note: As a consequence of this, there might be differences between the three sources mentioned.


3.0 - An SVG to XAML converter in code

The SVG to XAML converter transforms an SVG document with XSLT to XAML, but it can in fact do any transformation on an XML file. The reverse, XAML to SVG, is also possible as we will see later. The stylesheet (svg2xaml.xsl) determines the result, in this case a XAML file is produced.


3.1 - The code explained

The test-code (see download) is a Windows Forms application as wrapper for the converter. The converter itself is only one function, XSLT_Transform(), with three filenames as parameters: the SVG input document, the XSL stylesheet and the XAML output.


  C# - SVG to XAML with XSLT.

 using System.Xml;
 using System.Xml.Xsl;
 using System.IO;
 [...]

 private string sPath = @"D:\...";      // Path for stylesheet.
 private string sFile_xml;              // XML file, *.xml, *.svg.
 private string sFile_xsl;              // Stylesheet (svg2xaml.xsl).
 private string sFile_out;              // Output file.
 [...]

 // ---------------------------------------------------------------
 // Date      030409
 // Purpose   Transform an XML document with XSLT.
 // Entry     sFileName_xml - The XML datafile.
 //           sFileName_xsl - The XSL style sheet.
 //           sFileName_out - The result of the transformation.
 // Return    An empty string if successful, else an error description.
 // Comments  The output file is directly saved to disk.
 // ---------------------------------------------------------------
 private string XSLT_Transform(string sFileName_xml,
                               string sFileName_xsl,
                               string sFileName_out)
 {
     try
     {
         // Enable support for XSLT 'document()' function.
         XsltSettings settings = new XsltSettings(true, true);
         // Alternative:
         // settings.EnableDocumentFunction = true;     

         // Load the style sheet.
         XslCompiledTransform xslt = new XslCompiledTransform();
         xslt.Load(sFileName_xsl, settings, new XmlUrlResolver());
         // Execute the transform and output the results to a file.
         xslt.Transform(sFileName_xml, sFileName_out);

         return "";
     }
     catch (Exception ex)
     {
         return ex.Message;
     }
 }

 // Test XSLT_Transform().
 private void btnTransform_Click(object sender, EventArgs e)
 {
     sFile_xml = sPath + @"\Testfile.svg";
     sFile_xsl = sPath + @"\svg2xaml.xsl";
     sFile_out = sPath + @"\Testfile.xaml";

     string sRet = XSLT_Transform(Testfile.svg, 
                                  svg2xaml.xsl, Testfile.xaml);
     if (sRet.Length == 0)
     {
         if (File.Exists(sFile_out) == true)
         {
             // Show result in a TextBox.
             txtBox.Text = File.ReadAllText(sFile_out);
         }
         else
         {
             txtBox.Text = "Output file not found.";
         }
     }
     else
     {
         // Show error description.
         txtBox.Text = sRet;
     }
 }


Function XSLT_Transform() is a universal function for executing an XSLT transform on an arbitrary XML document by applying the XslCompiledTransform class (System.Xml.Xsl).

For translating colors from the source, stylesheet svg2xaml.xsl uses the document() function for addressing an external document colors.xml. This must be allowed with the settings for XslCompiledTransform. When no allowance is given an exception is thrown with the message:

"Execution of the 'document()' function was prohibited. Use the XsltSettings.EnableDocumentFunction property to enable it."

With the same XsltSettings, permission is given to use scripts from the stylesheet.
Support for DTD declarations in the source file is currently not implemented, you will see the following message:

"For security reasons DTD is prohibited in this XML document. To enable DTD processing set the ProhibitDtd property on XmlReaderSettings to false and pass the settings into XmlReader.Create method."

When testing, a quick workaround is to remove the DTD declaration from the source before a conversion is done.


3.2 - Testing the converter

SVG files were validated by opening them in browser Firefox. XAML files can be validated by opening them in Firefox or Internet Explorer (IE7, IE8). In all cases, the build-in validator gives detailed information when an error is found, with a reason and the position of the error in the file.

A simple SVG testfile was made with a circle, rectangle and a text element:


  SVG - The image to convert (Image_01.svg).

 <?xml version="1.0" encoding="UTF-8"?>
 <svg xmlns:svg="http://www.w3.org/2000/svg"
      xmlns="http://www.w3.org/2000/svg"
      xmlns:xlink="http://www.w3.org/1999/xlink"
      width="240" height="240">
      <rect x="1" y="1" width="238" height="238" rx="10" ry="10" 
           fill="none" 
           stroke="lightsteelblue" stroke-width="2" />
      <circle cx="100" cy="75" r="30" fill="tomato" 
           stroke="darkslateblue" stroke-width="2" />
      <circle cx="130" cy="45" r="8" fill="skyblue" 
           stroke="darkslateblue" stroke-width="1" />
      <text x="30" y="215" font-family="verdana" font-size="11" 
           fill="blue">
           Testing SVG to XAML conversion.
      </text>
 </svg>


This is the result from the converter (white space added by hand):


  XAML - The result after conversion (Image_01.xaml).

 <?xml version="1.0" encoding="utf-8"?>
 <Canvas 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     Width="240" Height="240" >
     <Rectangle 
         Canvas.Left="1" Canvas.Top="1" 
         Width="238" Height="238" 
         RadiusX="10" RadiusY="10" 
         Stroke="#b0c4de" StrokeThickness="2" />
     <Ellipse 
         Canvas.Left="70" Canvas.Top="45" 
         Width="60" Height="60" 
         Fill="#ff6347" Stroke="#483d8b" StrokeThickness="2" />
     <Ellipse Canvas.Left="122" Canvas.Top="37" 
         Width="16" Height="16" 
         Fill="#87ceeb" Stroke="#483d8b" StrokeThickness="1" />
     <TextBlock 
         Canvas.Left="30" Canvas.Top="215"
         FontSize="11" FontFamily="verdana" Foreground="blue" >
         Testing SVG to XAML conversion.
     </TextBlock>
 </Canvas>



Fig. 3.1 - Image_01.svg in Firefox.



Fig. 3.2 - Image_01.xaml in Firefox and IE.


This is a successful conversion, except for the position of the text and small changes in the size of the objects.

This test reveals:

- An <svg> root element is translated to <Canvas> and the positions of the child elements are translated to Canvas.SetLeft and Canvas.SetTop values. This is OK because the canvas needs absolute positioning of it's childs.
- In SVG, the size of the child elements must be smaller than the size of the root element <svg> otherwise they are truncated. This is not neccessary in XAML for Canvas.
- In SVG, Color-keywords and font names are not case sensitive; they are valid in Firefox and the converter. The W3C specification, however, defines the color-keywords for SVG in lower-case.
- Some color names are converted to RGB values (Fill="#ff6347") and some to strings ("blue"), and in the latter case the color is in lower-case, not CamelCase as usual in XAML (Blue, LightSteelBlue). For Internet Explorer this is valid XAML but it can cause problems when XAML objects are used in code.
- The converter uses RGB values for the output colors, not ARGB (Fill="#ffff6347") as usual in XAML.
- The position of the text is not correct. The reason is unclear, this could be a Firefox interpretation.
- All the objects in the XAML image are slightly smaller than in the SVG image, the reason is the positioning of the borders (Stroke, StrokeThickness): in SVG the border stretches to the outside of the object, in XAML to the inside of the object. This effect is amplified when borders are wide (stroke-width, StrokeThickness), see also Image_02.svg and Image_02.xaml in the download for comparison.

These differences might be not relevant in some artwork but they are unfortunately not acceptable for technical drawings. This small example already shows how difficult it is to make exact conversions and how much details are involved in such a process. It also gives a hint of the work involved for making this kind of converters. Results are possibly also affected by the application for rendering the image; a browser, printer, or a Frame Control.

When Image_01.svg is opened in Inkscape and then saved as XAML (whitespace added by hand):


  XAML - SVG saved from Inkscape as XAML (Image_01_Inkscape_white.xaml).

 <?xml version="1.0" encoding="UTF-8"?>
 <Canvas xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     Name="svg2440" 
     Width="240" Height="240">
     <Canvas.Resources/>
     <Rectangle xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
         Canvas.Left="1" Canvas.Top="1" 
         Width="238" Height="238" 
         RadiusX="10" RadiusY="10" 
         Name="rect2442" 
         Stroke="#b0c4de" StrokeThickness="2"/>
     <Ellipse xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
         Canvas.Left="70" Canvas.Top="45" 
         Width="60" Height="60" 
         Name="circle2444" 
         Fill="#ff6347" Stroke="#483d8b" StrokeThickness="2"/>
     <Ellipse xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
         Canvas.Left="122" Canvas.Top="37" 
         Width="16" Height="16" 
         Name="circle2446" 
         Fill="#87ceeb" Stroke="#483d8b" StrokeThickness="1"/>
     <TextBlock xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
         FontSize="11" FontFamily="verdana" 
         Foreground="blue" 
         Canvas.Left="30" Canvas.Top="215" 
         Name="text2448">
                   The earth, seen from mars.
     </TextBlock>
 </Canvas>


Inkscape adds (empty) resources, and a name and namespace declaration for each object. For the rest, this code is identical with the code from the converter. This was expected because the stylesheet for the converter is borrowed from Inkscape.


3.3 - Testing with more complicated images

The converter was also tested with the well known Butterfly.svg, Lion.svg and Tiger.svg images and with the SVG images from [4] (Coloredtoucan2.svg, GreenFrond.svg). They all were converted well, but there are only a limited number of different elements in these images (Table 1) so, this is not a thorough test. Most images almost exclusively use Path elements. This seems to work quite well, and also Polygon. All the test-files are in the download.




Fig. 3.3 - Coloredtoucan2.xaml in IE.


The following elements are tested with these images:

     Table 1 - Test images
Image SVG Element
Butterfly.svgpath
Coloredtoucan2.svgpath, group
GreenFrond.svgviewBox, radialGradient, path, group
Lion.svgpolygon, transform (rotate, translate), group
Tiger.svgtransform (translate), path, group


4.0 - SVG to XAML using graphics editor Inkscape

Inkscape is a powerful yet easy to use vector graphics editor with SVG as native format, but it can also save to XAML. Creating SVG images and converting them to XAML with Inkscape, however, is not perfect. Often the positioning of the elements is not correct, text objects are problematic most of the time and the size of the objects is not exact because of different rendering of the borders (Stroke), as we have seen above, and maybe other reasons.

When text is not shown in a saved SVG image, or only shown as a black object, use menu Text | Convert to Text after selecting the object. Still, positioning of text is often flawed after conversion.

When objects are grouped (select the objects + icon 'Group selected objects' on the toolbar) and then saved as image, the group element <g> often translates the image to a wrong position, even to the point that it is out of sight. Removing this element from the code brings it back (TestText_01.svg, TestText_02.svg).
Note: Inkscape has settings for transforms (menu File | Inkscape Preferences, Transforms), this was not tested.

Notice that Inkscape has coordinate 0,0 in the bottom-left corner of the canvas. This is mathematically correct, but unusual for Visual Studio, SVG and XAML; these environments use top-left as 0,0 coordinate. It seems that newer Inkscape versions will abandon the Cartesian coordination system (version 0.46 was used here) [8].


4.1 - Saving vector graphics as XAML

Create an image in Inkscape or open an image from file.

  1. Create an image in Inkscape or open it with File > Open.
  2. Save with File | Save As (Microsoft XAML, *.xaml)
Notice also that Inkscape can save to two types of SVG files, Inkscape SVG (*.svg) and Plain SVG (*.svg). As a rule of thumb, use the former for use in Inkscape only, the latter when SVG is exported to other applications. 'Plain SVG' gives the most tidy files.


4.2 - Saving selected objects as XAML

With File | Save (As) the complete page is saved as drawing. It is also possible to use the drawing as a repository for a number of images (as objects, object collections, or groups) and to save single objects to SVG or XAML file.

Objects (or grouped objects) can be saved from a drawing in Inkscape as follows:
  1. Create an image in Inkscape or open it with File | Open.
  2. Select the object in the image + Copy (right mouse button)
  3. Open a new window with File | New | Default (or A4).
  4. Focus on the new window + Paste
  5. Select the object
  6. Open the 'Document Properties' settings with icon 'Edit Properties ...' on the top toolbar
    1. Tab 'Page'
    2. Use button 'Fit page to selection' (the setting is applied)
    3. Close 'Document Properties'
  7. Save with File | Save As (Microsoft XAML, *.xaml)
Note: Copy and Paste for objects does not work between instances of Inkscape. A new window must be opened in Inkscape itself with File | New.

This procedure assures you that the bottom-left corner of the object is on coordinate 0.0 of the page (canvas) and that the canvas itself has the size of the object (when saved as 'Plain SVG', this is the root <svg> element in the file, with attributes width and height). The XAML image, as .xaml file, has now the correct size.


5.0 - XAML to SVG conversion

The Inkscape installation also contains stylesheets for translating XAML to SVG. This was given a short test too.

XAML files can be opened directly in Inkscape with menu File | Open (Microsoft XAML). The XAML is converted to SVG with an XSLT transformation, this time with xaml2svg.xsl (see directory C:\Program Files\Inkscape\share\extensions in the installation). The main stylesheet is accompanied by a set of specialized stylesheets in subdirectory \xaml2svg.

Only XAML files in an SVG context are opened correctly of course; you cannot open files with user-interfaces created in Visual Studio (the stylesheet does not support the UI elements). It does, however, open files containing elements from the System.Windows.Shapes namespace and the names of the files in \xaml2svg (animation.xsl, brushes.xsl, canvas.xsl, geometry.xsl, properties.xsl, shapes.xsl and transform.xsl) gives an indication for other support.

This is also a common XSLT transformation so, the same XSLT_Transform() function from our code can be used to convert XAML to SVG using xaml2svg.xsl. A limited test was done on some images containing shapes from the System.Windows.Shapes namespace and transformations from the System.Windows.Media namespace. The images were opened in browser Firefox to see if valid SVG was produced.

For all the files, Firefox returns:

"This XML file does not appear to have any style information associated with it. The document tree is shown below." (shows only the code).

This can be corrected by adding the following namespace declaration in the root element:

xmlns="http://www.w3.org/2000/svg"




Fig. 5.1 - Source, Page_06.xaml.
Rectangles rotated with RenderTransform (RotateTransform).



Fig. 5.2 - Result, Page_06.svg.
The rotated rectangles are spinning out of control after a conversion to SVG (same scale, Firefox).


It appears that only simple XAML documents are converted successfully. In the test files (see the Page_xx.xaml files in the download) transformations, resources and some GeometryGroup properties gave problems.
Opening the XAML files in Inkscape gives exactly the same results, which proves that it does a conversion to SVG when a XAML file is opened with File | Open (Microsoft XAML).

As for XAML to SVG, the xaml2svg.xsl stylesheet does not seem to be universal enough to be useful as general purpose converter. Opening XAML in Inkscape is probably only useful when it is a file earlier saved from Inkscape.


6.0 - Conclusion

The XSL svg2xaml.xsl stylesheet for converting SVG to XAML discussed here does a good job, but it is not perfect. It is an unfinished product, but both Moonlight and Inkscape are using this stylesheet, which probably proves that there is no better alternative.
A second conclusion, concerning Inkscape, is that it is a very good SVG editor but not a XAML editor. Saving images as XAML gives unpredictable results and it is only useful when raw material is needed which can be corrected by hand.
The discussed stylesheets are free and you are allowed to modify them. With knowledge of XSLT, SVG and XAML (and a lot of time and patience) you can consider improving them yourself.


7.0 - References


[1] W3C - Scalable Vector Graphics (SVG)
SVG is a language for describing two-dimensional graphics and graphical applications in XML.
http://www.w3.org/Graphics/SVG/

[2] W3C - Scalable Vector Graphics (SVG) 1.1 Specification.
W3C Recommendation 14 January 2003.
http://www.w3.org/TR/SVG11/

[3] MSDN - XAML
Extensible Application Markup Language (XAML) is a markup language for declarative application programming.
http://msdn.microsoft.com/en-us/library/ms747122.aspx

[4] Having fun with XAML (Silverlight) and SVG.
SVG to XAML and XAML to SVG source.
http://members.chello.nl/~a.degreef/XAML.html

[5] Moonlight - SVG to XAML source.
Index of /trunk/moon/tools/svg2xaml.
http://anonsvn.mono-project.com/viewvc/trunk/moon/tools/svg2xaml/

[6] Moonlight.
Moonlight is an open source implementation of Silverlight (http://silverlight.net), primarily for Linux and other Unix/X11 based operating systems.
http://www.mono-project.com/Moonlight

[7] Inkscape.
An Open Source vector graphics editor using the W3C standard Scalable Vector Graphics (SVG) file format.
http://www.inkscape.org/

[8] Inkscape Roadmap.
Milestone 13 - Inkscape 0.47. Inkscape SVG Effort. Revisit coordination system (move away from Cartesian).
http://wiki.inkscape.org/wiki/index.php/Roadmap