Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Westi on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Problem combining svg and xslt 1

Status
Not open for further replies.

rjblok

Programmer
May 16, 2007
5
NL
Dear all,
I am not all that familiar with svg; nevertheless I wish to include a svg element in a xsl stylesheet.

If I run the following code I get my required output:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:transform version="1.0"
xmlns:xsl="
<xsl:template match="/">

<xsl:for-each select="TimeML/MAKEINSTANCE">
<xsl:if test="@tense!='NONE'">
<xsl:variable name='eventid'select="@eventID"/>
<xsl:for-each select="../BODY/bn_episode_trans/section/TEXT/turn/s/EVENT">
<xsl:if test="@eid=$eventid">
<xsl:value-of select="../."/>
</xsl:if>
</xsl:for-each>

</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:transform>

However, if I add <svg width="600px" height="250px" xmlns=" after the templatematch nothing seems to work anymore.

code:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:transform version="1.0"
xmlns:xsl="

<xsl:template match="/">
<svg width="600px" height="250px" xmlns=" <xsl:for-each select="TimeML/MAKEINSTANCE">
<xsl:if test="@tense!='NONE'">
<xsl:variable name='eventid' select="@eventID">
</xsl:variable>

<xsl:for-each select="../BODY/bn_episode_trans/section/TEXT/turn/s/EVENT">
<xsl:if test="@eid=$eventid">
<xsl:value-of select="../."/>
</xsl:if>
</xsl:for-each>

</xsl:if>
</xsl:for-each>
</svg>
</xsl:template>
</xsl:transform>

Does anyone know why, and how it can be solved?

Thanks in advance,

YT, Robert
 
It could happen if when you make the transformation with your "real" xml document, the document actually has a defined default namespace or prefixed namespace(s), then you always have to set up the xsl with that namespace(s) declared and with prefix (default in xml or not).

Suppose the "real" xml be declared like this.
[tt]
<root [blue]xmlns="urn:xyz"[/blue]>
<! etc etc ... -->
</root>
[/tt]
Then your xsl should be modifed to look like this.
[tt]
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:transform version="1.0"
xmlns:xsl=" [blue]xmlns:ns="urn:xyz" exclude-result-prefix="ns"[/blue]>


<xsl:template match="/">
<svg width="600px" height="250px" xmlns=" <xsl:for-each select="TimeML/MAKEINSTANCE">
<xsl:if test="@tense!='NONE'">
<xsl:variable name='eventid' select="@eventID">
</xsl:variable>

<xsl:for-each select="../BODY/bn_episode_trans/section/TEXT/turn/s/EVENT">
<xsl:if test="@eid=$eventid">
<xsl:value-of select="../."/>
</xsl:if>
</xsl:for-each>

</xsl:if>
</xsl:for-each>
</svg>
</xsl:template>
</xsl:transform>
[/tt]
 
Amendment
Forgotten to edit the cut and paste part as well. Here is a re-list.
[tt]
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:transform version="1.0"
xmlns:xsl=" [blue]xmlns:ns="urn:xyz" exclude-result-prefix="ns"[/blue]>


<xsl:template match="/">
<svg width="600px" height="250px" xmlns=" <xsl:for-each select="[blue]ns:[/blue]TimeML/[blue]ns:[/blue]MAKEINSTANCE">
<xsl:if test="@tense!='NONE'">
<xsl:variable name='eventid' select="@eventID">
</xsl:variable>

<xsl:for-each select="../[blue]ns:[/blue]BODY/[blue]ns:[/blue]bn_episode_trans/[blue]ns:[/blue]section/[blue]ns:[/blue]TEXT/[blue]ns:[/blue]turn/[blue]ns:[/blue]s/[blue]ns:[/blue]EVENT">
<xsl:if test="@eid=$eventid">
<xsl:value-of select="../."/>
</xsl:if>
</xsl:for-each>

</xsl:if>
</xsl:for-each>
</svg>
</xsl:template>
</xsl:transform>
[/tt]
 
Thanks for your reply,

Indeed, the root-element in the actual XML doc reeds:
<TimeML xmlns:xsi=" xsi:noNamespaceSchemaLocation="TimeML1.1.xsd" >

I changed the stylesheet to:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:transform version="1.0"
xmlns:xsl="xmlns:svg="xmlns:html="xmlns:ns="xsi: exclude-result-prefix="ns">

<xsl:template match="/">
<svg:svg width="600px" height="250px">
<xsl:for-each select="ns:TimeML/ns:MAKEINSTANCE">
<xsl:if test="@tense!='NONE'">
<xsl:variable name='eventid' select="@eventID"/>
<xsl:for-each select="../ns:BODY/ns:bn_episode_trans/ns:section/ns:TEXT/ns:turn/ns:s/ns:EVENT">
<xsl:if test="@eid=$eventid">
<xsl:value-of select="../."/><html:br/>
</xsl:if>
</xsl:for-each>

</xsl:if>
</xsl:for-each>

</svg:svg>
</xsl:template>
</xsl:transform>

But this does not seem to do the trick (see robdeb.freehostia.com/class.xml). Obviously, since I am not really sure what I am doing here it could just be a syntaxerror.
 
Ah, no. That's not what I meant, but it is good that you tried though. If all matching involved node which is not in the namespace of XMLSchema-instance, there is no need to do that.

I have not looked at your xml source. If without svg root, the transformation works, and that you assure there is no more namespace in the source xml, try something structurally like this.
[tt]
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:transform version="1.0"
xmlns:xsl="[blue]<xsl:eek:utput method="xml" media-type="image/svg+xml" encoding="ISO-8859-1" />[/blue]

<xsl:template match="/">
<svg width="600px" height="250px" xmlns=" <xsl:for-each select="TimeML/MAKEINSTANCE">
<xsl:if test="@tense!='NONE'">
<xsl:variable name='eventid' select="@eventID">
</xsl:variable>

<xsl:for-each select="../BODY/bn_episode_trans/section/TEXT/turn/s/EVENT">
<xsl:if test="@eid=$eventid">
<xsl:value-of select="../."/>
</xsl:if>
</xsl:for-each>

</xsl:if>
</xsl:for-each>
</svg>
</xsl:template>
</xsl:transform>
[/tt]
There is no reason inserting svg element as root does not produce the new xml document as desired. However, if the original xml is not validate or that the resultant svg is not properly svg, then everything is just conditional.
 
I've taken a look of the xml source. The transformation works but not properly done as far as the content rendering is concerned. But the main problem is that you are not making out a svg document.

This is the patchy correction to the script so as you can see the result to convince the transformation is working, and only the svg spec was not respected.
[tt]
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:transform version="1.0"
xmlns:xsl="<xsl:eek:utput method="xml" media-type="image/svg+xml" encoding="ISO-8859-1" />

<xsl:template match="/">
<svg [blue]width="1000px" height="800px"[/blue] xmlns=" [blue]<text fill="blue">[/blue]
<xsl:for-each select="TimeML/MAKEINSTANCE">
<xsl:if test="@tense!='NONE'">
<xsl:variable name='eventid' select="@eventID">
</xsl:variable>

<xsl:for-each select="../BODY/bn_episode_trans/section/TEXT/turn/s/EVENT">
<xsl:if test="@eid=$eventid">
[blue]<tspan x="10" dy="20">[/blue]
<xsl:value-of select="../."/>
[blue]</tspan>[/blue]
</xsl:if>
</xsl:for-each>
</xsl:if>
</xsl:for-each>
[blue]</text>[/blue]
</svg>
</xsl:template>
</xsl:transform>
[/tt]
Send the output to svg-aware application and you'll see the output.
 
Adding the xsl:eek:utput does not seem to work either. If I leave the svg tags out, output is generated, if it's in I get nothing. Nevertheless, my parser does not seem to complain.
This is the output without svg (robdeb.freehostia.com/class.xml).
Firefox shows correct output; opera says it seems there is no stylesheet associated with the XML file (there is...)

Do you have another suggestion?
 
It is not only the output element. There are other additions to make it svg document proper. I have no problem with that patch to be rendered in ff/op/.. though a bit boring as it contains only text.
 
Yeeh, thanks a million! I did not know the text and tspan where necessary!
The text output is quite boring; but is needs to go into a pop later on.
Thanks for you help anyway; I suppose I will get into some more troubles along the way: do I dare contact you again?

Cheers
Robert
 
Another question: how to go about if I would like to add a svg shape along with every sentence (so in every loop a shape at a new position)?
I found out working with variables is rather troublesome, for values cannot be changed once the are set. However, during every loop values must change to reposition a shape.

 
>how to go about if I would like to add a svg shape along with every sentence (so in every loop a shape at a new position)?
Sure the verbosity of xml can be adding to the difficulty to think straight. And the complexity of the matter itself which have _lot_ of numbers related to the positioning. Maybe this will get you some impetus.
[tt]
<xsl:template match="/">
<svg width="1500px" height="800px" xmlns=" viewBox="0 0 1500 800">
<g transform="translate(20,0)">
<text fill="black" style="font-family:Garamont;">
<xsl:for-each select="TimeML/MAKEINSTANCE[@tense!='NONE']">
<xsl:variable name='eventid' select="@eventID" />
<xsl:variable name="pos1" select="position()" />
<xsl:for-each select="../BODY/bn_episode_trans/section/TEXT/turn/s/EVENT[@eid=$eventid]">
<xsl:variable name="pos2" select="position()" />
<tspan x="10" dy="20">
<xsl:value-of select="../."/>
</tspan>
<circle cx="0" cy="{$pos1*$pos2*20 - 5}" r="3" fill="#c00" />
</xsl:for-each>
</xsl:for-each>
</text>
</g>
</svg>
</xsl:template>
[/tt]
For more involved case, the above apparent simplicity will be exponentially inflated.
 
Amendment

Upon reading what I posted and looking into the data more closely, I noticed that the hastily hack $pos1*$pos2 is only working by accident that $pos2 taking on value of 1 all the time. Conceptually, it is not correct and not applicable to general case. This is the amendment applicable to general case with the right logic of coordinating.
[tt]
<xsl:template match="/">
<svg width="1500px" height="800px" xmlns=" viewBox="0 0 1500 800">
<g transform="translate(20,0)">
<text fill="black" style="font-family:Garamont;">
[blue]<xsl:variable name="nlist" select="TimeML/MAKEINSTANCE[@tense!='NONE']" />[/blue]
<xsl:for-each select="TimeML/MAKEINSTANCE[@tense!='NONE']">
<xsl:variable name='eventid' select="@eventID" />
<xsl:variable name="pos1" select="position()" />
[blue]<xsl:variable name="count1_m1" select="count($nlist[position() &lt;= $pos1 - 1])" />[/blue]
<xsl:for-each select="../BODY/bn_episode_trans/section/TEXT/turn/s/EVENT[@eid=$eventid]">
<xsl:variable name="pos2" select="position()" />
<tspan x="10" dy="20">
<xsl:value-of select="../."/>
</tspan>
<circle cx="0" cy="{[red]($count1_m1+$pos2)[/red]*20 - 5}" r="3" fill="#c00" />
</xsl:for-each>
</xsl:for-each>
</text>
</g>
</svg>
</xsl:template>
[/tt]
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top