Sarissa tests are written using ECMAUnit, a unit testing framework for ECMAScript (a.k.a. JavaScript). You can test Sarissa against your browser here. Please note that some tests may fail if you run those directly from your filesystem due to security restrictions in your browser; use a web server instead.
You don't have to. You can find compressed versions of each file along with the original ones. To use them, simply append "-compressed.js" (without the quotes) to the original file names when importing them to your webpage. We use the MobilVox Maven JavaScript Plugin to make the compressed versions, which are also used in our ECMAUnit tests.
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.
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");
But with Sarissa you do not need that, the code can be the same for all 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(new XMLSerializer().serializeToString(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!"); };
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(new XMLSerializer().serializeToString(oDomDoc));
To serialize an XML DOM Node simply feed it to an XMLSerializer object:
var xmlString = new XMLSerializer().serializeToString(someXmlDomNode);
You can check for and get a human-readable description of the error using the Sariss. 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");
In general, Sarissa uses the browser's native XSLTProcessor to control XSLT transformations. This includes Mozilla/FF, Opera, Webkit and IE. Sarissa transparently provides an implementation of XSLTProcessor for the latter. Notes::
The XSLTProcessor 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(new XMLSerializer().serializeToString(newDocument)); } // test the above function test("test 1");
The Javeline folk have created an XPath/XSLT compatibility library in pure javascript. The library is available for download on their dev site. To use the library with Sarissa, import the scripts to your webpage in the folowing order:
The Javeline XPath/XSLT compatibility library will provide implementations of XSLTProcessor and IE's XPath related extentions (i.e. selectNodes etc.).
Use the Sarissa.updateContentFromForm method:
<div id="targetId"> this content will be updated</div> <form action="/my/form/handler" method="post" onbeforesubmit="return Sarissa.updateContentFromForm(this, document.getElementById('targetId'));">
If JavaScript is supported, the form will not be submitted. Instead, Sarissa will scan the form and make an appropriate AJAX request, also adding a parameter to signal to the server that this is an AJAX call. The parameter is constructed as "Sarissa.REMOTE_CALL_FLAG=true" so you can change the parameter name simply by assigning another value to Sarissa.REMOTE_CALL_FLAG. If JavaScript is not supported the form will be submitted normally. Optionally, the response may be transformed before injected to the page, see also the API docs.
Loading a DOM document from a URL, transforming it and using it to update the content of an HTML element is a very common task if you are into "AJAX" apps. With Sarissa you can do it in a single line of code:
Sarissa.updateContentFromURI(sFromUrl, oTargetElement, xsltproc, callback, skipCache);
The parameters used here are:
Quite similarly, if you want to use an XML DOM object instead of a remote XML document simply take a look at Sarissa.updateContentFromNode
Note: To use updateContentFromURI or updateContentFromNode you need to include sarissa_dhtml.js in your HTML page.
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'");
In Mozilla/FF, DOM L3 XPath is always available and namespaces are resolved automatically if their scope covers the whole document (i.e. if declared in the root element node). If the namespace's scope is deeper, you must use Sarissa.setXpathNamespaces() to inform browsers (including Mozilla/FF) about them.
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>Sarissa XPath example</title> <script type="text/javascript" src="sarissa.js"> </script> <script type="text/javascript" src="sarissa_ieemu_xpath.js"> </script> <script type="text/javascript"> // <![CDATA[ function testXpath() { // create a DOM document 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>"; var 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"); // test XPath expressions on the document 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(new XMLSerializer().serializeToString(objNodeList[ i])); }; alert("testing selectSingleNode("+sXpath+") on a "+domNode); var oElem = domNode.selectSingleNode(sXpath); alert(oElem+"\n"+new XMLSerializer().serializeToString(oElem)); }; // ]]> </script> </head> <body> <button onclick="testXpath()">test xpath</button> </body> </html>
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: << << "' """&&'' < > & ' " </array-item> <array-item key="4">Epilogue</array-item> </chapters> <editor>Manos Batsis</editor> <publisher> <name>Some Publisher</name> </publisher> </book>