Sathya
Sathya

Reputation: 3

XSLT replace relative links with absolute links with data available in a variable

I am trying to replace relative links with absolute links where data is available in param.

Here is the xsl I am using.

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="2.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        xmlns:ext="http://exslt.org/common"
        exclude-result-prefixes="#all">

    <xsl:output method="html" encoding="UTF-8" omit-xml-declaration="yes" indent="no"/>

    <xsl:param name="text1">
     <span>Response from web service starts.<div>
        <a href="http://www.google.com">Absolute Link</a>
        Other stuff<a href="/link1">Relative Link</a></div>
        Response from web service done.</span>
    </xsl:param>

    <xsl:template match="/">
       <html>
       <body>       
           <a href="http://www.gmail.com">Link in HTML</a>                  
        <xsl:copy>
            <xsl:apply-templates select="ext:node-set($text1)//a[@href[starts-with(.,'/')]]"/>
        </xsl:copy>
       </body>
       </html>
     </xsl:template>

    <xsl:template match="a[@href[starts-with(.,'/')]]">
        <xsl:attribute name="href">
          <xsl:value-of select="concat('http://myserver',.)"/>
        </xsl:attribute>    
     </xsl:template>
    </xsl:stylesheet>

This is the output I need.

<html>
    <body>      
        <a href="http://www.gmail.com">Link in HTML</a>                 
        <span>
            Response from web service starts.
            <div>
                <a href="http://www.google.com">Absolute Link</a>
                Other stuff
                <a href="http://myserver/link1">Relative Link</a>
            </div>
            Response from web service done.
        </span>
    </body>
</html>

This xsl is not working. The input xml can be anything. I am wondering how the relative links in the parameter text1 can be replaced with absolute links and then rendered as html.

Any help is much appreciated. Thanks.

Upvotes: 0

Views: 223

Answers (2)

Martin Honnen
Martin Honnen

Reputation: 167726

You need to process all nodes and you need to put in an identity transformation template to copy the nodes you don't want to transform. Furthermore set up the template for the href attribute:

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:ext="http://exslt.org/common"
    exclude-result-prefixes="xs ext">

    <xsl:output method="html" encoding="UTF-8" omit-xml-declaration="yes" indent="no"/>

    <xsl:param name="text1">
        <span>Response from web service starts.<div>
            <a href="http://www.google.com">Absolute Link</a>
            Other stuff<a href="/link1">Relative Link</a></div>
            Response from web service done.</span>
    </xsl:param>

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="/">
        <html>
            <body>       
                <a href="http://www.gmail.com">Link in HTML</a>                  
                <xsl:copy>
                    <xsl:apply-templates select="ext:node-set($text1)/node()"/>
                </xsl:copy>
            </body>
        </html>
    </xsl:template>

    <xsl:template match="a/@href[starts-with(.,'/')]">
        <xsl:attribute name="href">
            <xsl:value-of select="concat('http://myserver',.)"/>
        </xsl:attribute>    
    </xsl:template>
</xsl:stylesheet>

Note that your stylesheet had version="2.0" but used the node-set extension function so I assumed you want to solve that with an XSLT 1.0 processor where you need to use the node-set function. If you really used an XSLT 2.0 processor then you can simplify <xsl:apply-templates select="ext:node-set($text1/node()"/> to <xsl:apply-templates select="$text1/node()"/>.

Upvotes: 1

Stefan Hegny
Stefan Hegny

Reputation: 2187

Instead of

<xsl:apply-templates select="ext:node-set($text1)//a[@href[starts-with(.,'/')]]"/>

you need a recursive copy and only modify the matching nodes

<xsl:apply-templates select="ext:node-set($text1)"/>
....
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>  
</xsl:template>

change the match of your <xsl:template match="a[@href[starts-with(.,'/')]]"> template to

 <xsl:template match="@href[starts-with(.,'/')]">

and then

Upvotes: 0

Related Questions