1

I have a HTML page with some Javascript that I'm trying to parse with XSLT 1.0. I want to modify a URL that's inside the Javascript to make the path absolute instead of relative.

The Javascript-code looks roughly like this:

<html>
    <head>
        <script>
            function login() {
                window.location = '{@myBase}/myloginpage';
            }
        </script>
    </head>

    <body>
     ...
    </body>
</html>

I want the '{@myBase}' to be replaced with my domain. I feel that I'm very much off course.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
   xmlns:proxy="java:senselogic.sitevision.portlet.proxy.web.ProxyFunctions" 
   extension-element-prefixes="proxy">


   <xsl:import href="template.xsl"/>

    <xsl:template match="//script/text()">
        <xsl:variable name="mypath">
          <xsl:call-template name="string-replace-all">
            <xsl:with-param name="text"><xsl:value-of select="{@myBase}"/></xsl:with-param>
            <xsl:with-param name="replace">{@myBase}</xsl:with-param>
            <xsl:with-param name="by">http://www.mydomain.com</xsl:with-param>
          </xsl:call-template>
        </xsl:variable>
    </xsl:template>    



    <xsl:template name="string-replace-all">
      <xsl:param name="text" />
      <xsl:param name="replace" />
      <xsl:param name="by" />
      <xsl:choose>
        <xsl:when test="contains($text, $replace)">
          <xsl:value-of select="substring-before($text,$replace)" />
          <xsl:value-of select="$by" />
          <xsl:call-template name="string-replace-all">
            <xsl:with-param name="text"
            select="substring-after($text,$replace)" />
            <xsl:with-param name="replace" select="$replace" />
            <xsl:with-param name="by" select="$by" />
          </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="$text" />
        </xsl:otherwise>
      </xsl:choose>
    </xsl:template>    
</xsl:stylesheet>
1
  • The notion of transforming a script inside an HTML page with XSLT is, frankly, bonkers. Without knowing more about the overall environment it's hard to say for sure, but one might note that this is a one-line sed program. Other alternatives, depending on who "owns" the HTML, include using a text editor to change {@myname} to your domain. :-) If you can add your own script to the page, it could be one-liner with String.replace. Bottom line is that XSLT is designed at heart to process XML and it just ain't the right way in general to do text stuff. What led you to think you wanted to use XSLT? Commented Dec 11, 2012 at 17:06

1 Answer 1

2

Actually, you are not far off.

Firstly, you are defineing a variable <xsl:variable name="mypath"> to hold the results of the call-template but not actually doing anything with it. I don't think you need to wrap it in a variable declaration at all.

Secondly, you are not passing the correct value to the text parameter. Instead of doing this

<xsl:with-param name="text"><xsl:value-of select="{@myBase}"/></xsl:with-param>

Do this

<xsl:with-param name="text"><xsl:value-of select="."/></xsl:with-param>

Or better still, this:

<xsl:with-param name="text" select="."/>

Try this XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:proxy="java:senselogic.sitevision.portlet.proxy.web.ProxyFunctions" extension-element-prefixes="proxy">
    <xsl:param name="domain" select="'http://www.mydomain.com'"/>

    <xsl:template match="//script/text()">
        <xsl:call-template name="string-replace-all">
            <xsl:with-param name="text" select="."/>
            <xsl:with-param name="replace" select="'{@myBase}'" />
            <xsl:with-param name="by" select="$domain"/>
        </xsl:call-template>
    </xsl:template>

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

    <xsl:template name="string-replace-all">
        <xsl:param name="text"/>
        <xsl:param name="replace"/>
        <xsl:param name="by"/>
        <xsl:choose>
            <xsl:when test="contains($text, $replace)">
                <xsl:value-of select="substring-before($text,$replace)"/>
                <xsl:value-of select="$by"/>
                <xsl:call-template name="string-replace-all">
                    <xsl:with-param name="text" select="substring-after($text,$replace)"/>
                    <xsl:with-param name="replace" select="$replace"/>
                    <xsl:with-param name="by" select="$by"/>
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="$text"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>

(Note that I have also set your domain to be a parameter)

When applied to your XHTML, the following is output

<html>
<head>
<META http-equiv="Content-Type" content="text/html">
<script>
            function login() {
                window.location = 'http://www.mydomain.com/myloginpage';
            }
        </script></head>
<body>
     ...
    </body>
</html>
Sign up to request clarification or add additional context in comments.

2 Comments

Tim, why don't you simplify <xsl:with-param name="text"><xsl:value-of select="."/></xsl:with-param> to <xsl:with-param name="text" select="."/>?
I've slightly simplified the parameters, as per Martin's suggestion. Thanks Martin!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.