Chris Pollett > Students >
Joom

    ( Print View )

    [Bio]

    [CS297Proposal]

    [Del1]

    [Del2]

    [Del3]

    [CS298Proposal]

    [DemoIE298]

    [DemoMozilla298]

    [CS298Report-PDF]

    [CS298Presentation-PDF]

                           

























Joom's Shape to SVG Translator

The purpose of deliverable3 is to experiment with XSL stylesheets in order to translate one XML application to another XML application. In this case, we designed our source XML document type called SHML (Shape Mark Up Language) to have four different kinds of nodes <shapes>, <circle>, <square>, <triangle>. We also define a DTD file along with a source document for syntax error detection. A target document is output in SVG, which is an XML application to display 2D line art graphics. 

Below is a sample of a source SHML documents.

<shapes>
   <triangle>
      <triangle/>
   </triangle>
   <square>
      <circle/>
      <triangle/>
   </square>
   <circle>
      <circle>
         <square/>
      </circle>
   </circle>
</shapes>

A <shapes> tag serves as a root node of a SHML document. It consists of zero or more component nodes, <circle>, <triangle>, <square>.
Also, each of these component nodes can be made up of zero or more <circle>, <triangle>, and <square> tags which can also be nested structures as illustrated in the sample above.

Our target document which is written in SVG will display graphics associated to types and arranged in accordance with structures of nodes defined in a source document.
The output document can be seen below (It displays in IE if you have the (
Adobe-SVG Plug-in):

Sample Shape to SVG conversion

According to the source document, <shapes> has three child nodes: <triangle>, <square>, and <circle>. So it should output a triangle, a square, and a circle drawn in parallel from left to right. Each child node also has one or more child nodes, which should be drawn nested inside their parent nodes. For example, the first child node of the <shapes> tag, <triangle>, has one child node, <triangle>, This child <triangle> node is displayed inside the parent <triangle> node. Similar rules are also applied to the other two child nodes of a root <shapes> node.


Below is the code used in this deliverable.

First, we have the DTD:

<!--The purpose of this file is to check the syntax of deliverable3.xml-->
<!ELEMENT shapes (square | circle | trianble)*>
<!ELEMENT square (square | circle | triangle)*>
<!ELEMENT circle (square | circle | triangle)*>
<!ELEMENT triangle (square | circle | triangle)*>

Next, we have an example XML document with this DTD:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE shapes SYSTEM "deliverable3.dtd">
<?xml:stylesheet type="text/xsl" href="deliverable3.xsl"?>
<shapes>
  <triangle>
     <triangle/>
  </triangle>
  <square>
      <circle/>
      <triangle/>
  </square>
  <circle>
     <circle>
        <square/>
     </circle>
  </circle>
</shapes>


Finally, we have the stylesheet.

<?xml version="1.0" encoding="ISO-8859-1" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
   xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:helper="http://deliverable3" 
   xmlns:xlink="http://www.w3.org/1999/xlink">
	<xsl:output method="xml" indent="yes" />
	<!--==========================================================================-->
	<!--A root element template-->
	<!--This template specifies what creates the root element of the result tree.-->
	<!--In this case, it tells XSL processor to start with the <shapes> element.-->
	<!--==========================================================================-->
	<xsl:template match="/">
		<xsl:apply-templates select="shapes" />
	</xsl:template>
	<!--==========================================================================-->
	<!--<shapes> template-->
	<!--This template creates all heading elements for an SVG document. It predefines-->
	<!--basis shapes for circles, triangles, and squares, and calls a template-->
	<!--associated to each child node.-->
	<!--==========================================================================-->
	<xsl:template match="shapes">
		<!--========================================================================-->
		<!--Use <xsl:text> to specify the standard DTD for SVG 1.0.-->
		<!--========================================================================-->
		<xsl:text disable-output-escaping="yes"> 
				&lt;!DOCTYPE svg 
SYSTEM "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"&gt;
			</xsl:text>
		<!--==========================================================================-->
		<!--We create a root <svg> element and hardcodes a size of a displaying window-->
		<!--============================================================================-->
		<svg width="400" height="400">
			<!--==========================================================================-->
			<!--An SVG <defs> tag is where we predefine a basis-unit 
shape used in this sample-->
			<!--(a circle, triangle, and a square), which will be called later-->
			<!--by associated templates.-->
			<!--                        -->
			<!--Use an SVG <circle> tag to create a base circle shape, an SVG-->
			<!--<polygon> tag to create a base triangle shape, and an SVG-->
			<!--<rect> tag to create a base square shape.-->
			<!--Notice that all these predefined shapes are created at the origin position-->
			<!--in order that it is easy to move these shapes around to new positions-->
			<!--by a simple translating process.-->
			<!--==========================================================================-->
			<defs>
				<circle id="a_circle" fill="none" stroke="red" 
stroke-width="0.03" cx="0" cy="0" r="1" />
				<polygon id="a_triangle" fill="none" stroke="green" 
stroke-width="0.03" points="0,-1 -1,0 1,0" />
				<rect id="a_square" fill="none" stroke="blue" 
stroke-width="0.03" x="-0.5" y="-0.5" width="1" height="1" />
			</defs>
			<!--==========================================================================-->
			<!--<xsl:apply-templates> calls an associated template of each child 
node and passes-->
			<!--two parameters (size, width) to that template.-->
			<!--                                              -->
			<!--In this example, I design sizes of parent nodes-->
			<!--twice bigger than sizes of the child nodes.-->
			<!--So each child node of the root has the biggest size-->
			<!--                                                   -->
			<!--A size parameter is used to calculate scaling factors which will be 
implemented-->
			<!--in a scaling transformation process.-->
			<!--When parent nodes pass the size parameter to child nodes, child nodes-->
			<!--will be created in an appropriat size, which is half a size of a parent's.-->
			<!--                                                                 -->
			<!--A width parameter is to tell a width of a reqion in which child nodes-->
			<!--of the context nodes can be drawn.-->
			<!--In order to give the equal space to each child node,-->
			<!--a width of a frame of a parent node must be divided by a total number of 
child nodes,-->
			<!--which are obtained by function count().-->
			<!--This parameter will be used later to calculate an x-coordinate position 
when we-->
			<!--translate a predefined shape, and we don't have to worry about y-coordinate-->
			<!--because every shape is drawn at fixed y-coordinate position(200).-->
			<!--==========================================================================-->
			<xsl:apply-templates select="*">
				<xsl:with-param name="size" select="1" />
				<xsl:with-param 
name="width" select="400 div count(*)" /> <!-- 400 is the origianl size in this sample-->
			</xsl:apply-templates>
		</svg>
	</xsl:template>
	<!--==========================================================================-->
	<!--<circle> template-->
	<!--A circle template receives two parameters, size and width,-->
	<!--from a calling template and passes three parameters, size, width, and-->
	<!--start_x to an associated child template-->
	<!--A start_x parameter is used as a starting position of this frame.-->
	<!--Its default value is assigned to zero.-->
	<!--A left-corner starting positon at which a circle is drawn is calculated from-->
	<!--a start_x parameter plus an offset. The offset value depends on an index number-->
	<!--of this node from the parent which is obtained by X-path function postion().-->
	<!--From this example, each shape is drawn at a fixed y position-->
	<!--but a position of x can be vary, which depends on how many child nodes-->
	<!--the parent of this context node has.-->
	<!--a scale parameter is to tell how big a circle will be, which is assigned-->
	<!--to be twice smaller than a size of a parent node.-->
	<!--==========================================================================-->
	<xsl:template match="circle">
		<xsl:param name="size" />
		<xsl:param name="width" />
		<xsl:param name="start_x" select="0" />
		<xsl:param name="position" select="position()" /> 
<!--Obtain the index number of this node from the parent-->
		<xsl:param name="totalNodes" select="count(parent::*/*)" /> 
<!--Count a total number of child nodes of the parent-->
		<xsl:param name="x" select="$start_x + ($position - 1)*$width" /> 
<!--Find a new left-corner starting position-->
		<xsl:param name="x_coordinate" select="$x + $width div 2" /> 
<!--Find a center x position of a circle-->
		<xsl:param name="y_coordinate" select="200" /> <!--A center y position is fixed-->
		<xsl:param name="scale" select="$width div ($size*2)" /> 
<!--Find a new size which is half a size of a parent node-->
		<!--Apply those parameters to svg tags to draw an appropriate picture-->
		<g>
			<xsl:attribute name="transform">
				<xsl:text>translate(</xsl:text>
				<xsl:value-of select="$x_coordinate" />
				<xsl:text>, </xsl:text>
				<xsl:value-of select="$y_coordinate" />
				<xsl:text>) scale(</xsl:text>
				<xsl:value-of select="$scale" />
				<xsl:text>, </xsl:text>
				<xsl:value-of select="$scale" />
				<xsl:text>)</xsl:text>
			</xsl:attribute>
			<use xlink:href="#a_circle" />
		</g>
		<!--Pass parameters to associated child template-->
		<xsl:apply-templates select="*">
			<xsl:with-param name="size" select="$size * 2" />
			<xsl:with-param name="width" select="$width div count(*)" />
			<xsl:with-param name="start_x" select="$x" />
		</xsl:apply-templates>
	</xsl:template>
	<!--==========================================================================-->
	<!--The same rules applied to a circle template are also applied to the triangle template-->
	<!--==========================================================================-->
	<xsl:template match="triangle">
		<xsl:param name="size" />
		<xsl:param name="width" />
		<xsl:param name="start_x" select="0" />
		<xsl:param name="position" select="position()" />
		<xsl:param name="totalNodes" select="count(parent::*/*)" />
		<xsl:param name="x" select="$start_x + ($position - 1)*$width" />
		<xsl:param name="x_coordinate" select="$x + $width div 2" />
		<xsl:param name="y_coordinate" select="200" />
		<xsl:param name="scale" select="$width div ($size*2)" />
		<g>
			<xsl:attribute name="transform">
				<xsl:text>translate(</xsl:text>
				<xsl:value-of select="$x_coordinate" />
				<xsl:text>, </xsl:text>
				<xsl:value-of select="$y_coordinate" />
				<xsl:text>) scale(</xsl:text>
				<xsl:value-of select="$scale" />
				<xsl:text>, </xsl:text>
				<xsl:value-of select="$scale" />
				<xsl:text>)</xsl:text>
			</xsl:attribute>
			<use xlink:href="#a_triangle" />
		</g>
		<xsl:apply-templates select="*">
			<xsl:with-param name="size" select="$size * 2" />
			<xsl:with-param name="width" select="$width div count(*)" />
			<xsl:with-param name="start_x" select="$x" />
		</xsl:apply-templates>
	</xsl:template>
	<!--==========================================================================-->
	<!--The same rules applied to a circle template are also applied to a square template-->
	<!--==========================================================================-->
	<xsl:template match="square">
		<xsl:param name="size" />
		<xsl:param name="width" />
		<xsl:param name="start_x" select="0" />
		<xsl:param name="position" select="position()" />
		<xsl:param name="totalNodes" select="count(parent::*/*)" />
		<xsl:param name="x" select="$start_x + ($position - 1)*$width" />
		<xsl:param name="x_coordinate" select="$x + $width div 2" />
		<xsl:param name="y_coordinate" select="200" />
		<xsl:param name="scale" select="$width div $size" />
		<g>
			<xsl:attribute name="transform">
				<xsl:text>translate(</xsl:text>
				<xsl:value-of select="$x_coordinate" />
				<xsl:text>, </xsl:text>
				<xsl:value-of select="$y_coordinate" />
				<xsl:text>) scale(</xsl:text>
				<xsl:value-of select="$scale" />
				<xsl:text>, </xsl:text>
				<xsl:value-of select="$scale" />
				<xsl:text>)</xsl:text>
			</xsl:attribute>
			<use xlink:href="#a_square" />
		</g>
		<xsl:apply-templates select="*">
			<xsl:with-param name="size" select="$size * 2" />
			<xsl:with-param name="width" select="$width div count(*)" />
			<xsl:with-param name="start_x" select="$x" />
		</xsl:apply-templates>
	</xsl:template>
</xsl:stylesheet>