views:

432

answers:

1

I am using XSL to display an XML representation of an email message in browsers. Email attachments are stored in separate files to the main email XML file, and so I want the resulting web page for the email to contain a link to its attachments.

However some of the attachments are email messages themselves, and may have been forwards or replies and thus may have names containing colons like FW:Important. The name is URL-escaped as FW%3AImportant, and stored as a file as FW%3AImportant.xml.

The problem is that the URL in my XSL-produced web page is unescaped and once again contains the colon (file://FW:Important.xml) and thus is a broken link. What is the best way to stop this behaviour?

Here is the XML snippet:

<email:part email:filename="FW%3AImportant">
    <email:attachment filename="FW%3AImportant.xml">
        FW%3AImportant.xml
    </email:attachment>
</email:part>

And here is the XSL snippet:

<xsl:template match="email:email/email:parts">
    <xsl:for-each select="email:part/email:attachment">
        <a>
            <xsl:attribute name="href">
                <xsl:value-of select="@filename" />
            </xsl:attribute>
            <xsl:value-of select="@filename" />
        </a>
    </xsl:for-each>    
</xsl:template>
A: 

I think you are on the wrong track here. It is not XSLT that unescapes your URL, it is the browser.

The only escape sequences known to XML (and hence to XSLT) are in the form of "&xxx;". The "%xx" of your URL strings is left unchanged.

The problem is that your <a href="..."> contains exactly the string the browser is trying it with. So you are doing something wrong when encoding the URL.

When the file on the file-system is stored as:

FW%3AImportant.xml

then the correct URL to reference it must be:

<a href="FW%253AImportant.xml">FW%3AImportant.xml</a>
<!-- ------^^^ the '%' char itself must be escaped! -->

This means you have to URL-encode the string before you place it in a href attribute, just like in any other system that generates HTML.

Unfortunately, there is no native URL-encode function in XSLT. This means you can either use an extension function of your XSLT environment, or do the encoding in a separate template using XPath string functions. Since correct URL-encoding is not exactly trivial, I recommend using something proven here. Here is a stylesheet you can reference (<xsl:import>) that does it for you: http://skew.org/xml/stylesheets/url-encode/

Tomalak
That makes sense, I'll give it a go. I had already looked at that stylesheet but I was hoping for a simpler answer!
jwaddell