Jeni Tennison
> <xsl:element name="A">
> <xsl:attribute name="href">
>
javascript:Popup=window.open('','IntlPopup','alwaysRaised=1,dependent=1,
height=300,location=0,menubar=1,personalbar=0,scrollbars=0,status=0,
toolbar=0,width=590,resizable=0');
> Popup.focus();
> Popup.document.write('
> <TABLE>
> <xsl:copy-of select="tr"/>
> </TABLE>
> ');
> </xsl:attribute>
> Enlarge this table
> </xsl:element>
If you look at the code above, you'll see that you're setting the @href
attribute on the generated A element to a string inside which (as far as
the XSLT processor's concerned) you're creating a TABLE element, and a
number of copies of other elements as well.
XSLT processors justifiably won't let you put elements within attribute
content: you have to escape the < and >. This means that you can't simply
copy the tr elements across - you have to output them as serialised XML. I
wrote this template earlier today for a similar problem:
<xsl:template match="*" mode="serialise">
<xsl:text /><<xsl:value-of select="name()" />
<xsl:for-each select="@*">
<xsl:text> </xsl:text>
<xsl:value-of select="name()" />
<xsl:text />="<xsl:value-of select="." />"<xsl:text />
</xsl:for-each>
<xsl:text>></xsl:text>
<xsl:apply-templates mode="serialise" />
<xsl:text /></<xsl:value-of select="name()" />><xsl:text />
</xsl:template>
So, you can either replace the above with:
<xsl:element name="A">
<xsl:attribute name="href">
javascript:Popup=window.open
('','IntlPopup','alwaysRaised=1,dependent=1,height=300,
location=0,menubar=1,personalbar=0,scrollbars=0,
status=0,toolbar=0,width=590,resizable=0');
Popup.focus();
Popup.document.write('
<TABLE>
<xsl:apply-templates select="tr" mode="serialise" />
</TABLE>
');
</xsl:attribute>
Enlarge this table
</xsl:element>
Or you can use CDATA sections so that you don't have to worry about
escaping the < and > around the TABLE element:
<xsl:element name="A">
<xsl:attribute name="href">
<![CDATAjavascript:Popup=window.open
('','IntlPopup','alwaysRaised=1,dependent=1,height=300,location=0,
menubar=1,personalbar=0,scrollbars=0,status=0,toolbar=0,width=590,
resizable=0');
Popup.focus();
Popup.document.write('
<TABLE>]]>
<xsl:apply-templates select="tr" mode="serialise" />
<![CDATA[</TABLE>
');]]>
</xsl:attribute>
Enlarge this table
</xsl:element>
The resultant output will be:
<A
href="javascript:Popup=window.open
('','IntlPopup','alwaysRaised=1,dependent=1,height=300,location=0,
menubar=1,personalbar=0,scrollbars=0,status=0,toolbar=0,width=590,
resizable=0');
Popup.focus();
Popup.document.write('
<TABLE>
<tr>...</tr>
</TABLE>
');">Enlarge this table</A> but the Javascript processor will see the unescaped string:
javascript:Popup=window.open
('','IntlPopup','alwaysRaised=1,dependent=1,height=300,location=0,
menubar=1,personalbar=0,scrollbars=0,status=0,toolbar=0,width=590,
resizable=0');
Popup.focus();
Popup.document.write('
<TABLE>
<tr>...</tr>
</TABLE>
'); and therefore 'do the right thing'. Or should, anyway.
Additional note from David Carlisle:
> But what is the purpose of empty <xsl:text /> instructions? It's the same as putting the characters inside a non empty xsl:text,
but saves a few keystrokes. Note the end result is the same,
the white space used to indent the stylesheet is in nodes that only have
white space so is stripped.
<xsl:value-of select="name()" />
<xsl:text />="<xsl:value-of
is effectively same as
<xsl:value-of select="name()" />
<xsl:text>="<xsl:text><xsl:value-of
but both of those are not the same as
<xsl:value-of select="name()" />
="<xsl:value-of
which puts a newline and some spaces before the = in the output tree.
Mike Kay goes on:
An empty <xsl:text/> instruction splits a text node into two, typically
making one of them a whitespace-only node that will be stripped from the
stylesheet.
Useful e.g. in
<xsl:attribute>
<xsl:text/>[<xsl:value-of select="$x"/>]<xsl:text/>
</xsl:attribute>
to prevent newlines in the output. You can't put an <xsl:text> element
around the <xsl:value-of>, it's not allowed to contain child elements, and
the alternative of
<xsl:text>[</xsl:text><xsl:value-of select="$x"/><xsl:text>]</xsl:text>
is even uglier.
|