Link to home
Start Free TrialLog in
Avatar of sturquette
sturquette

asked on

Crossing name spaces in XSL Transformations

Given the following transformation, is it possible to call the UtilityMethod that is coded under the Group2 namespace from a function within the Group1 name space without rewriting the UtilityMethod in the Group1 namespace?

<?xml version="1.0" encoding="utf-8"?>
<xsl:transform version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:ms="urn:schemas-microsoft-com:xslt"
      xmlns:Group1="urn:myScript1:js"
      xmlns:Group2="urn:myScript2:js"
      >
      <xsl:output method="text"/>

      <ms:script language="JScript" implements-prefix="Group1">
      <![CDATA[
            function SomeFunction(someArg) {
                  //do some stuff
                  return "something";
            }
      ]]>
      </ms:script>

      <ms:script language="JScript" implements-prefix="Group2">
      <![CDATA[
            function SomeMethod(anotherArg) {
                  //do some stuff

                  if (anotherArg.length > 0)
                        return UtilityMethod();
                  else
                        return "stuff";
            }
            function UtilityMethod(){
                  //do some stuff
                  return "utility things";
            }
      ]]>
      </ms:script>

      <xsl:template match="/">
      Results of Group 1 : <xsl:value-of select="Group1:SomeFunction('data')"/>
      Results of Group 2 : <xsl:value-of select="Group2:SomeMethod('')"/>
      Results of Group 2 : <xsl:value-of select="Group2:SomeMethod('data')"/>
      </xsl:template>

</xsl:transform>
Avatar of rdcpro
rdcpro
Flag of United States of America image

Have you tried it?  

I do know it's possible to nest these functions, so you could do it like:

<xsl:value-of select="Group2:UitilityMethod(Group1:SomeFunction('data'))"/>

Regards,
Mike Sharp
Avatar of sturquette
sturquette

ASKER

nesting is not really what I am after

I would like to call the UtilityMethod method in the Group2 Namespace from the SomeFunction method in the Group1 name space

something like this
function SomeFunction(someArg) {
      //do some stuff
      var myvar=UtilityMethod();
      return myvar;
}


This code throws an error when i run it until i create a UtilityMethod procedure in Group1
Avatar of Duane Lawrence
post the error
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.

Transformation Error : ERROR:  Microsoft JScript runtime error
Object expected
line = 5, col = 3 (line is offset from the start of the script block).
Error returned from property or method call.

Microsoft JScript runtime error
Object expected
line = 5, col = 3 (line is offset from the start of the script block).
Error returned from property or method call.

RangeError
-2147352567
If you do not include the DEFER attribute for the <SCRIPT> tag, and the function is called from the transformed document, an "Object Expected" error occurs.

http://support.microsoft.com/kb/q273793/
duanelawrence

That answer does not execute the code, it merely places the code in the transformed document.  In the solution I am seeking, I do not care about the transformed document.  

In the code I listed I had the following three lines
     Results of Group 1 : <xsl:value-of select="Group1:SomeFunction('data')"/>
     Results of Group 2 : <xsl:value-of select="Group2:SomeMethod('')"/>
     Results of Group 2 : <xsl:value-of select="Group2:SomeMethod('data')"/>
In the first line
I called a script function in Group1 namespace and got back a value
In the second line
I called a script function in Group2 namespace and got back a value
In the third line
I called a script function in Group2 namespace which called another method in Group2 namespace

My desired result is to call a method in Group1 namespace which will can call one or more methods in Group2 namespace
here is the outupt from lines 1,2 and 3 above

Results of Group 1 : something
Results of Group 2 : stuff
Results of Group 2 : utility things
I'll have to research this, but you can reach functions in two script blocks if they share the same namespace.  Like:
     <ms:script language="JScript" implements-prefix="Group1">
     <![CDATA[
          function SomeFunction(someArg) {
               //do some stuff
               //return "something";
                    return UtilityMethod();
          }
     ]]>
     </ms:script>

     <ms:script language="JScript" implements-prefix="Group1">
     <![CDATA[
          function SomeMethod(anotherArg) {
               //do some stuff

               if (anotherArg.length > 0)
                    return UtilityMethod();
               else
                    return "stuff";
          }
          function UtilityMethod(){
               //do some stuff
               return "utility things";
          }
     ]]>
     </ms:script>


Is there a reason both script block *must* be in separate namespaces?  

Regards,
Mike Sharp
It seems to me that this might be better if you put your library functions in an Extension Object, or even simply a COM object that any XSLT script could access.  Each script block could instantiate the helper class, and call methods on it.  

In fact, in Javascript, you could probably use the helper class as a prototype to extend it within the script block (javascript uses prototype inheritance, rather than class inheritance).  This is similar to how you might extend the Javascript Date object with a special method:

Date.prototype.toDateTimeString = function()
{
 var YYYY,MM,M,DD,D,hh,h,mm,m,ss,s;  
 YYYY = this.getFullYear() + "";
 MM = (M=this.getMonth()+1)<10?('0'+M):M;  
 DD = (D=this.getDate())<10?('0'+D):D;  
 h=this.getHours();  
 hh = h<10?('0'+h):h;  
 mm=(m=this.getMinutes())<10?('0'+m):m;  
 ss=(s=this.getSeconds())<10?('0'+s):s;  
 return YYYY + "-" + MM + "-" + DD + "T" + hh + ":" + mm + ":" + ss
}

It's used like:

var Now = new Date()
alert(Now.toDateTimeString());

In this example, all of the methods of the Date object are "inherited" and a new method is provided.  




Regards,
Mike Sharp
I am building a application that  will be compiled in C#.  
Most transformations will be accomplished by calling extensible objects in my compiled code, but I need to have the ability to add a script block in the transformation file with methods that access my extensible object methods in the same thread.  As I saw it, this is simply having a method of one namespace calling a method in another namespace.  This functionality is the cornerstone to my application to allow our installation personnel to make customizations in the transformation script while still giveing them the ability to use the compiled methods.  If I can "bridge the gap" and figure out how to make a call from one namespace to another, I believe that I will be very close in completing my goal.

I have already proven that I can
 create an object in C#
 load the xml and xslt file in XPathDocument and XslTransform objects respectively
 associate the Namespace using the AddExtensionObject method to the C# object
 Execute methods of the object in the XSLT transformation file
 gets/set properties of the C# object
 manipulate the object in C# and rerun the transformation to get the new values

All I have left to do is to write a script block that contains a method that can access the compiled C# object

Seems pretty complex, but really it is not.  Once I get this namespace thing out of the way, or an acceptable work around, I will have a pretty flexable application that, depending on your skillset, is completly customazible.

Steve T
Mike

As i understand Extension Objects, they are compiled code.  Under that paradigm all the functional scripts would be in compiled code. That would keep me from being able to customize the transformation scripts without changing compiled code.
ASKER CERTIFIED SOLUTION
Avatar of rdcpro
rdcpro
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I dont think that will work.  Here is what I got on my initial attempt.

System.Xml.Xsl.XsltException: Namespace '.....' has duplicate implementation.

I am going to try a couple of other combinations to see if I can get something to work.