Solved

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

Posted on 2003-11-07
7
634 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
  • 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
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
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

What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

Join & Write a Comment

Browsing the questions asked to the Experts of this forum, you will be amazed to see how many times people are headaching about monster regular expressions (regex) to select that specific part of some HTML or XML file they want to extract. The examp…
I was working on a PowerPoint add-in the other day and a client asked me "can you implement a feature which processes a chart when it's pasted into a slide from another deck?". It got me wondering how to hook into built-in ribbon events in Office.
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
This video demonstrates how to create an example email signature rule for a department in a company using CodeTwo Exchange Rules. The signature will be inserted beneath users' latest emails in conversations and will be displayed in users' Sent Items…

747 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

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now