Changing scales of an .svg path in XSLT 2.0

Here should go questions about transforming XML with XSLT and FOP.
willisd1
Posts: 8
Joined: Fri Jan 23, 2009 4:46 pm

Changing scales of an .svg path in XSLT 2.0

Post 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.
willisd1
Posts: 8
Joined: Fri Jan 23, 2009 4:46 pm

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

Post 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-->
george
Site Admin
Posts: 2095
Joined: Thu Jan 09, 2003 2:58 pm

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

Post 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
George Cristian Bina
willisd1
Posts: 8
Joined: Fri Jan 23, 2009 4:46 pm

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

Post 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.
Post Reply