Solved

Use Jscript function result in <xsl:if test=>

Posted on 2003-11-07
7
642 Views
Last Modified: 2008-03-10
I am trying to use a <xsl:if> to test the value returned from a Jscript. I am using .Net Framework 1.1 to do transformation (XSLTransform). This works in MSXML4 ( using Xselerator ).  

The error  receive "Index is outside bounds of the array", is related to the <xsl:if>.

Here is sample code:
XML
-------------------------
<?xml version='1.0'?>
<root/>

XSL
---------------------------
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt"
    xmlns:user="urn:test">
      <msxsl:script language="JScript" implements-prefix="user" >
var CurrentLine = 1;

function GetAttr(s)
{
      return ' ';
}


function GetLine()  {
      return CurrentLine;
}
function IncrLine()  {
      CurrentLine = ++CurrentLine;
      return "";
}
      </msxsl:script>
      <xsl:template match="/">
            <test>
                  <line>
                        <xsl:value-of select="user:GetLine()" />
                  </line>
                  <line>
                        <xsl:if test="(user:GetLine() = 1)">
                              <sub>Passed</sub>
                        </xsl:if>
                  </line>
                  <line>
                        <xsl:value-of select="user:IncrLine()" />
                        <xsl:value-of select="user:GetLine()" />
                  </line>
            </test>
      </xsl:template>
</xsl:stylesheet>

////////////////////////////////////////////
Code
///////////////////////////////////////////
Imports System
Imports System.IO
Imports System.Xml
Imports System.Xml.XPath
Imports System.Xml.Xsl

Public Class Sample

   Private Const filename As String = "rootr.xml"
   Private Const stylesheet As String = "calc.xsl"

   Public Shared Sub Main()

    'Create the XslTransform and load the stylesheet.
    Dim xslt As XslTransform = New XslTransform
    xslt.Load(stylesheet)

    'Load the XML data file.
    Dim doc As XPathDocument = New XPathDocument(filename)

    'Create an XmlTextWriter to output to the console.            
    Dim writer As XmlTextWriter = New XmlTextWriter(Console.Out)
    writer.Formatting = Formatting.Indented

    'Transform the file.
    xslt.Transform(doc, Nothing, writer, Nothing)
    writer.Close()
  End Sub
End Class
'''''''''''''''''''''''''''''''''''//////////////////////////////////

Expected Output:
--------------------------------------------------------
<?xml version="1.0" encoding="UTF-16"?>
<test xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:user="urn:test">
      <line>1</line>
      <line>
            <sub>Passed</sub>
      </line>
      <line>2</line>
</test>
0
Comment
Question by:lrr81765
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 3
7 Comments
 
LVL 6

Expert Comment

by:metalmickey
ID: 9702225
I dont know anything about Jscript or .net  and i may be way off, but i think you have to screen javascript in the xslt as the parser will try to parse the characters in the javascript.

try encapsulating it in a CDATA tag

<![CDATA[

Your javascript goes here  

  ]]>


IE

<msxsl:script language="JScript" implements-prefix="user" >
<![CDATA[
var CurrentLine = 1;

function GetAttr(s)
{
    return ' ';
}


function GetLine()  {
    return CurrentLine;
}
function IncrLine()  {
    CurrentLine = ++CurrentLine;
    return "";
}
 ]]>
    </msxsl:script>

Should there be some XML in the XML file?

<?xml version='1.0'?>
<root/>



MM
0
 
LVL 26

Expert Comment

by:rdcpro
ID: 9703079
I hate to say this, but what lrr81765 is trying to do is a *bad* idea.  You should never code side-effects in XSLT.  Don't create a global variable and change it using functions calls, especially to get around the immutability of XSLT variables.  The reason for this is that you cannot predict the order of execution for templates.  The spec specifically states this, and the processor is free to make whatever optimizations it chooses.   I strongly suggest you come up with a different approach.

Regards,
Mike Sharp
0
 

Author Comment

by:lrr81765
ID: 9703770
Thank you all for the quick response. metalmickey, I have tried this as well, but it does not work.

rdcpro, what I am doing is keeping track of a line position ( not the same as currentline() or position() ). I have the pleasure of controlling the envioroment that it runs on (MS Framework) as well.  To envision this, imagine a parameter that is passed in called "lines" that is equal to 10. I want to continue processing until 10 lines have been processed, and perhaps, do something different on lines 2,3,6, and 9.

Can you give some type of alternative?
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 26

Expert Comment

by:rdcpro
ID: 9704104
Sure.  Use XSLT recursion.  I just posted a similar example.  This one looks to see the largest value of <event-week>, then builds the number of rows specified.  In this particular case, there is one node <event-week>6</event-week>, so it builds 6 rows on the table.  You can view it in action here:

http://dev.rdcpro.com/Members/rdcpro/misc/events.xml

The XSLT that makes this happen is:

http://dev.rdcpro.com/Members/rdcpro/misc/events-recursive.xslt

Or you can download them from:

http://dev.rdcpro.com/Members/rdcpro/misc/

Obviously, you could also set a parameter externally.

The thing about side effects in XSLT is that even within the MS .NET framework, you could find a subsequent version of the framework might make an optimization in the template processor that will break your code.   The specification is very specific on this point.  XSLT is Turing-complete, so there should never be a situation where you need a side-effect function like this.  

Regards,
Mike Sharp
0
 

Author Comment

by:lrr81765
ID: 9732774
rdcpro,
Ok I think I have a grip on the recursion.

Can I use the variable in the script functions (i.e.:
function GetLine()  {
      var x;
      x=<xsl:value-of select="$CurrentLine"/>;
      return x;
}

function IncrLine()  {
      <xsl:variable name="CurrentLine" select="$CurrentLine + 1" />;
      return ;
}

function ResetLine()  {
      <xsl:variable name="CurrentLine" value="1" />;
      return "";
}

-----------
And then do my test as <xsl:if test=$CurrentLine = 1" />

and be able to increment the variable with <xsl:value-of select="user:IncrLine()" />

?


0
 

Author Comment

by:lrr81765
ID: 9732873
Alas, reading the Magic Book tells me that the <xsl:variable> cannot be updated :(
0
 
LVL 26

Accepted Solution

by:
rdcpro earned 500 total points
ID: 9733344
You're still trying to get around immutability.

The key to understanding it is that a variable or parameter cannot be updated *in the current instance of a template*.  So if you want a new value for a variable, you need a new template instance.  That's why you use XSLT recursion for this.

Here's a simple example of a recursive counter, that increments an xsl:variable using recursion.  Remember, if the variable counts to 10, there will be 10 instances of the template that contains the variable.  Whether you do the recursion test before or after  you output the variable will determine whether the counting is ascending or descending...examine this example:

http://dev.rdcpro.com/Members/rdcpro/snippets/recursionandcounting/

Regards,
Mike Sharp
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

The Client Need Led Us to RSS I recently had an investment company ask me how they might notify their constituents about their newsworthy publications.  Probably you would think "Facebook" or "Twitter" but this is an interesting client.  Their cons…
Introduction In my previous article (http://www.experts-exchange.com/Microsoft/Development/MS-SQL-Server/SSIS/A_9150-Loading-XML-Using-SSIS.html) I showed you how the XML Source component can be used to load XML files into a SQL Server database, us…
In an interesting question (https://www.experts-exchange.com/questions/29008360/) here at Experts Exchange, a member asked how to split a single image into multiple images. The primary usage for this is to place many photographs on a flatbed scanner…
I've attached the XLSM Excel spreadsheet I used in the video and also text files containing the macros used below. https://filedb.experts-exchange.com/incoming/2017/03_w12/1151775/Permutations.txt https://filedb.experts-exchange.com/incoming/201…
Suggested Courses

751 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question