Figure 1 Processing the Equation with JScript
function processEquation(ops) {
var result=0, i;
for (i=0; i<ops.length; i++) {
switch(ops[i].nodeName) {
case "add":
result += parseFloat(ops[i].text); break;
case "sub":
result -= parseFloat(ops[i].text); break;
case "mul":
result *= parseFloat(ops[i].text); break;
case "div":
result = result / parseFloat(ops[i].text); break;
case "mod":
result = result % parseFloat(ops[i].text); break;
default:
return "Unsupport operation";
}
}
return result;
}
Figure 2 Processing the Equation with XSLT
<?xml version="1.0" encoding="utf-8"?>
<xsl:transform version="1.0"
xmlns:xsl="https://www.w3.org/1999/XSL/Transform"
>
<xsl:output method="text"/>
<xsl:template name="processEquation">
<xsl:param name="ops" select="/.."/>
<xsl:choose>
<xsl:when test="$ops">
<xsl:variable name="last" select="$ops[last()]"/>
<xsl:variable name="total">
<xsl:call-template name="processEquation">
<xsl:with-param name="ops"
select="$ops[position()!=last()]"/>
</xsl:call-template>
</xsl:variable>
<xsl:choose>
<xsl:when test="name($last)='add'">
<xsl:value-of select="$total + $last"/>
</xsl:when>
<xsl:when test="name($last)='sub'">
<xsl:value-of select="$total - $last"/>
</xsl:when>
<xsl:when test="name($last)='mul'">
<xsl:value-of select="$total * $last"/>
</xsl:when>
<xsl:when test="name($last)='div'">
<xsl:value-of select="$total div $last "/>
</xsl:when>
<xsl:when test="name($last)='mod'">
<xsl:value-of select="$total mod $last"/>
</xsl:when>
<xsl:otherwise>
<xsl:message terminate="yes">
Unsupported operation</xsl:message>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>0</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="/">
<!-- root template -->
result:
<xsl:call-template name="processEquation">
<xsl:with-param name="ops" select="/equation/*"/>
</xsl:call-template>
</xsl:template>
</xsl:transform>
Figure 3 Processing the Equation with XSLT + JScript
<?xml version="1.0" encoding="utf-8"?>
<xsl:transform version="1.0"
xmlns:xsl="https://www.w3.org/1999/XSL/Transform"
xmlns:ms="urn:schemas-microsoft-com:xslt"
xmlns:usr="urn:the-xml-files:xslt"
>
<xsl:output method="text"/>
<ms:script language="JScript" implements-prefix="usr">
<![CDATA[
function processEquation(ops) {
var result=0, i;
for (i=0; i<ops.length; i++) {
switch(ops[i].nodeName) {
case "add":
result += parseFloat(ops[i].text); break;
case "sub":
result -= parseFloat(ops[i].text); break;
case "mul":
result *= parseFloat(ops[i].text); break;
case "div":
result = result / parseFloat(ops[i].text); break;
case "mod":
result = result % parseFloat(ops[i].text); break;
default:
return "Unsupport operation";
}
}
return result;
}
]]>
</ms:script>
<xsl:template match="/">
<!-- root template -->
result: <xsl:value-of
select="usr:processEquation(/equation/*)"/>
</xsl:template>
</xsl:transform>
Figure 4 A Transformation
<xsl:transform version="1.0"
xmlns:xsl="https://www.w3.org/1999/XSL/Transform"
xmlns:out="https://www.w3.org/1999/xhtml"
xmlns:ext="https://example.org/extension"
extension-element-prefixes="ext"
>
<xsl:template match="/">
<out:html>
<xsl:choose>
<xsl:when
test="element-available('ext:doSomeFunkyMagic')">
<ext:doSomeFunkyMagic/>
</xsl:when>
<xsl:otherwise>
<!-- backup functionality goes here -->
•••
</xsl:otherwise>
</xsl:choose>
</out:html>
</xsl:template>
</xsl:transform>
Figure 5 The Same Transformation with Fallback
<xsl:transform version="1.0"
xmlns:xsl="https://www.w3.org/1999/XSL/Transform"
xmlns:out="https://www.w3.org/1999/xhtml"
xmlns:ext="https://example.org/extension"
extension-element-prefixes="ext"
>
<xsl:template match="/">
<out:html>
<ext:doSomeFunkyMagic>
<xsl:fallback>
<!-- backup functionality goes here -->
•••
</xsl:fallback>
</ext:doSomeFunkyMagic>
</out:html>
</xsl:template>
</xsl:transform>
Figure 6 Using Multiple msxsl:script Elements
<xsl:transform version="1.0"
xmlns:xsl="https://www.w3.org/1999/XSL/Transform"
xmlns:ms="urn:schemas-microsoft-com:xslt"
xmlns:js="urn:the-xml-files:xslt-js"
xmlns:vb="urn:the-xml-files:xslt-vb">
<xsl:output method="text"/>
<ms:script language="JScript" implements-prefix="js">
<![CDATA[
function SayHelloFromJScript(name) {
return "Hello from JScript:" + name;
}
]]>
</ms:script>
<ms:script language="VBScript" implements-prefix="vb">
<![CDATA[
function SayHelloFromVBScript(name)
SayHelloFromVBScript = "Hello from VBScript:" & name
end function
]]>
</ms:script>
<xsl:template match="/">
<!-- root template -->
<xsl:value-of select="js:SayHelloFromJScript('billy')"/>
<xsl:value-of select="vb:SayHelloFromVBScript('bob')"/>
</xsl:template>
</xsl:transform>
Figure 7 XPath/MSXML Type Mapping for Function
W3C XPath Type
|
Equivalent JScript/VBScript Type
|
String
|
String.
|
Boolean
|
Boolean.
|
Number
|
Number.
|
Result Tree Fragment
|
IXMLDOMNodeList that contains a single node of type NODE_DOCUMENT_ FRAGMENT.
|
Node Set
|
IXMLDOMNodeList.
|
Figure 8 Extension Function
<ms:script language="JScript" implements-prefix="math">
<![CDATA[
function CalcDistance(points) {
var xdelta =
parseFloat(points[0].selectSingleNode("x").text) -
parseFloat(points[1].selectSingleNode("x").text);
var ydelta =
parseFloat(points[0].selectSingleNode("y").text) -
parseFloat(points[1].selectSingleNode("y").text);
return Math.sqrt(Math.pow(xdelta, 2) +
Math.pow(ydelta, 2));
}
]]>
</ms:script>
Figure 9 Process Result Tree Fragment
<ms:script language="JScript" implements-prefix="math">
<![CDATA[
function CalcDistance(points) {
var x1 =
points[0].childNodes[0].selectSingleNode("x").text;
var x2 =
points[0].childNodes[1].selectSingleNode("x").text;
var y1 =
points[0].childNodes[0].selectSingleNode("y").text;
var y2 =
points[0].childNodes[1].selectSingleNode("y").text;
var xdelta = parseFloat(x1) - parseFloat(x2);
var ydelta = parseFloat(y1) - parseFloat(y2);
return Math.sqrt(Math.pow(xdelta, 2) +
Math.pow(ydelta, 2));
}
]]>
</ms:script>
Figure 10 XPath/MSXML Type Mapping for Return Values
JScript/VBScript Type
|
Equivalent W3C XPath Type
|
Number
|
Number
|
All other primitive types (String, Boolean, and so on)
|
String
|
Objects
|
Error
|
Figure 11 XPath/.NET Type System Mapping
W3C XPath Type
|
Equivalent .NET Class (Type)
|
String
|
System.String
|
Boolean
|
System.Boolean
|
Number
|
System.Double
|
Result Tree Fragment
|
System.Xml.XPath.XPathNavigator
|
Node Set
|
System.Xml.XPath.XPathNodeIterator
|
Figure 12 .NET Namespaces Available in msxsl:script
Namespace
|
Description
|
System
|
System class
|
System.Collection
|
Collection classes
|
System.Text
|
Text classes
|
System.Xml
|
Core XML classes
|
System.Xml.Xsl
|
XSLT classes
|
System.Xml.XPath
|
XPath classes
|
Figure 13 Calling from XPath
<xsl:transform version="1.0"
xmlns:xsl="https://www.w3.org/1999/XSL/Transform"
xmlns:ms="urn:schemas-microsoft-com:xslt"
xmlns:js="urn:the-xml-files:xslt-csharp"
>
<ms:script language="JScript" implements-prefix="js">
<![CDATA[
void function1() {
// omitted for brevity
}
void function2() {
// omitted for brevity
}
•••
]]>
</ms:script>
</xsl:transform>
Figure 14 Using a Person Object as an XSLT Extension
Dim xsldoc As New Msxml2.FreeThreadedDOMDocument40
Dim xmldoc As New Msxml2.FreeThreadedDOMDocument40
Dim xsltemp As New Msxml2.XSLTemplate40
Dim xslproc As Msxml2.IXSLProcessor
Dim p as New Person
p.name = "Michael"
p.age = 3
xsldoc.Load "person.xsl"
Set xsltemp.stylesheet = xsldoc.documentElement
Set xslproc = xsltemp.createProcessor
xmldoc.Load "input.xml"
xslproc.input = xmldoc
xslproc.addObject p, "urn:person"
xslproc.Transform
MsgBox xslproc.output
|