Page 1 of 1

Changing scales of an .svg path in XSLT 2.0

Posted: Sat Feb 07, 2009 5:20 pm
by willisd1
A few items ago in the forum, I asked the question about how to rescale an svg polyline point. The answer worked very well and I have used that method on other svg entities.

There is one entity that I am not having any success with though - the path element.

Input:
<path d="M106.32,54.64 L108.88,98.67 40.47,180.66 160.02,180.00 z" />

I have tried to:
1. Tokenize this string using various regex (To break out the coordinates from the M and L)
2. Multiply the results by a factor (return 10*xs:decimal($k))
3. Reconstruct the sequence

I have not yet been successful. Any help would again be greatly appreciated.

Re: Changing scales of an .svg path in XSLT 2.0

Posted: Mon Feb 09, 2009 9:51 am
by willisd1
Well...making progress. I have accomplished the first two objectives, now I am just trying to reassemble the sequence into final a path attribute.

Code: Select all


<!--Turn path attribute into a space delimited sequence-->

<xsl:template match="ns1:path/@d" xmlns:ns1="http://www.w3.org/2000/svg">
<xsl:variable name="oldpath">
<xsl:analyze-string select="." regex='([A-Z])|(\d+\.\d+)|([a-z])'>
<xsl:matching-substring>
<xsl:value-of select="regex-group(1)"/>
<xsl:value-of select="regex-group(2)"/>
<xsl:value-of select="regex-group(3)"/>
<xsl:text> </xsl:text>
</xsl:matching-substring>
</xsl:analyze-string>
</xsl:variable>

<!--Tokenize sequence to check if castable as XS:decimal, then rescale-->

<xsl:variable name="newpath">
<xsl:value-of select="for $i in tokenize($oldpath, ' ') return(if($i castable as xs:decimal) then 10*xs:decimal($i) else ($i))"/>
</xsl:variable>

<!--Reassemble sequence into final path attribute-->

Re: Changing scales of an .svg path in XSLT 2.0

Posted: Mon Feb 09, 2009 1:05 pm
by george
I would do it a little different. Split the path into tokens keeping them all (including comma and spaces). Then apply the scaling for numeric tokens and put them together:

Code: Select all


  <xsl:template match="svg:path" xmlns:svg="http://www.w3.org/2000/svg">
<!-- Turn path attribute into a sequence of tokens -->
<xsl:variable name="oldpath">
<xsl:analyze-string select="@d" regex="([A-Z])|(\d+\.\d+)|([a-z])|,|\s">
<xsl:matching-substring>
<xsl:value-of select="."/>
<xsl:text>#</xsl:text>
</xsl:matching-substring>
</xsl:analyze-string>
</xsl:variable>
<!--Tokenize sequence to check if castable as xs:decimal, then rescale-->
<xsl:variable name="newpath"
select="for $i in tokenize($oldpath, '#')
return(if($i castable as xs:decimal) then 10*xs:decimal($i) else ($i))"/>
<xsl:variable name="newvalue">
<xsl:value-of select="$newpath" separator=""/>
</xsl:variable>
<!--Reassemble sequence into final path attribute-->
<svg:path d="{$newvalue}"/>
</xsl:template>
Regards,
George

Re: Changing scales of an .svg path in XSLT 2.0

Posted: Tue Feb 10, 2009 2:57 am
by willisd1
Very good. Thanks again.

Since I am new to XSLT as well as programming in general, this is quite a process to educate myself. It's nice to have some experience available to keep a newbie moving forward.