sarissa

sarissa

This document is the API Specification for sarissa.

Summary

TOC

Overview

Sarissa is an ECMAScript library acting as a cross-browser wrapper for native XML APIs. It offers various XML related goodies like Document instantiation, XML loading from URLs or strings, XSLT transformations, XPath queries etc and comes especially handy for people doing what is lately known as "AJAX" development.

Supported browsers are Mozilla - Firefox and family, Internet Explorer with MSXML3.0 and up, Konqueror (KDE 3.3+ for sure), Safari and Opera. Konq, Safari and Opera offer no XSLT/XPath scripting support AFAIK.

This document provides an overview of Sarissa along with examples of common tasks. The API documentation follows (thanks to JSDoc). This documentation is distributed under the GNU Free Documentation License (fdl.txt).

The latest version of Sarissa can always be found on the Sourceforge project page. Please send comments, corrections etc via email or the Sarissa forum..

License(s)

Sarissa is distributed under the GNU GPL version 2 (see gpl.txt) or higher, GNU LGPL version 2.1 (see lgpl.txt) or higher and Apache Software License 2.0 or higher (see asl.txt). This means you can choose one of the three and use that if you like. If you make modifications under the ASL, i would appreciate it if you submitted those. In case your copy of Sarissa does not include the license texts, you may find them online in various formats at http://www.gnu.org and http://www.apache.org.

Gredits (People)

See CHANGELOG.txt. My deepest apologies to anyone I fail to mention; please send over an email and I will fix it :-)

Gredits (Software)

Sarissa is documented with JSDoc, tested with ECMAUnit and built using Apache Ant.

Sarissa was inspired by articles and code available on the web, most notably the IE Emu Series [webfx.eae.net] at webfx and Cross-Browser DOM Wrapper article [webreference.com].

Here are some projects using Sarissa, please let me know of others:

Nearby, Dimitri Glazkov's XPath over HTML for MSIE (html-xpath) project at http://sourceforge.net/projects/html-xpath can be used as a complement to Sarissa. Moz already has DOM3 like HTML XPath support.

How to test Sarissa in your browser with ECMAUnit

Sarissa tests are written using ECMAUnit, a unit testing framework for ECMAScript (a.k.a. JavaScript). You can test Sarissa against your browser here.

How to obtain a DOM Document object

Obtaining a DOM Document object is as easy as calling a factory method:

// Get a browser-specific DOM Document object
var oDomDoc = Sarissa.getDomDocument();

Additionally, you can also pass two string parameters to that factory method. These parameters are a namespace and a local name respectively. Their combination builds the Document Element thus:

var oDomDoc = Sarissa.getDomDocument("http://foo.org/ns/uri","foo");

will build a representation of the following into memory:

<foo xmlns="http://foo.org/ns/uri"></foo>

In Mozilla, calling the Sarissa.getDomDocument method as above is equivalent to:

var oDomDoc = document.implementation.createDocument("http://foo.org/ns/uri","foo", null);

In the case you are using Internet Explorer, the Sarissa.getDomDocument method returns a DOM Document object, using the most recent MSXML ProgID available in your system for that Class. So supposing MSXML4.0 is available, the equivalent statement for IE is:

var oDomDoc = new ActiveXObject("Msxml2.DOMDocument.4.0");

If the arguments to the factory method include a namespace URI and node name, the proper DocumentElement is built and inserted in the Document object in IE as well.

How to obtain an XMLHTTP Request object

Creating an XMLHTTP/XMLHttpRequest is as easy as

var xmlhttp = new XMLHttpRequest();

In IE 7 this works asis. For users under IE prior to version 7, an XMLHTTP object is returned using the most recent MSXML ProgID found in the client system. So, supposing that the user has MSXML4.0 installed, the above is equal to:

var xmlhttp = new ActiveXObject("Msxml2.XMLHTTP.4.0");

Further coding on XMLHTTP objects is the same for both browsers, so:

var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", "http://foo.org/someDocument.xml", false);
// if needed set header information 
// using the setRequestHeader method
xmlhttp.send('');
alert(Sarissa.serialize(xmlhttp.responseXML));

will load the document from the server and then throw an alertbox with the contents of the file to your screen. XMLHTTP objects support both synchronous and asynchronous loading of remote XML documents (note the third parameter of the xmlhttp.open method above). In asynchronous loading, you will probably want to call a function to handle the object readystatechange events, see if loading is completed and then do whatever. To do that, add your onreadystatechange handler function before calling the send method. Something like:

xmlhttp.onreadystatechange = function()
{
	if(xmlhttp.readyState == 4)
		alert("Finished loading!");
};

How to load an XML Document Object from an XML String

You can also make a DOM Document "load" using an String variable with XML content. It's pretty simple using the DOMParser object:

var oDomDoc = Sarissa.getDomDocument();
var xmlString = "<root>my xml!</root>";
oDomDoc = (new DOMParser()).parseFromString(xmlString, "text/xml");
alert(Sarissa.serialize(oDomDoc));

How to check for parsing errors

You can chack for and get a human-readable description of the error using the Sarissa getParseErrorText method, passing the document as the argument:

if(Sarissa.getParseErrorText(oDomDoc) == Sarissa.PARSED_OK){
	// The document was parsed/loaded just fine, go on
	doSomething(oDomDoc);
} 
else{
	// The document was not loaded correctly! Inform the user:
	alert(Sarissa.getParseErrorText(oDomDoc));
};

Sarissa.getParseErrorText will return one of:

Tip: Wrap the result of Sarissa.getParseErrorText in a "pre" element if you want to render it.

If you have used the deprecated .load methods, you can also use the parseError property. The property always gives an integer, anything other than zero signals an error.

// ...
oDomDoc.async = false;
oDomDoc.load("someDocument.xml");
if(oDomDoc.parseError.errorCode != 0)
   alert("not well formed or other error!");
else
   alert("loaded ok");

How to transform a DOM Document Object with XSLT

Both Mozilla and IE provide JavaScript interfaces to control XSLT transformations thanks to Transformiix and MSXML3 (or above) respectively. MSXML3+ is available with IE6 or as a seperate instalation.

Sarissa emulates Mozilla's XSLTProcessor for Internet Explorer. This object allows reusability of stylsheets; with it you can use the same stylesheet on more than one source file. You use the XSLTProcessor to control transformations and set / get stylesheet parameters as in the following example:

// create an instance of XSLTProcessor
var processor = new XSLTProcessor();

// create a DOM Document containing an XSLT stylesheet
var xslDoc = Sarissa.getDomDocument();
var xslStr = "<?xml version='1.0' encoding='UTF-8'?>"+
  	"<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform' >"+
    	"<xsl:output method='html' version='1.0' encoding='UTF-8' indent='yes'/>"+
	"<xsl:param name='title'><xsl:value-of select=\"'default title'\"/></xsl:param>"+
    	"<xsl:template match='/'><p class='test' title='{$title}'>test</p>"+
        "</xsl:template><xsl:template match='@*'>"+
    	"</xsl:template></xsl:stylesheet>";
xslDoc = (new DOMParser()).parseFromString(xslStr, "text/xml");

// make the stylesheet reusable by importing it in the 
// XSLTProcessor
processor.importStylesheet(xslDoc);


// now XSLTProcessor is the 'proxy' for our stylesheet,
// the function below demonstrates usage
function test(paramValue) {
	// set a stylesheet parameter
	processor.setParameter(null, "title", paramValue);
    // create source document
    var xmlDoc = Sarissa.getDomDocument("http://foo.org/ns/uri","foo", null);
    // transform the document 
    var newDocument = processor.transformToDocument(xmlDoc);
    // show transformation results
    alert(Sarissa.serialize(newDocument));
}


// test the above function
test("test 1");

How to use XPath from JavaScript to select Nodes from an XML Document

Mozilla fully implements DOM Level 3 XPath so it was pretty trivial to implement IE's basic selectNodes and selectSingleNode methods, with full namespaces support. This is available in sarissa_ieemu_xpath.js. Actually IE also needs the proprietary setProperty method for it's XPath implementation to work. setProperty is used for a number of things in IE. First you'll have to use it to make XPath available for a certain document:

oDomDoc.setProperty("SelectionLanguage", "XPath");

In IE, using selectNodes or selectSingleNode without the above first will give an error. Also, the same method with different parameters is used to allow IE to resolve namespace prefixes, for example:

oDomDoc.setProperty("SelectionNamespaces", 
                    "xmlns:xhtml='http://www.w3.org/1999/xhtml'");

If you want to allow IE to resolve multiple namespace prefixes, use a space delimited list like:

oDomDoc.setProperty("SelectionNamespaces", 
                    "xmlns:xhtml='http://www.w3.org/1999/xhtml' 
                     xmlns:xsl='http://www.w3.org/1999/XSL/Transform'");

Mozilla does not need any of the above. DOM L3 XPath is always available and namespaces are resolved err... automatically. Below is an example of using selectNodes and selectSingleNode when Sarissa is available to provide cross browser XPath functionality. For more documentation on these proprietary methods check with the documentation at the MSDN website (http://msdn.microsoft.com). I'm not providing a URL for that as they constantly change their URLs.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
    <title>Untitled</title>
    <script type="text/javascript" src="sarissa.js">
    </script>
    <script type="text/javascript" src="sarissa_ieemu_xpath.js">
    </script>
    <script type="text/javascript">
    <!--
function testXpath()
{
    var xmlDoc = Sarissa.getDomDocument();
    var objNodeList;
    var xmlStr = "<?xml version='1.0' encoding='UTF-8'?>"+
        "<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>"+
        "<xsl:output method='xml' version='1.0' encoding='UTF-8' indent='yes'/>"+
        "<xsl:template match='*'></xsl:template><xsl:template match='@*'>"+
        "</xsl:template></xsl:stylesheet>";
        xmlDoc = (new DomParser()).parseFromString(xmlStr, "text/xml");
	
    // the following two lines are needed for IE
    xmlDoc.setProperty("SelectionNamespaces", "xmlns:xsl='http://www.w3.org/1999/XSL/Transform'");
    xmlDoc.setProperty("SelectionLanguage", "XPath");
	
    testSelectNodesOn(xmlDoc, "//xsl:template");
    testSelectNodesOn(xmlDoc.documentElement, "//xsl:template");
    testSelectNodesOn((xmlDoc.documentElement.getElementsByTagName("*"))[0], "//xsl:template");
}
function testSelectNodesOn(domNode, sXpath)
{
    alert("testing selectNodes("+sXpath+") on a "+domNode);
    var objNodeList = domNode.selectNodes(sXpath);
    for(i=0;i<objNodeList.length;i++)
        alert(Sarissa.serialize(objNodeList[i]));
    alert("testing selectSingleNode("+sXpath+") on a "+domNode);
    var oElem = domNode.selectSingleNode(sXpath);
    alert(oElem+"\n"+Sarissa.serialize(oElem));
};
    //-->
    </script>
</head>

<body>
<button onclick="testXpath()">test xpath</button>
</body>
</html>

How to serialize non-DOM objects to XML

You can easily convert any non DOM object to XML using the Sarissa.xmlize method. Sarissa will preserve the structure and naming of the object graph, translating it to an XML tree. Collection items are translated to array-item elements. For an example, the following lines:

// create an object hierarchy       	
book.chapters = new Array();
book.chapters[0] = "Kingdom of Tags";
book.chapters[1] = "Fall";
book.chapters[2] = "Final battle";
book.chapters[3] = "Characters that need to be escaped: << << \"' \"\"\"&&'' < > & ' \" ";
book.chapters[4] = "Epilogue";
book.editor = "Manos Batsis";
var publisher = new Object();
publisher.name = "Some Publisher";
book.publisher = publisher;

// serialize to an XML string
var s = Sarissa.xmlize(book, "book");
alert("Generated XML:\n"+s)

will generate the markup below:

<book>
   <chapters>
      <array-item key="0">Kingdom of fools</array-item>
      <array-item key="1">Fall</array-item>
      <array-item key="2">Final battle</array-item>
      <array-item key="3">
         Characters that need to be escaped: &lt;&lt; &lt;&lt; 
         &quot;&apos; 
         &quot;&quot;&quot;&amp;&amp;&apos;&apos; 
         &lt; &gt; &amp; &apos; &quot; 
      </array-item>
      <array-item key="4">Epilogue</array-item>
   </chapters>
   <editor>Manos Batsis</editor>
   <publisher>
      <name>Some Publisher</name>
   </publisher>
</book>

SourceForge.net Logo


File Summary
sarissa.js  
sarissa_dhtml.js  
sarissa_ieemu_xpath.js  
sarissa_ieemu_xslt.js  

sarissa

Documentation generated by JSDoc on Tue May 9 22:30:39 2006