HTML 4.01 strict HTML
Visit Sourceforge.net

General TabFAQ TabDOM TabSAX TabTOOLS Tab
General FAQ DOM SAX Tools

The documentation for XML for <SCRIPT> is broken up into five sections:

General: Documentation layout and philosophy
FAQ: Information on licensing and other general items
DOM Parser: Documents the DOM Parser and gives code examples
SAX Parser: Documents the SAX Parser and gives code examples
Tools: Documents the extra tools included with XML for <SCRIPT>

For a more in-depth understanding of XML for <SCRIPT>, you are highly encouraged to look at the source code for the test suites and the example applications. These demonstrate "real life" usage of the parsers and give a very good overview of the capabilities of the code.


CONTENTS
How does XML for <SCRIPT> comare to XML Data Islands?
What about document.implmentation.createDocument and MSXML?
How do I get the XML to the browser?
What license if XML for <SCRIPT> released under?
Help! Netscape 6 doesn't send my XML to the server!
Does XML for <SCRIPT> work in Konqueror/Safari?
Does XML for <SCRIPT> work in Opera?
Is there any type of error handling?
Are there any known bugs?
Why does the DOM parser always return a new XMLDoc object whenever it manipulates the tree?
The .js files are huge! Are there smaller ones available?
How does XML for <SCRIPT> comare to XML Data Islands?

There are a number of significant advantages to XML for <SCRIPT> over XML Data Islands.

1) XML for <SCRIPT> uses ECMA and W3C Standards, XML Data Islands do not.

This means that you will not be limiting your browser base to a single vendor, single browser solution. XML for <SCRIPT> has been tested to work with Netscape, Mozilla, Konqueror, Safari, Opera and Internet Explorer. XML Data Islands will only work with Internet Explorer, and only then on certain versions.

2) XML for <SCRIPT> does not pose security risks, XML Data Islands can.

XML Data Islands are usually used with the MSXML Parser. MSXML is an ActiveX object, which requires ActiveX scripting be enabed in the browser. Microsoft has a long history of security holes with this technology as it basically allows administrator access through the browser to the client's machine on many Windows platforms. It is possible to somewhat lock down IE to make this difficult, but that process must be done on each machine that is to use your application. This can create an administration nightmare.

XML for <SCRIPT>'s technology works within the browser's security sandbox and has none of these issues.

3) XML for <SCRIPT> does not require new software to be installed on the client machine, XML Data Islands often do.

The MSXML control that XML Data Islands commonly use is not guaranteed to be installed on client machines. This means that you must ensure that these controls are available for the browser to auto-install. This auto-install process is by no means foolproof and can break other applications on the system. Often, updates to these components require users to clear their component cache (a long and rather obtuse process) before downloading the components again to get the updates. Again, this can create an administration nightmare.

XML for <SCRIPT> does not effect any other part of the user's system and needs no installation. Since XML for <SCRIPT> is not distributed in binary form (as opposed to MSXML), fixes to your application need only be propagated to one place (the server) rather than out to each client.

4) XML for <SCRIPT> is open source and Free software, XML Data Islands are not.

When you download XML for <SCRIPT> you get full access to the source code to see how things are implemented. You are also free to modify, fix and change the software as you see fit as described by the LGPL license. XML Data Islands do not give you this freedom.

To be fair, in a controlled IE only environment, XML Data Islands may be a viable solution. However, tying yourself strictly to the Microsoft platform is a choice that must be very carefully made. Especially considering the threat of a Business Software Alliance audit, arbitrary licensing changes, security/administration problems and cost. XML for <SCRIPT> frees you from these concerns and allows you to focus on the task at hand.

What about document.implmentation.createDocument and MSXML?

Browser technology is advancing to the point where it is conceivable that in the near future, JavaScript handling of XML will be accomplished via the browser's own XML parser. Today, Mozilla and Internet Explorer for Windows allow you to create instances of their XML DOM parsers, load data and manipulate XML directly from JavaScript. The manner in which you create the XML Parser is different between the two browsers, but the interfaces to the parsers themselves complies with the W3C standards.

Mozilla uses the document.implementation.createDocument W3C standard to create a custom XML DOM object. To populate this object with data, Mozilla has extended the W3C specification to add a load() method which allows an XML file to be loaded into the parser.

Konqueror supports document.implementation.createDocument as well. However, as of Konqueror 3.1, no load() method extension is available. I have been in touch with the Konqueror developers and this feature is tentatively planned for Konqueror 3.2.

Internet Explorer for Windows uses a Windows-only ActiveX object to allow JavaScript access to an XML DOM tree. While the creation of this ActiveX object uses code that is proprietary to Internet Explorer for Windows, once the MSXML object is created, it exposes a W3C interface to JavaScript which allows for cross platform code to be written.

How does XML for <SCRIPT> compare to these technologies? Very well! Most importantly, XML for <SCRIPT> works in a wider range of browsers than both of these solutions. XML for <SCRIPT> also allows JavaScript developers to enhance and extend the parser in any way they see fit. This option is difficult in Mozilla and impossible for Internet Explorer. XML for <SCRIPT> also provides server-side proxies which allow for XML code to be loaded from any domain on the web.

Over time, as more and more browsers add support for JavaScript XML parsing, XML for <SCRIPT> may become unnecessary for complicated web application development. In the mean time, however, it serves an important role in the process of creating robust, cross platform web applications.

How do I get the XML to the browser?

There are many ways to get the XML from the server side to the client. However, depending on your targeted browser set, some ways may be better than others. In many cases, it is best to use absolute positioning to position a <textarea> off of the screen that contains your XML text. Modern browsers make this option very easy by using cascading style sheets. Older browsers may require some tweaking.

Another option is to put your XML in a hidden <input> element.

In any case, please be sure to escape out your XML when you place it in your HTML page. While some browsers may let you do something like this:

<textarea>
<?xml version="1.0"?>
<ROOTNODE>
<NODE>
value
</NODE>
</ROOTNODE>
</textarea>

the above code is invalid HTML and can cause serious problems in some browsers, noteably Mozilla.

In many cases, these browsers will change the case of the tags (or add new ones) which will break the parser. Oddly enough, not all tags get modified. An example of one that does is <TITLE>. With unescaped XML in a textarea element, mozilla will change the case of the tag leading the DOM parser to report an error of "expected /TITLE found closing /title".

The XML code sent to the browser really should be escaped to HTML, as demonstrated below:

<textarea>
&lt;?xml version="1.0"?&gt;
&lt;ROOTNODE&gt;
&lt;NODE&gt;
value
&lt;/NODE&gt;
&lt;/ROOTNODE&gt;
</textarea>

New in version 2.0 of XML for <SCRIPT> is a tool that will help you automate the changing of your XML into valid HTML. Rather than convert the XML to escaped HTML (which can be hard to read and bloated) it converts the <, >, and & characters into high ASCII characters that are unlikely to be in your XML stream. This tool can be found under the "Tools" link on the left.

What license is XML for <SCRIPT> released under?

XML for <SCRIPT> is released under the GNU Library (Lesser) General Public License. For more informaiton, please see the COPYING file included in the distribution.

Help! Netscape 6 doesn't send my XML to the server!

Netscape 6 (and all Mozilla derivitives up to Mozilla .97) have a bug that causes them not to send form data back to the server if the form element has its CSS property "display" set to "none". In this case, it is necessary to set the "display" property to something else (i.e. "block") and then submit the form.

Instead of using "display: none" consider absolute positioning. It is cross-platform with the modern browsers and avoids this problem.

The status of this bug can be found here.

Does XML for <SCRIPT> work in Konqueror/Safari?

Konqueror versions 2.2 and higher should work just fine with XML for <SCRIPT> DOM versions 1.1 and higher. Konqueror versions 3.0 are required to run the SAX parser included in XML for <SCRIPT> version 2.0

Konqueror versions prior to 2.2 seem to have problems with some of the recursive elements of XML for <SCRIPT> and some of the regular expressions used to escape illegal XML characters.

Konqueror versions prior to 3.0 had difficulties with the anonymous functions included in the SAX parser of XML for <SCRIPT> version 2.0.

Safari is based off of Konqueror 3.03 and has no known issues with XML for <SCRIPT>

Does XML for <SCRIPT> work in Opera?

Yes! Opera 5, 6 and 7 fully pass the XML for <SCRIPT> test suites. Please keep in mind that if you're targeting Opera versions prior to 7.0, some of the HTML DOM manipulation functions are different than IE, Konqueror or Mozilla. They are actually more like Netscape 4. For more information, please see the clearTestResults() and insertOptionElement() functions included with the test suites.

Is there any type of error handling?

Yes. XML for <SCRIPT> has a number of different ways to handle errors depending on which parser you use. For the DOM parser, you may define an error function in the constructor of your XMLDoc object. This function will be called with a parameter indicating the error string. For example:

var objDom = new XMLDoc(strXML, xmlError);

In this case, "xmlError" is a "pointer" to a function that XML for <SCRIPT> will call if there is an error. xmlError should be present in your script and should accept a single parameter. This parameter will be the string of the error. For example:

function xmlError(strError) {
alert(strError);
}

The XMLDoc object also has the hasErrors property you may query to see if any errors have been reported.

For the SAX parser, errors are reported in one of many of the SAX events. Once a SAX error has been fired parsing of the XML file stops at that point.

For more information on error handling, please look at the test suites for the parsers and inspect the error handling functions.

Are there any known bugs?

Yes. XML for <SCRIPT>'s DOM parser has two known bugs with attributes and attribute values.

1) If you place an > in the value of your attribute, XML for <SCRIPT> will appear to lock the browser. In fact, it is in a loop and will continue to call the error function until the browser is killed.

2) If you forget to close your attribute value with a quote, the same behavior as bug #1 can be observed.

XML for <SCRIPT> also has a bug where the function insertNodeInto will not produce the expected results for CDATA type nodes if the data contained within the CDATA tag contains a ">" symbol.

XML for <SCRIPT>'s 2.0 SAX parser had a bug in its attribute handling as well. If an empty attribute (e.g. emptyAttribute="") followed an attribute that was not empty, the empty attribute would be assigned the value of the previous, non-empty attribute. This bug was fixed in XML for <SCRIPT> 2.1

Why does the DOM parser always return a new XMLDoc object whenever it manipulates the tree?

At the moment, many of XML for <SCRIPT>'s dom manipulation functions are rather inefficient. An attempt was made to make all of the DOM manipulation be performed at the node level. However, JavaScript itself got in the way and prevented the code from working properly. For example, a node would be manipulated in the parser correctly, but as soon as the function returned into the application code, the node would no longer be updated correctly in either the local node object or the local XMLDoc object. It's unknown at this time whether this was a bug in the parser or a limitation of JavaScript.

Not all DOM manipulation functions had this problem. However, a consistant API was deemed more important than the performance benefits that would have been achieved with node-level manipulation. In addition, the performance of the parser is rather good even with the design employed. XML for <SCRIPT>'s dom manipulation functions have been used with success on large projects with large XML streams with adequate results.

This issue will be addressed in the future if the performance need arises. Patches are always welcome.

The .js files are huge! Are there smaller ones available?

Yes and no... There is a file called tinyxmldom.js included with the distribution. It has been run through the JavaScript Crunchinator at brainjar.com. This file is roughly 70% smaller than the standard xmldom.js file.

Currently, there is not a compressed version of xmlsax.js. This is due to me not being able to get the compressed version of it to work properly in the browsers after it had been crunched. If you would like to contribute a compressed tinyxmlsax.js file, I would appreciate it. If you do, please also include the diffs to xmlsax.js so that I can compress the files in the future as well.


CONTENTS
How do I get started with the DOM parser?
 
XMLDoc Object - Constructor
XMLDoc Object - createXMLNode method
XMLDoc Object - docNode property
XMLDoc Object - getUnderlyingXMLText method
XMLDoc Object - hasErrors property
XMLDoc Object - insertNodeAfter method
XMLDoc Object - insertNodeInto method
XMLDoc Object - loadXML method
XMLDoc Object - removeNodeFromTree method
XMLDoc Object - replaceNodeContents method
XMLDoc Object - source property
 
XMLDoc/XMLNode Object - selectNode method
XMLDoc/XMLNode Object - selectNodeText method
 
XMLNode Object - Constructor
XMLNode Object - addAttribute method
XMLNode Object - getAttribute method
XMLNode Object - getAttributeNames method
XMLNode Object - getElementById method
XMLNode Object - getElements method
XMLNode Object - getText method
XMLNode Object - getParent method
XMLNode Object - getUnderlyingXMLText method
XMLNode Object - nodeType property
XMLNode Object - removeAttribute method
XMLNode Object - tagName property
XMLNode Object - toString method
 
convertEscapes
convertToEscapes
trim
How do I get started with the DOM parser?

It's very easy, really. Let's say you have the following XML:

<?xml version="1.0"?>
<ROOTNODE>
<TAG1>
Hello World
</TAG1>
</ROOTNODE>

and you want to get the text out of the TAG1 tag. Here's the code:

function displayXML() {
var xml;
xml = ""
+ "<?xml version=\"1.0\"?>"
+ "<ROOTNODE>"
+ "<TAG1>"
+ "Hello World"
+ "</TAG1>"
+ "</ROOTNODE>";

//instantiate a new XMLDoc object. Send any errors to the xmlError function
var objDom = new XMLDoc(xml, xmlError)
//get the root node
var objDomTree = objDom.docNode;
//get all of the elements named "TAG1"
var tag1Elements = objDomTree.getElements("TAG1");
//get the first "TAG1" element
var element = tag1Elements[0];
//now get the text
var text = element.getText();
//show the user
alert(text);
} // end function displayXML

function xmlError(e) {
//there was an error, show the user
alert(e);
} //end function xmlError
XMLDoc Object - Constructor

var objDom = new XMLDoc(<xml string>, <error function>)

accepts:
<xml string>: string containing XML text
<error function>: function name to call if there is an error

returns:
new XMLDoc object

Example:
function displayXML() {
var xml;
xml = ""
+ "<?xml version=\"1.0\"?>"
+ "<ROOTNODE>"
+ "<TAG1>"
+ "Hello World"
+ "</TAG1>"
+ "</ROOTNODE>";

//instantiate a new XMLDoc object. Send any errors to the xmlError function
var objDom = new XMLDoc(xml, xmlError)
} // end function displayXML

function xmlError(e) {
//there was an error, show the user
alert(e);
} //end function xmlError
XMLDoc Object - createXMLNode method

var newNode = objDom.createXMLNode(<xml string>);

accepts:
<xml string>: string containing XML text

returns:
new XMLNode object

createXMLNode is a convienience function to create a new node that inherits the properties of the document object

Example:
//objDom is an object of type XMLDoc
var newNode = objDom.createXMLNode("<TAG2>test</TAG2>");

See also: domManipulationTestOne in domTestSuite.js

XMLDoc Object - docNode property

var rootNode = objDom.docNode;

accepts:
N/A

returns:
new XMLNode object

If the instantiation of the XMLDoc object is successful, the docNode property will return the root node of the XML text.

Example:
xml = ""
+ "<?xml version=\"1.0\"?>"
+ "<ROOTNODE>"
+ "<TAG1>"
+ "Hello World"
+ "</TAG1>"
+ "</ROOTNODE>";

var objDom = new XMLDoc(xml, xmlError);
//get the root node
var objDomTree = objDom.docNode;

XMLDoc Object - getUnderlyingXMLText method

objDom.getUnderlyingXMLText()

accepts:
N/A

returns:
string: The current XML representation of the XMLDoc object omitting processing instructions and DTD's. Also, this function turns any <TAG/> tags into <TAG></TAG>

Example:
var xml = ""
+ "<?xml version=\"1.0\"?>"
+ "<FOO>"
+ "<BAR>"
+ "hello"
+ "</BAR>"
+ "</FOO>";
var objDom = new XMLDoc(xml, xmlError);
alert(objDom.getUnderlyingXMLText());

See also: underlyingXMLFunctionsTestOne in domTestSuite.js

XMLDoc Object - hasErrors property

objDom.hasErrors;

accepts:
N/A

returns:
N/A

Checking for the hasErrors property is one way of determining if an error has been reported. The recommended way of checking, however, is to catch the error in the error function passed into the XMLDoc constructor.

Example:
xml = ""
+ "<?xml version=\"1.0\"?>"
+ "<ROOTNODE>"
+ "<>"
+ "</ROOTNODE>";
var objDom = new XMLDoc(xml, xmlError);
alert(objDom.hasErrors);
XMLDoc Object - insertNodeAfter method

objDom = objDom.insertNodeAfter(<reference node>, <new node>)

accepts:
<reference node>: the node to insert the new node after
<new node>: the new node object to insert after the reference node object

returns:
new XMLDoc object

insertNodeAfter will place a new node after the reference node at the same level. For example, inserting a new node with the text <NEW>new!</NEW> after the <REFERENCE> node in the following XML will yield:

Users of XML for <SCRIPT> should call the convertToEscapes function any time they are performing dom manipulation by adding new nodes consisting of user-generated text with the exception of CDATA type nodes. While XML for <SCRIPT> is generally rather loose with what it will allow in text, many other parsers are not and will generate an error if one of these characters is unescaped. For more information, see the information under convertToEscapes in the TOOLS section of the documentation.

Before:
<ROOTNODE>
<REFERENCE>
reference node
</REFERENCE>
</ROOTNODE>

After:
<ROOTNODE>
<REFERENCE>
reference node
</REFERENCE>
<NEW>
new!
</NEW>
</ROOTNODE>

Example:
var xml = ""
+ "<?xml version=\"1.0\"?>"
+ "<ROOTNODE>"
+ "<TAG1>"
+ "</TAG1>"
+ "</ROOTNODE>"
var objDom = new XMLDoc(xml, xmlError);
var domTree = objDom.docNode;
var referenceNode = domTree.getElements("TAG1")[0];
//create the new node
var newNode = objDom.createXMLNode("<TAG2>test</TAG2>");
//now add it to the tree
objDom = objDom.insertNodeAfter(referenceNode, newNode);

See also: domManipulationTestOne in domTestSuite.js

XMLDoc Object - insertNodeInto method

objDom = objDom.insertNodeInto(<reference node>, <new node>)

accepts:
<reference node>: the node to insert the new node into
<new node>: the new node object to insert into the reference node object

returns:
new XMLDoc object

insertNodeInto will place a new node into the reference node directly after the end of the reference node's tag declaration. For example, inserting a new node with the text <NEW>new!</NEW> into the <REFNCE> node in the following XML will yield:

Users of XML for <SCRIPT> should call the convertToEscapes function any time they are performing dom manipulation by adding new nodes consisting of user-generated text with the exception of CDATA type nodes. While XML for <SCRIPT> is generally rather loose with what it will allow in text, many other parsers are not and will generate an error if one of these characters is unescaped. For more information, see the information under convertToEscapes in the TOOLS section of the documentation.

Before:
<ROOT>
<REFNC>
<TAG1>
value
</TAG1>
</REFNC>
</ROOT>

After:
<ROOT>
<REFNC>
<NEW>
new!
</NEW>
<TAG1>
value
</TAG1>
</REFNC>
</ROOT>

Example:
var xml = ""
+ "<?xml version=\"1.0\"?>"
+ "<ROOT>"
+ "<TAG1>"
+ "<TAG3>"
+ "value"
+ "</TAG3>"
+ "</TAG1>"
+ "</ROOT>";
var objDom = new XMLDoc(xml, xmlError);
//first find the node to insert into, in this case, TAG1
var domTree = objDom.docNode;
var referenceNode = domTree.getElements("TAG1")[0];
//create the new node
var newNode = objDom.createXMLNode("<TAG2>test</TAG2>");
//now add it to the tree
objDom = objDom.insertNodeInto(referenceNode, newNode);

See also: domManipulationTestTwo in domTestSuite.js

XMLDoc Object - loadXML method

loadStatus = objDom.loadXML(<XML String>)

accepts:
<XML String>: The XML String to parse

returns:
true if the parsing was successful
false if the parsing failed

The primary purpose of the loadXML method is to reuse a pre-existing XMLDoc object and load it with new data.

NOTE: To read information out of the new XMLDoc object, you will need to get a new handle to the new XMLDoc object docNode via the docNode property. See below for an example of the correct syntax.

function displayXML() {
var xml1;
xml1 = ""
+ "<?xml version=\"1.0\"?>"
+ "<ROOTNODE>"
+ "<TAG1>"
+ "Hello World"
+ "</TAG1>"
+ "</ROOTNODE>";


var xml2;
xml2 = ""
+ "<?xml version=\"1.0\"?>"
+ "<ROOTNODE>"
+ "<TAG1>"
+ "Why Hello. Say, do you have the time"
+ "</TAG1>"
+ "</ROOTNODE>";
//instantiate a new XMLDoc object. Send any errors to the xmlError function
var objDom = new XMLDoc(xml1, xmlError)
//get the root node
var objDomTree = objDom.docNode;
//get all of the elements named "TAG1"
var tag1Elements = objDomTree.getElements("TAG1");
//get the first "TAG1" element
var element = tag1Elements[0];
//now get the text
var text1 = element.getText();
//now load the 2nd XML
objDom.loadXML(xml2);
//get the new root node
var objDomTree = objDom.docNode;
//get all of the elements named "TAG1"
var tag1Elements = objDomTree.getElements("TAG1");
//get the first "TAG1" element
var element = tag1Elements[0];
//now get the text
var text2 = element.getText();
//now show the user
alert("the first value was " + text1 + ". The second value was " + text2);
} // end function displayXML

See also domLoadTestOne and domLoadTestTwo in domTestSuite.js

XMLDoc Object - removeNodeFromTree method

objDom = objDom.removeNodeFromTree(<reference node>)

accepts:
<reference node>: the node to remove from the tree

returns:
new XMLDoc object

removeNodeFromTree will remove the reference node (and all of it's children) from the XMLDoc object. For example, removing the node with the text <NEW>new!</NEW> from the following XML will yield:

Before:
<ROOT>
<REFNC>
<NEW>
<TAG1>
value
</TAG1>
</NEW>
</REFNC>
</ROOT>

After:
<ROOT>
<REFNC>
</REFNC>
</ROOT>

Example:
var xml = ""
+ "<?xml version=\"1.0\"?>"
+ "<ROOT>"
+ "<TAG1>"
+ "<TAG2>"
+ "hello"
+ "</TAG2>"
+ "</TAG1>"
+ "</ROOT>";
var objDom = new XMLDoc(xml, xmlError);
//first find the node that we want to delete in this case it is TAG2
var domTree = objDom.docNode;
var referenceNode = domTree.getElements("TAG1")[0].getElements("TAG2")[0];
//now remove the node
//******** REMEMBER that the return value is a new DOM object!!! ********
objDom = objDom.removeNodeFromTree(referenceNode);

See also: domManipulationTestThree in domTestSuite.js

XMLDoc Object - replaceNodeContents method

objDom = objDom.replaceNodeContents(<reference node>, <value>)

accepts:
<reference node>: the node to have it's contents replaced
<value>: the new value of the node

returns:
new XMLDoc object

replaceNodeContents is generally used to replace the text value of a node. <value> is commonly just the new string value you would like returned in the node's getText() method. In this case, the text of the node is replaced word for word with what is passed in by the <value> parameter. However, <value> can also be a totally new XML string, allowing for the placement of any number of new nodes inside the reference node.

Unlike the function insertNodeInto, replaceNodeContents removes all of the current contents of the reference node and replaces them with the contents of <value>. The only information retained are the attributes of the node.

For example, replacing the contents of <TAG1> with "hello" in the following XML will yield:

Before:
<ROOT>
<REFNC>
<TAG1>
value
</TAG1>
</REFNC>
</ROOT>

After:
<ROOT>
<REFNC>
<TAG1>
hello
</TAG1>
</REFNC>
</ROOT>

Replacing the contents of <REFNC> with "hello" in the following XML will yield:

Before:
<ROOT>
<REFNC>
<TAG1>
value
</TAG1>
</REFNC>
</ROOT>

After:
<ROOT>
<REFNC>
hello
</REFNC>
</ROOT>

Example:
var xml = ""
+ "<?xml version=\"1.0\"?>"
+ "<ROOTNODE>"
+ "<TAG1 attribute=\"keepme\">"
+ "foo"
+ "</TAG1>"
+ "</ROOTNODE>";
var objDom = new XMLDoc(xml, xmlError);
//first find a node to replace its contents, in this case, TAG1
var domTree = objDom.docNode;
var rfnceNode = domTree.getElements("TAG1")[0];
//now do the replace
//******** REMEMBER that the return value is a new DOM object!!! ********
objDom = objDom.replaceNodeContents(rfnceNode, "new value");

See also: domManipulationTestFour in domTestSuite.js

XMLDoc Object - source property

objDom.source;

accepts:
N/A

returns:
N/A

The XMLDoc objects source property represents the *original* source XML for the object. This property is *not* updated by the dom manipulation functions.

Example:
xml = ""
+ "<?xml version=\"1.0\"?>"
+ "<ROOT>"
+ "<TAG1>"
+ "value"
+ "</TAG1>"
+ "</ROOT>";
var objDom = new XMLDoc(xml, xmlError)
alert(objDom.source);
XMLDoc/XMLNode Object - selectNode method

objDOM.selectNode(<search string>)
objNODE.selectNode(<search string>)

accepts:
<search string>: the tag path search string

returns:
NODE object (if node found) or null if not found

XML for <SCRIPT> tagPath searching allows JavaScript developers who know the layout and structure of their XML documents easy access to the nodes in their XML Dom. The format of the search criteria is similar to that of CSS Selectors. Consider the following code:

var xml = "<?xml version=\"1.0\"?>"
+ "<ROOTNODE>"
+ "<TAG1>"
+ "<TAG2>"
+ "hello"
+ "</TAG2>"
+ "<TAG2 id="foo">"
+ "hello 2"
+ "</TAG2>"
+ "</TAG1>"
+ "</ROOTNODE>";

var objDom = new XMLDoc(xml, xmlError);
//show the text of the first TAG2 node
var domTree = objDom.docNode;
alert(domTree.getElements("TAG1")[0].getElements("TAG2")[0].getText());


The code to get the node text in the example above is rather straightforward, but is large and can be cumbersome. XML for <SCRIPT> tagPath searching makes this much easier. Consider the following code, which is equivalent to the sample code above:

var xml = "<?xml version=\"1.0\"?>"
+ "<ROOTNODE>"
+ "<TAG1>"
+ "<TAG2>"
+ "hello"
+ "</TAG2>"
+ "<TAG2 id="foo">"
+ "hello 2"
+ "</TAG2>"
+ "</TAG1>"
+ "</ROOTNODE>";

var objDom = new XMLDoc(xml, xmlError);
//show the text of the first TAG2 node
alert(objDom.selectNode("/TAG1/TAG2[0]").getText());


tagPath searching allows JavaScript developers to specify which node they wish to select by passing in a well-formed search string. This search string is formatted according to the following rules:

"/" at the start of the string denotes the root node. This root node would be either the current NODE object (when called from another NODE object) or the root node of the DOC object (when called from a DOC object) as shown above.

Nodes may be selected according to the following rules:
  • By Name: /tag1/tag2
  • By Name and zero-based position: /tag1/tag2[0]
  • Globally: /* (i.e. select all nodes in this position)
  • Via attributes: /tag1/tag2[@id="foo"]
  • Any combinations of the above:

Only one search attribute is allowed in any attribute ([@<attribute>=",<value>"]) search. However, multiple attribute searches are allowed for a single node (/node[@<attribute1>=",<value>"][@<attribute2>=",<value>"]).

For more information on XML for <SCRIPT>s tagPath capabilities, you are encouraged to inspect the DOM test suite and the DOM tagPath sample application source code.

You can view an interactive demo of the tagPath capabilities by viewing the DOM tagPath sample application. This sample application is located in the "Sample Code (Parsers)" section of the website.

XMLDoc/XMLNode Object - selectNodeText method

objDOM.selectNodeText(<search string>)
objNODE.selectNodeText(<search string>)

accepts:
<search string>: the tag path search string

returns:
String of the node's text value (if found) or null if not found

The return string of this function is the exact same string that would be returned if the NODE object method getText() was invoked on a NODE returned from a selectNode call.

Node Object - Constructor

var objNode = new XMLNode(<node type>, <doc>,<str>)

accepts:
<nodeType>: indicates the node type of the node
<doc>: contains a reference to the XMLDoc object describing the document
<str>: contains the text for the tag or text entity

returns:
new XMLNode object

It is uncommon for anyone but the parser itself to create new XMLNode objects. When creating new node objects in code for dom manipulation, it is recommended that you use the createXMLNode method of the XMLDoc object. However, it is possible to create your own nodes should the need arise.

The available node types are TEXT, COMMENT, ELEMENT and CDATA. These should be passed as text in upper-case to the constructor.

Example:
var xml;
xml = ""
+ "<?xml version=\"1.0\"?>"
+ "<ROOTNODE>"
+ "<TAG1>"
+ "Hello World"
+ "</TAG1>"
+ "</ROOTNODE>";
//instantiate a new XMLDoc object.
var objDom = new XMLDoc(xml, xmlError)
var objNode = new XMLNode("TEXT", objDom, "<TAG1>value</TAG1>")
Node Object - addAttribute method

objNode.addAttribute(<attribute name>, <attribute value>)

accepts:
<attribute name>: the name of the new attribute
<attribute value>: the value of the new attribute

returns:
N/A

addAttribute will add an attribute to the node object. This addition will also be reflected in the node's XMLDoc object as well.

If the attribute name passed in already exists for the node, the old value will be removed and replaced with the new value.

For example, adding an attribute of name "name" and value "value" to <TAG1> in the following XML will yield:

Before:
<ROOT>
<REFNC>
<TAG1>
value
</TAG1>
</REFNC>
</ROOT>

After:
<ROOT>
<REFNC>
<TAG1 name="value">
value
</TAG1>
</REFNC>
</ROOT>

Example:
var xml = ""
+ "<?xml version=\"1.0\"?>"
+ "<ROOTNODE>"
+ "<TAG1>"
+ "foo"
+ "</TAG1>"
+ "</ROOTNODE>";
var objDom = new XMLDoc(, xmlError);
//first find the node to add the attribute to, in this case, TAG1
var domTree = objDom.docNode;
var referenceNode = domTree.getElements("TAG1")[0];
//now add the attribute
referenceNode.addAttribute("attribute", "attributeValue");

See also: domManipulationTestFive in domTestSuite.js

Node Object - getAttribute method

objNode.getAttribute(<attribute name>)

accepts:
<attribute name>: the name of the new attribute

returns:
attribute value: if name is found
null: if name is not found

getAttribute's <attribute name> parameter is case sensitive.

For example, getting the "id" attribute from <TAG1> in the following XML will yield:

XML:
<ROOT>
<REFNC>
<TAG1 id="value">
hello
</TAG1>
</REFNC>
</ROOT>

Result:
"value"

Example:
var xml = ""
+ "<?xml version=\"1.0\"?>"
+ "<ROOT>"
+ "<TAG1 id="hello" >"
+ "</TAG1>"
+ "</ROOT>";
var objDom = new XMLDoc(, xmlError);
//first find the node to get an attribute from, in this case, TAG1
var domTree = objDom.docNode;
var referenceNode = domTree.getElements("TAG1")[0];
//now get the attribute
var attributeValue = referenceNode.getAttribute("id");

See also: domManipulationTestNine in domTestSuite.js

Node Object - getAttributeNames method

objNode.getAttributeNames()

accepts:
N/A

returns:
Array of attribute Names for the node

getAttributeNames will return an empty array if there are no attributes for the node.

For example, getting the attribute names from <TAG1> in the following XML will yield:

XML:
<ROOT>
<REFNC>
<TAG1 id="value" hxy="2" >
</TAG1>
</REFNC>
</ROOT>

Result:
Array[0] = "id"
Array[1] = "hxy"

Example:
var xml = ""
+ "<?xml version=\"1.0\"?>"
+ "<ROOT>"
+ "<TAG1 id="hello" >"
+ "</TAG1>"
+ "</ROOT>";
var objDom = new XMLDoc(xml, xmlError);
//first find the node to get attributes from, in this case, TAG1
var domTree = objDom.docNode;
var referenceNode = domTree.getElements("TAG1")[0];
//now get the attributes
var attributes = referenceNode.getAttributes();

See also: domManipulationTestEight in domTestSuite.js

Node Object - getElementById method

objNode.getElementById(<element's id attribute value>)

accepts:
<element's id attribute value>: the id attribute value of a node to search for

returns:
XMLNode object: if id is found
null: if id is not found

If there is more than one node in the XML with the same ID, the parser will return the first node found, searching top to bottom beginning at the node calling getElementById.

For example, getting the element of id 4 from in the following XML will yield:

XML:
<ROOT>
<REFNC>
<TAG1 id="4">
value
</TAG1>
</REFNC>
</ROOT>

Result:
The node object representing <TAG1 id="4">value</TAG1>

Example:
var xml = ""
+ "<?xml version=\"1.0\"?>"
+ "<ROOT>"
+ "<REFNC>"
+ "<TAG1 id="4">"
+ "value"
+ "</TAG1>"
+ "</REFNC>"
+ "</ROOT>";
var objDom = new XMLDoc(, xmlError);
//get the root node and then search for the node with id=4
var domTree = objDom.docNode;
var searchNode = domTree.getElementById("4");

See also: getElementByIdTestOne in domTestSuite.js

Node Object - getElements method

objNode.getElements(|tag name|)

accepts:
|tag name|: optional element name to filter on.

returns:
Array of XMLNode objects: if any are found matching the filter criteria

If no tag name filter is passed to the method, getElements will return all of the elements under the node. If a tag name filter is specified, only those tags whos tag name matches that filter will be returned. An empty array will be returned if there are no tags under the node or if no tag names under the node match the tag name filter passed in.

For example, calling getElements("TAG1") from the <REFNC> node in the following XML will yield:

XML:
<ROOT>
<REFNC>
<TAG1>
value
</TAG1>
<TAG2>
value
</TAG2>
</REFNC>
</ROOT>

Result:
Array[0]: node object representing <TAG1>value</TAG1>

Example:
var xml = ""
+ "<?xml version=\"1.0\"?>"
+ "<ROOT>"
+ "<TAG1 id="hello" >"
+ "</TAG1>"
+ "</ROOT>";
var objDom = new XMLDoc(xml, xmlError);
//find the first TAG1 node
var domTree = objDom.docNode;
var firstTag1Node = domTree.getElements("TAG1")[0];
Node Object - getText method

objNode.getText()

accepts:
N/A

returns:
The text value of the node with the escape values converted to their real value for TEXT and COMMENT nodes.

Generally, getText is called on a node at the bottom of the tree to get the text value out of it. Calling getText on a node with node elements under it will return the text value of those nodes as well.

Sometimes putting your XML in HTML can cause extra spaces to be inserted into your text. Since XML for <SCRIPT> tries to retain these spaces, you may want to trim the retults of getText() to your liking.

For example, calling getText() from the <TAG1> node in the following XML will yield:

XML:
<ROOT>
<REFNC>
<TAG1>
value
</TAG1>
<TAG2>
value
</TAG2>
</REFNC>
</ROOT>

Result:
"value"

Example:
var xml = ""
+ "<?xml version=\"1.0\"?>"
+ "<ROOT>"
+ "<TAG1 id=\"hello\" >"
+ "</TAG1>"
+ "</ROOT>";
var objDom = new XMLDoc(xml, xmlError);
//find the first TAG1 node
var domTree = objDom.docNode;
var firstTag1Node = domTree.getElements("TAG1")[0];
alert(firstTag1Node.getText());
Node Object - getParent method

objNode.getParent()

accepts:
N/A

returns:
The parent XMLNode object to the node

For example, calling getParent() from the <TAG1> node in the following XML will yield:

XML:
<ROOT>
<REFNC>
<TAG1>
value
</TAG1>
<TAG2>
value
</TAG2>
</REFNC>
</ROOT>

Result:
The XMLNode object representing
<REFNC>
<TAG1>
value
</TAG1>
<TAG2>
value
</TAG2>
</REFNC>

Example:
var xml = ""
+ "<?xml version=\"1.0\"?>"
+ "<ROOTNODE>"
+ "<TAG1>"
+ "foo"
+ "</TAG1>"
+ "</ROOTNODE>";
var objDom = new XMLDoc(, xmlError);
//first find the node to find the parent of, in this case TAG1
var domTree = objDom.docNode;
var referenceNode = domTree.getElements("TAG1")[0];
var elementParent = referenceNode.getParent();

See also: domManipulationTestEleven in domTestSuite.js

Node Object - getUnderlyingXMLText method

objNode.getUnderlyingXMLText()

accepts:
N/A

returns:
string: The current XML representation of the XMLNode object omitting processing instructions and DTD's. Also, this function turns any <TAG/> tags into <TAG></TAG>

Example:
var xml = ""
+ "<?xml version=\"1.0\"?>"
+ "<FOO>"
+ "<BAR>"
+ "hello"
+ "</BAR>"
+ "</FOO>";
var objDom = new XMLDoc(xml, xmlError);
var domTree = objDom.docNode;
var node = domTree.getElements("FOO")[0];
alert(node.getUnderlyingXMLText());

See also: underlyingXMLFunctionsTestTwo in domTestSuite.js

Node Object - nodeType property

objNode.nodeType

accepts:
N/A

returns:
string: The node type of the node.

Example:
var xml = ""
+ "<?xml version=\"1.0\"?>"
+ "<FOO>"
+ "<BAR>"
+ "hello"
+ "</BAR>"
+ "</FOO>";
var objDom = new XMLDoc(xml, xmlError);
var domTree = objDom.docNode;
var node = domTree.getElements("FOO")[0];
alert(node.nodeType);

See also: nodeTypeTestOne, nodeTypeTestTwo, nodeTypeTestThree and nodeTypeTestFour in domTestSuite.js

Node Object - removeAttribute method

objNode.removeAttribute(<attribute name>)

accepts:
<attribute name>: the name of the attribute to remove

returns:
N/A

removeAttribute will remove an attribute to the node object. This subtraction will also be reflected in the node's XMLDoc object as well.

For example, remove an attribute of name "name" from <TAG1> in the following XML will yield:

Before:
<ROOT>
<REFNC>
<TAG1 name="value">
hello
</TAG1>
</REFNC>
</ROOT>

After:
<ROOT>
<REFNC>
<TAG1>
value
</TAG1>
</REFNC>
</ROOT>

Example:
var xml = ""
+ "<?xml version=\"1.0\"?>"
+ "<ROOTNODE>"
+ "<TAG1 id=\"3\">"
+ "foo"
+ "</TAG1>"
+ "</ROOTNODE>";
var objDom = new XMLDoc(, xmlError);
//first find a node to remove an attribute from, in this case, TAG1
var domTree = objDom.docNode;
var referenceNode = domTree.getElements("TAG1")[0];
//now remove the attribute
referenceNode.removeAttribute("id");

See also: domManipulationTestSeven in domTestSuite.js

Node Object - tagName property

objNode.tagName

accepts:
N/A

returns:
N/A

The tagName property returns the tag name (without any attributes) of the node.

For example, calling tagName from the <TAG1> node in the following XML will yield:

XML:
<ROOT>
<REFNC>
<TAG1 name="value">
hello
</TAG1>
</REFNC>
</ROOT>

Result:
"TAG1"

Example:
var xml = ""
+ "<?xml version=\"1.0\"?>"
+ "<ROOTNODE>"
+ "<TAG1 id=\"3\">"
+ "foo"
+ "</TAG1>"
+ "</ROOTNODE>";
var objDom = new XMLDoc(xml, xmlError);
//first find the node for to get a tag name from , in this case, TAG1
var domTree = objDom.docNode;
var referenceNode = domTree.getElements("TAG1")[0];
//now get the tag name
alert(referenceNode.tagName);

See also: domManipulationTestEleven, domManipulationTestTen and getElementByIdTestOne in domTestSuite.js

Node Object - toString method

objNode.toString()

accepts:
N/A

returns:
N/A

The toString method produces a diagnostic string description of a the node.

Example:
var xml = ""
+ "<?xml version=\"1.0\"?>"
+ "<ROOTNODE>"
+ "<TAG1 id=\"3\">"
+ "foo"
+ "</TAG1>"
+ "</ROOTNODE>";
var objDom = new XMLDoc(xml, xmlError);
//first find the node for which we want to call toString, in this case it is TAG1
var domTree = objDom.docNode;
var referenceNode = domTree.getElements("TAG1")[0];
//now get the tag name
alert(referenceNode.toString());
Convenience Functions - convertEscapes function

convertEscapes(<string>)

accepts:
<string>: string with escaped characters (i.e. "&lt;")

returns:
string with unescaped characters (i.e. "<")

Characters such as less-than signs, greater-than signs and ampersands are illegal in XML syntax and must be escaped before being inserted into the DOM. This function is a convience function to take those escaped characters and return them to their original values for processing outside the parser.

XML for <SCRIPT> will automagically convert the content of the XML elements to their non-escaped values when xmlNode.getText() is called for every element except CDATA.

Examples:
&amp; == &
&lt; == <
&gt; == >
Convenience Functions - convertToEscapes function

convertToEscapes(<string>)

accepts:
<string>: string with unescaped characters (i.e. "<")

returns:
string with escaped characters (i.e. "&lt;")

Characters such as less-than signs, greater-than signs and ampersands are illegal in XML syntax. This function is a convience function to escape those characters out to there legal values.

Users of XML for <SCRIPT> should call this function any time they are performing dom manipulation by adding new nodes consisting of user-generated text with the exception of CDATA type nodes. While XML for <SCRIPT> is generally rather loose with what it will allow in text, many other parsers are not and will generate an error if one of these characters is unescaped.

Examples:
< == &lt;
> == &gt;
& == &amp;

Example:
var xml = ""
+ "<?xml version=\"1.0\"?>"
+ "<ROOT>"
+ "<TAG1>"
+ "<TAG3>"
+ "value"
+ "</TAG3>"
+ "</TAG1>"
+ "</ROOT>";
var objDom = new XMLDoc(xml, xmlError);
//first find the node that we want to insert into, in this case it is TAG1
var domTree = objDom.docNode;
var referenceNode = domTree.getElements("TAG1")[0];
//get a value input by the user in an HTML form
var userValue = document.getElementById("inputDescription").value;
//convert to escapes to make sure all XML is valid
userValue = convertToEscapes(userValue);
//create the new node
var newNode = objDom.createXMLNode("<DESC>" + userValue + "</DESC>");
//now add it to the tree
objDom = objDom.insertNodeInto(referenceNode, newNode);

See also: cmdSaveClicked in formFunctions.js

Convenience Functions - trim function

trim(<string>, |trim left true|false |, |trim right |true|false |)

accepts:
<string>: string to be trimmed
|trim left|: (optional) trim the left side of the string
|trim right|: (optional) trim the right side of the string

returns:
string trimmed as desired.

In the trim function, trim left and trim right default to "true" if not passed in.


CONTENTS
How do I get started with the SAX Parser?
What SAX Events and Interfaces are supported?
Is there a pre-built event handler object available?
Do I need to catch every event fired by the SAX Parser?
What's this handleCharacterData function for?
 
SAXDriver Object - Constructor
SAXDriver Object - parse method
SAXDriver Object - setDocumentHandler method
SAXDriver Object - setErrorHandler method
SAXDriver Object - setLexicalHandler method
 
SAXEventHandler Object - Constructor
SAXEventHandler Object - characters event
SAXEventHandler Object - comment event
SAXEventHandler Object - endCDATA event
SAXEventHandler Object - endDocument event
SAXEventHandler Object - endElement event
SAXEventHandler Object - error event
SAXEventHandler Object - fatalError event
SAXEventHandler Object - processingInstruction event
SAXEventHandler Object - setDocumentLocator event
SAXEventHandler Object - startCDATA event
SAXEventHandler Object - startDocument event
SAXEventHandler Object - startElement event
SAXEventHandler Object - warning event
SAXEventHandler Object - _handleCharacterData method
SAXEventHandler Object - _fullCharacterDataReceived
 
trim
How do I get started with the SAX Parser?

It's actually very easy. XML for <SCRIPT> ships with a pre-built SAXEventHandler object that is ready to accept events from the SAXDriver object. Simply copy the code in preMadeSaxEventHandler.js (located in the jsXMLParser directory) into your code (or link to the file) and write code to handle events as you see fit.

For example, if you wanted to show the user an alert box with the name of each element as it was parsed, you would write the following code:

function startParser(xml) {
var parser = new SAXDriver();
var eventHandler = new SAXEventHandler();
parser.setDocumentHandler(eventHandler);
parser.setLexicalHandler(eventHandler);
parser.setErrorHandler(eventHandler);
parser.parse(xml);
}; // end function startParser

The code to show the alert box at the start of each element would reside in the startElement event sink and would look like the following:

SAXEventHandler.prototype.startElement = function(name, atts) {
alert(name);
} // end function startElement
What SAX Events and Interfaces are supported?

The SAX "standard" defines the following interfaces. See below for the support offerred by XML for <SCRIPT>

Implemented Interfaces:
//Document Interface
SAXDocumentHandler.startDocument ()
SAXDocumentHandler.endDocument ()
SAXDocumentHandler.startElement (name, atts)
SAXDocumentHandler.endElement (name)
SAXDocumentHandler.characters (data, start, length)
SAXDocumentHandler.processingInstruction (target, data)
SAXDocumentHandler.setDocumentLocator (locator)

//Lexical Interface
SAXLexicalHandler.startCDATA ()
SAXLexicalHandler.endCDATA ()
SAXLexicalHandler.comment (data, start, length)

//Error Interface
SAXErrorHandler.warning (exception)
SAXErrorHandler.error (exception)
SAXErrorHandler.fatalError (exception)

Unimplemented Interfaces:
SAXDocumentHandler.ignorableWhitespace (data, start, length)
SAXLexicalHandler.startDTD (name, publicId, systemId)
SAXLexicalHandler.endDTD ()
SAXLexicalHandler.startEntity (name)
SAXLexicalHandler.endEntity (name)
Is there a pre-built event handler object available?

Yes! Please see the file preMadeSaxEventHandler.js in the jsXMLParser directory. This pre-built object supports all three event handling interfaces (Document, Lexical and Error) as well as provides built in methods for correctly handling character data.

Please keep in mind that you don't *have* to use this pre-built object if you don't want to. You may certainly roll your own if it suits you needs better.

Do I need to catch every event fired by the SAX Parser?

No. XML for <SCRIPT>'s SAX Driver object is capable of detecting whether or not an event handler exists for the event it wants to fire. If no event handler exists, the event will not fire and the parsing will continue.

What's this handleCharacterData function for?

During the parsing of an XML document, it is possible that the characters event may fire multiple times for a single element. If you place your characters event handling code in this event, you may not get all of the character data you expect.

To compensate for this behavior, XML for <SCRIPT>'s pre-built event handler includes a function called _handleCharacterData. This function is designed to capture all of the character data reported to the event handler and report it to the user all at once in the _fullCharacterDataReceived function. This reporting is done only when the function is sure there is no more character data expected for that element.

For more information on the _handleCharacterData function, click here

For more information on the _fullCharacterDataReceived function, click here

SAXDriver Object - Constructor

var saxParser = new SAXDriver();

Accepts:
N/A

Returns:
new SAXDriver object

Example:
function parseXML(xml) {
//instantiate the SAX Driver object
var saxParser = new SAXDriver();

//instantiate the pre-built event handler object
var eventHandler = new SAXEventHandler();

//tell the SAX driver object where to send events
saxParser.setDocumentHandler(eventHandler);
saxParser.setLexicalHandler(eventHandler);
saxParser.setErrorHandler(eventHandler);

//start the parsing process
saxParser.parse(xml);
}
SAXDriver Object - parse method

saxParser.parse(<xml>);

Accepts:
<xml> - String containing the XML to parse

Returns:
N/A

The parse method begins the process of parsing the XML data. The processing will complete before the next line of code is called.

Example:
function parseXML(xml) {
//instantiate the SAX Driver object
var saxParser = new SAXDriver();

//instantiate the pre-built event handler object
var eventHandler = new SAXEventHandler();

//tell the SAX driver object where to send events
saxParser.setDocumentHandler(eventHandler);
saxParser.setLexicalHandler(eventHandler);
saxParser.setErrorHandler(eventHandler);

//start the parsing process
saxParser.parse(xml);
}
SAXDriver Object - setDocumentHandler method

saxParser.setDocumentHandler(<Handler Object>);

Accepts:
<Handler Object> - An object that supports the Document Event Interface

Returns:
N/A

setDocumentHandler tells the SAX parser what code to call for the following events:

startDocument ()
endDocument ()
startElement (name, atts)
endElement (name)
characters (data, start, length)
processingInstruction (target, data)
setDocumentLocator (locator)

Your handler object does not need to support all of these events. Events that do not interest you can be left out with no ill-effect. However, for the events that you do wish to trap, your handler object must implement the above functions exactly as shown.

For your convenience, XML for <SCRIPT> provides a pre-built event handler in the file preMadeSaxEventHandler.js under the jsXMLParser directory. This handler implements all three SAX interfacs for you so you do not have to code them yourself.

Example:
function parseXML(xml) {
//instantiate the SAX Driver object
var saxParser = new SAXDriver();

//instantiate the pre-built event handler object
var eventHandler = new SAXEventHandler();

//tell the SAX driver object where to send events
saxParser.setDocumentHandler(eventHandler);
saxParser.setLexicalHandler(eventHandler);
saxParser.setErrorHandler(eventHandler);

//start the parsing process
saxParser.parse(xml);
}
SAXDriver Object - setErrorHandler method

saxParser.setErrorHandler(<Handler Object>);

Accepts:
<Handler Object> - An object that supports the Error Event Interface

Returns:
N/A

setErrorHandler tells the SAX parser what code to call for the following events:

SAXErrorHandler.warning (exception)
SAXErrorHandler.error (exception)
SAXErrorHandler.fatalError (exception)

Your handler object does not need to support all of these events. Events that do not interest you can be left out with no ill-effect. However, for the events that you do wish to trap, your handler object must implement the above functions exactly as shown.

For your convenience, XML for <SCRIPT> provides a pre-built event handler in the file preMadeSaxEventHandler.js under the jsXMLParser directory. This handler implements all three SAX interfacs for you so you do not have to code them yourself.

Example:
function parseXML(xml) {
//instantiate the SAX Driver object
var saxParser = new SAXDriver();

//instantiate the pre-built event handler object
var eventHandler = new SAXEventHandler();

//tell the SAX driver object where to send events
saxParser.setDocumentHandler(eventHandler);
saxParser.setLexicalHandler(eventHandler);
saxParser.setErrorHandler(eventHandler);

//start the parsing process
saxParser.parse(xml);
}
SAXDriver Object - setLexicalHandler method

saxParser.setLexicalHandler(<Handler Object>);

Accepts:
<Handler Object> - An object that supports the Lexical Event Interface

Returns:
N/A

setLexicalHandler tells the SAX parser what code to call for the following events:

SAXLexicalHandler.startCDATA ()
SAXLexicalHandler.endCDATA ()
SAXLexicalHandler.comment (data, start, length)

Your handler object does not need to support all of these events. Events that do not interest you can be left out with no ill-effect. However, for the events that you do wish to trap, your handler object must implement the above functions exactly as shown.

For your convenience, XML for <SCRIPT> provides a pre-built event handler in the file preMadeSaxEventHandler.js under the jsXMLParser directory. This handler implements all three SAX interfacs for you so you do not have to code them yourself.

Example:
function parseXML(xml) {
//instantiate the SAX Driver object
var saxParser = new SAXDriver();

//instantiate the pre-built event handler object
var eventHandler = new SAXEventHandler();

//tell the SAX driver object where to send events
saxParser.setDocumentHandler(eventHandler);
saxParser.setLexicalHandler(eventHandler);
saxParser.setErrorHandler(eventHandler);

//start the parsing process
saxParser.parse(xml);
}
SAXEventHandler Object - Constructor

var eventHandler = new SAXEventHandler();

Accepts:
N/A

Returns:
New SAXEvent handler object

The SAXEventHandler object is XML for <SCRIPT>'s pre-built event handler. It exists for your convenience. If you choose to roll your own event handler, you may ignore the information contained in the constructor section of the documentation. If you do roll your own event handler, it will need to have the same function signatures as the pre-built event handler for the events you will be trapping.

Example:
function parseXML(xml) {
//instantiate the SAX Driver object
var saxParser = new SAXDriver();

//instantiate the pre-built event handler object
var eventHandler = new SAXEventHandler();

//tell the SAX driver object where to send events
saxParser.setDocumentHandler(eventHandler);
saxParser.setLexicalHandler(eventHandler);
saxParser.setErrorHandler(eventHandler);

//start the parsing process
saxParser.parse(xml);
}
SAXEventHandler Object - characters event

characters(data, start, length)

Provides:
data - the raw xml data provided to the parser
start - position to start getting characters
length - number of characters to get

During the parsing of an XML document, it is possible that the characters event may fire multiple times for a single element. If you place your characters event handling code in this event, you may not get all of the character data you expect.

To compensate for this behavior, XML for <SCRIPT>'s pre-built event handler includes a function called _handleCharacterData. This function is designed to capture all of the character data reported to the event handler and report it to the user all at once in the _fullCharacterDataReceived function. This reporting is done only when the function is sure there is no more character data expected for that element.

The characters event traps the character data being reported by the parser, and appends the new data to an internal variable that keeps track of all the previous character data that had been reported for the current element.

For more information on the _handleCharacterData function, click here

For more information on the _fullCharacterDataReceived function, click here

Example:
characters (data, start, length) {
this.characterData += data.substr(start, length);
}
SAXEventHandler Object - comment event

comment(data, start, length)

Provides:
data - the raw xml data provided to the parser
start - position to start getting characters
length - number of characters to get

The comment event is fired whenever comment data is found in the XML stream. For example, the following XML will yield the events listed below if XML for <SCRIPT>'s pre-built event handler is used.

NOTE: Only the event name is reported here. For a full description of the events fired with this XML, please see testsComment1() in saxTestSuite.js

NOTE: If the "characters" event is listed below, it is assumed to come from the function _fullCharacterDataReceived.

XML:
<?xml version="1.0"?>
<root>
<!--Comment Text-->
</root>

Events:
setDocumentLocator
startDocument
processingInstruction
startElement
comment
endElement
endDocument

Example:
comments (data, start, length) {
var commentData = data.substr(start, length);
}
SAXEventHandler Object - endCDATA event

endCDATA()

Provides:
N/A

The endCDATA event is fired whenever the end of a CDATA section is found in the XML stream. For example, the following XML will yield the events listed below if XML for <SCRIPT>'s pre-built event handler is used.

NOTE: Only the event name is reported here. For a full description of the events fired with this XML, please see testsCDATA1() in saxTestSuite.js.

NOTE: If the "characters" event is listed below, it is assumed to come from the function _fullCharacterDataReceived.

XML:
<?xml version="1.0"?>
<root>
<![CDATA[CDATA Text]]>
</root>

Events:
setDocumentLocator
startDocument
processingInstruction
startElement
startCDATA
characters
endCDATA
endElement
endDocument

Example:
endCDATA() {
//make note that we have reached end of CDATA tag
}
SAXEventHandler Object - endDocument event

endDocument()

Provides:
N/A

The endDocument event is fired whenever the end of the document is found in the XML stream. For example, the following XML will yield the events listed below if XML for <SCRIPT>'s pre-built event handler is used.

NOTE: Only the event name is reported here. For a full description of the events fired with this XML, please see testsElement1() in saxTestSuite.js

NOTE: If the "characters" event is listed below, it is assumed to come from the function _fullCharacterDataReceived.

XML:
<?xml version="1.0"?>
<root>
</root>

Events:
setDocumentLocator
startDocument
processingInstruction
startElement
endElement
endDocument

Example:
endDocument() {
//make note that we have reached end of the document
}
SAXEventHandler Object - endElement event

endElement(<Element Name>)

Provides:
<Element Name> - the name of the element that is ending

The endElement event is fired whenever the end of an element is found in the XML stream. For example, the following XML will yield the events listed below if XML for <SCRIPT>'s pre-built event handler is used.

NOTE: Only the event name is reported here. For a full description of the events fired with this XML, please see testsElement1() in saxTestSuite.js

NOTE: If the "characters" event is listed below, it is assumed to come from the function _fullCharacterDataReceived.

XML:
<?xml version="1.0"?>
<root>
</root>

Events:
setDocumentLocator
startDocument
processingInstruction
startElement
endElement
endDocument

Example:
endElement(name) {
alert("I have reached the end of the element " + name);
}
SAXEventHandler Object - error event

error(<Exception object>)

Provides:
<Exception object> - Object containing information about the exception

The exception object has these methods:

exception.getMessage() - returns an error string
exception.getLineNumber() - returns the line number of the error
exception.getColumnNumber() - returns the column number of the error

At this time, XML for <SCRIPT>'s SAX parser does not throw this event. All error reporting is provided via the fatalError event. For more information on that event, please click here In the future, this event may be utilized so it is highly recommended that you place error trapping code in your handler for this event.

Example:
error(exception) {
//tell the user there is a problem
alert(exception.getMessage());
}
SAXEventHandler Object - fatalError event

fatalError(<Exception object>)

Provides:
<Exception object> - Object containing information about the exception

The exception object has these methods:

exception.getMessage() - returns an error string
exception.getLineNumber() - returns the line number of the error
exception.getColumnNumber() - returns the column number of the error

The fatalError event is fired whenever an error is found in the XML stream. For example, the following XML will yield the events listed below if XML for <SCRIPT>'s pre-built event handler is used.

NOTE: Only the event name is reported here. For a full description of the events fired with this XML, please see testsElementError1() in saxTestSuite.js

NOTE: If the "characters" event is listed below, it is assumed to come from the function _fullCharacterDataReceived.

XML:
<?xml version="1.0"?>
<root

Events:
setDocumentLocator
startDocument
processingInstruction
fatalError

Example:
fatalError(exception) {
//tell the user there is a problem
alert(exception.getMessage());
}
SAXEventHandler Object - processingInstruction event

processingInstructiont(<Target>, <Data>)

Provides:
<Target> - the target of the processing instruction
<Data> - the data of the processing instruction

The processingInstruction event is fired whenever a processing instruction is found in the XML stream. For example, the following XML will yield the events listed below if XML for <SCRIPT>'s pre-built event handler is used.

NOTE: Only the event name is reported here. For a full description of the events fired with this XML, please see testsPI1() in saxTestSuite.js

NOTE: If the "characters" event is listed below, it is assumed to come from the function _fullCharacterDataReceived.

XML:
<?xml version="1.0"?>
<root>
</root>

Events:
setDocumentLocator
startDocument
processingInstruction
startElement
endElement
endDocument

In the above example, the Target variable passed in would be set to xml while the data variable would be set to version="1.0"

Example:
processingInstructiont(target, data) {
alert("Processing instruction target:" + target);
alert("Processing instruction data:" + data);
}
SAXEventHandler Object - setDocumentLocator event

setDocumentLocator(<Parser Object>)

Provides:
<Parser Object> - A handle to the low level XML Parser

The setDocumentLocator event is always the first event fired when parsing an XML stream. The object provided is a handle to the actuall object behind the scenes responsible for the parsing of the XML. In most cases, you will not need to do anything with this object and this event can safely be ignored. However, if you do need raw access to the underlying parser, it is provided to you here. If you do need to add functionality to this underlying parser, the object that is being returned is defined in xmlsax.js as XMLP.

For example, the following XML will yield the events listed below if XML for <SCRIPT>'s pre-built event handler is used.

NOTE: Only the event name is reported here. For a full description of the events fired with this XML, please see testsElement1() in saxTestSuite.js

NOTE: If the "characters" event is listed below, it is assumed to come from the function _fullCharacterDataReceived.

XML:
<?xml version="1.0"?>
<root>
</root>

Events:
setDocumentLocator
startDocument
processingInstruction
startElement
endElement
endDocument

Example:
setDocumentLocator(ParserObject) {
//ignore this event
}
SAXEventHandler Object - startCDATA event

startCDATA()

Provides:
N/A

The startCDATA event is fired whenever the start of a CDATA section is found in the XML stream. For example, the following XML will yield the events listed below if XML for <SCRIPT>'s pre-built event handler is used.

NOTE: Only the event name is reported here. For a full description of the events fired with this XML, please see testsCDATA1() in saxTestSuite.js.

NOTE: If the "characters" event is listed below, it is assumed to come from the function _fullCharacterDataReceived.

XML:
<?xml version="1.0"?>
<root>
<![CDATA[CDATA Text]]>
</root>

Events:
setDocumentLocator
startDocument
processingInstruction
startElement
startCDATA
characters
endCDATA
endElement
endDocument

Example:
startCDATA() {
//make note that we have found the start of a CDATA tag
}
SAXEventHandler Object - startDocument event

startDocument()

Provides:
N/A

The startDocument event is fired when the start of a the document is found in the XML stream. For example, the following XML will yield the events listed below if XML for <SCRIPT>'s pre-built event handler is used.

NOTE: Only the event name is reported here. For a full description of the events fired with this XML, please see testsElement1() in saxTestSuite.js

NOTE: If the "characters" event is listed below, it is assumed to come from the function _fullCharacterDataReceived.

XML:
<?xml version="1.0"?>
<root>
</root>

Events:
setDocumentLocator
startDocument
processingInstruction
startElement
endElement
endDocument

Example:

Example:
startDocument() {
//make note that we have found the start of the document
}
SAXEventHandler Object - startElement event

startElement(<Name>, <Attributes Object>)

Provides:
<Name> - The name of the element that is starting
<Attribute Object> - An object representing the element's attributes

The Attributes Object (atts) has these methods:

atts.getName(<ordinal>) - gets the name of the attribute specified
atts.getValue(<ordinal>) - gets the value of the attribute specified
atts.getLength() -- gets the number of attributes for the element
atts.getValueByName(<name>) -- gets the value for the attribute specified

The value expected for the methods getName and getValue is a zero based ordinal based on the position of the attribute you're looking for in the attribute list.

The startElement event is fired when the start of an element is found in the XML stream. For example, the following XML will yield the events listed below if XML for <SCRIPT>'s pre-built event handler is used.

NOTE: Only the event name is reported here. For a full description of the events fired with this XML, please see testsElement1() in saxTestSuite.js

NOTE: If the "characters" event is listed below, it is assumed to come from the function _fullCharacterDataReceived.

XML:
<?xml version="1.0"?>
<root>
<tag att1="val1" att2="val2">
</tag>
</root>

Events:
setDocumentLocator
startDocument
processingInstruction
startElement
endElement
endDocument

Example:
startElement(name, atts) {
//get element name
var elm = "Element Name: " + name + "\n");

//now loop through attributes
var intCount = atts.getLength();
if (intCount > 0) {
elm += "Has element data of:\n";
}
for (intLoop=0;intLoop<intCount;intLoop++) {
elm += atts.getName(intLoop) + ": ";
elm += atts.getValue(intLoop) + "\n"
}

//display element info
alert(elm);
}
SAXEventHandler Object - warning event

warning(<Exception object>)

Provides:
<Exception object> - Object containing information about the exception

The exception object has these methods:

exception.getMessage() - returns an error string
exception.getLineNumber() - returns the line number of the error
exception.getColumnNumber() - returns the column number of the error

At this time, XML for <SCRIPT>'s SAX parser does not throw this event. All error reporting is provided via the fatalError event. For more information on that event, please click here In the future, this event may be utilized so it is highly recommended that you place error trapping code in your handler for this event.

Example:
warning(exception) {
//tell the user there is a problem
alert(exception.getMessage());
}
SAXEventHandler Object - _handleCharacterData method

_handleCharacterData()

Provides:
N/A

During the parsing of an XML document, it is possible that the characters event may fire multiple times for a single element. If you place your characters event handling code in this event, you may not get all of the character data you expect.

To compensate for this behavior, XML for <SCRIPT>'s pre-built event handler includes a function called _handleCharacterData. Since the characters event can be fired multiple times for an element, the only way to be sure you have received all of the characters for an element is to wait until an event other than characters is fired while at the same time storing all of the data reported by the multiple characters events. Once this non-character event is fired, then you can be assured you have the complete character data for the element.

_handleCharacterData is the internal function that serves the purpose of checking for non-characters events. It is called at the beginning every event which can signify that all of the characters data has been received. When _handleCharacterEvents is called, it checks the internal variable that holds the collection of characters data. If that varable is non-blank, then the function calls the interal event _fullCharacterDataReceived and resets the internal variable. _fullCharacterDataReceived is where you should put your character handling code.

Generally, it will not be necessary for you to modify this function.

For more information on the _fullCharacterDataReceived function, click here

SAXEventHandler Object - _fullCharacterDataReceived

_fullCharacterDataReceived(fullCharacterData)

Provides:
fullCharacterData - all of the character data for the element

During the parsing of an XML document, it is possible that the characters event may fire multiple times for a single element. If you place your characters event handling code in this event, you may not get all of the character data you expect.

XML for <SCRIPT>'s pre-built event handler compensates for this behavior for you. Once it is sure that all of the character data has been received for an element, it fires _fullCharacterDataReceived. This event is where you should put your characters event handling code.

Example:
_fullCharacterDataReceived(fullCharacterData) {
//show the user all of the character data
alert("characters for this element: " + fullCharacterData);
}
Convenience Functions - trim function

trim(<string>, |trim left true|false |, |trim right |true|false |)

accepts:
<string>: string to be trimmed
|trim left|: (optional) trim the left side of the string
|trim right|: (optional) trim the right side of the string

returns:
string trimmed as desired.

In the trim function, trim left and trim right default to "true" if not passed in.


CONTENTS
What tools are available in XML for <SCRIPT>?
 
How can I load XML data from outside my own domain?
Can I use this same API to load XML data from my own domain?
How does this API work?
What browsers does this API work with?
How do I use this API from JavaScript?
xmlIOProxyLoadData
xmlIOProxyGetLastLoadStatus
What do I have to do on the server side to use this API?
What server-side proxies come pre-built with XML for <SCRIPT>?
How do I configure the proxies?
Building your own server-side proxies
Licensing for custom server-side proxies
Java Proxy Reference Distribution
 
How can I save XML to the client's hard drive?
What browsers does this API work with?
xmlIODeleteData
xmlIOGetData
xmlIOSaveData
xmlIOListSavedDataNames
 
How can I make my escaped XML easy to read and smaller?
What browsers does this API work with?
xmlEscapeXMLToHTML
xmlUnescapeHTMLToXML
What tools are available in XML for <SCRIPT>?

XML for <SCRIPT> includes a number of tools that make development easier. These tools make it both possible and easy to extract, save and manipulate XML from a variety of data sources.

These tools have been catategorized into the following JavaScript files, which can be found in the jsTools directory.

xmlIO.js

  • Load XML from any web server
  • Load XML from client's stored cookies
  • Save XML to client via cookies
  • Retrieve list of saved XML data streams
  • Delete a saved XML data stream

xmlEscape.js

  • Escape XML into valid and readable HTML
  • Unescape escaped XML back to true XML
How can I load XML data from outside my own domain?

In many cases, it is useful to load XML from another file on your web server or from another web server entirely and manipulate it with XML for <SCRIPT>. With JavaScript, the former is possible with a little effort. However, the latter is impossible due to the JavaScript security sandbox your code must live in. This makes it impossible, for example, to load and manipulate an external RSS news stream directly from JavaScript.

XML for <SCRIPT> attempts to make both loading files from your server and from external servers both possible and simple. It does this by abstracting the many different methods for browser-server communications in a simple-to-use API. To allow for XML to be loaded from external domains, XML for <SCRIPT> provides a number of server-side proxies that load the external XML on behalf of the JavaScript and returns it to the browser in such a manner that reading and manipulation is possible.

Can I use this same API to load XML data from my own domain?

Absolutely! Simply add the file you want to your proxie's list of available data sources and access it just as you would any other data source in the list.

How does this API work?

The JavaScript security sandbox is very strict. If the data on a page or frame did not originate from the same domain as the script, programmatic access to that data is denied. This domain restriction presents severe limitations to developers trying to load XML data streams such as RSS data feeds and legitimately integrating them into their site.

This API works by "fooling" JavaScript into thinking the data being loaded originated from the same domain as the script. To accomplish this task, XML for <SCRIPT> uses two pieces of software: a client-side JavaScript API and a server-side proxy. Rather than JavaScript accessing the external data directly (resulting in innaccessible data), the JavaScript instructs the proxy server to fetch the data and return it on its behalf.

Since the proxy server resides inside your web server, you control what domains it can access. Assuming you've allowed access to the external data being requested, the proxy server fetches the data and returns it to the client in a package the JavaScript API understands.

The "magic" behind the process is this: Even though the data being returned to the JavaScript originated from outside it's domain, what actually returns the data to the JavaScript (the proxy) resides inside it's domain. As a result, full and unrestricted access to the returned data is granted.

To help clarify this process, the steps performed to load external data are generalized in the following graphical example.

Graphical description of the proxy process

1. JavaScript client calls proxy server and asks for external data
2. Proxy server connects to external data source and fetches the data
3. Proxy server packages the data and returns it to the JavaScript
4. JavaScript reads and manipulates data with unrestriced access
What browsers does this API work with?

Please be aware of some browser compatibility issues using this API. This API is compatible with Netscape 6.x and above, Mozilla, Internet Explorer 5.2 (Mac OS X), Internet Explorer 5.5 (Windows), Opera 7 and Konqueror versions 3.01 and above.

The following browsers are known *not* to work with this API:

  • Internet Explorer 5.0
  • Konqueror 2.x
  • Opera 6.x

The following functions are affected by this limitation:

  • xmlIOProxyLoadData
  • xmlIOProxyGetLastLoadStatus
How do I use this API from JavaScript?

It's actually rather easy. There are only two functions to be familiar with:

  • xmlIOProxyLoadData
  • xmlIOProxyGetLastLoadStatus

These functions are described in detail below.

NOTE: When using the function xmlIOProxyLoadData, you must include xmlEscape.js from the jsTools directory into your source HTML file.

xmlIOProxyLoadData
xmlIOProxyLoadData(
<proxyURL>,
<resourceID>,
<callBackFunction>,
<authenticationCode>)

accepts:
<proxyURL>: The URL of the proxy server
<resourceID>: The ID of the resource to retrieve
<callbackFunction>: The function to call when the data is finished loading
<authenticationCode>: Authentication code to the proxy server

returns:
A GUID representing the "thread" that is performing the load operation

xmlIOProxyLoadData is the primary function to call when retrieving data from one of XML for <SCRIPT>'s proxy servers. Each accepted parameter is detailed below.


proxyURL

The URL to the proxy server. The proxy server you are communicating with must reside on the same domain and port that the calling JavaScript originated from.

resourceID

For security purposes, the proxy servers contain the master list of available data that can be retrieved. This list is zero based and can contain as many items as you would like. The resourceID specifies which resource in this list (beginning with zero) that the proxy is to retrieve.

callbackFunction

The callback function is a function defined by the JavaScript programmer using xmlIOProxyLoadData. When functioning properly, this function will be called once the data from the proxy is fully loaded into the client's browser.

The callback function can be named anything the JavaScript programmer would like to call it, but it must have a method signature exactly as specified below:

<callbackFunction>(<String1>, <String2>, <String3>)

The first string will either be the XML Data returned by the proxy or an error string. It will be XML if the third parameter of the callback function is "success". It will be an error string of the third parameter of the callback function is "error".

The second string will be the GUID for this data request. This GUID can be compared to the GUID returned by xmlIOProxyLoadData to determine exactly which data request is being returned.

The third string is a success/fail code from the proxy server. It will either be "success" or "error".

NOTE: If the callback function is never called, more information about why may be available by calling the xmlIOProxyGetLastLoadStatus method described in the next section.


authenticationCode

For security purposes, the proxy server will not allow access to any of it's resources unless the proper authentication code is passed in.

NOTE: In order to protect this authentication code, It is highly recommended that you use a https (secure) connection when calling xmlIOProxyLoadData. When using a standard http connection, this authentication code is passed in plain text to the proxy.

NOTE: If you do use an https (secure) connection, keep in mind that the calling JavaScript will also have to originate from that same https connection.

Behind the scenes, xmlIOProxyLoadData creates a new IFRAME DOM element inside the browser. Since each new IFRAME DOM element is treated as a new thread inside the browsers, the call to xmlIOProxyLoadData will return control back to the calling JavaScript almost immediately.

xmlIOProxyLoadData has been designed to take advantage of this behavior and allow the JavaScript programmer to load multiple external data streams from the proxy server at the same time. If the JavaScript programmer wishes to take advantage of this capability, care must be taken to ensure that the correct JavaScript code for each data stream is called when the data is fully loaded into the client. To accomplish this, the JavaScript programmer has two options. These options are outlined below.

Option 1: Separate callback functions

If a limited number of external data streams are being loaded, the simplest manner to ensure the proper JavaScript code is called upon their return is to specify a different callback function for each call to xmlIOProxyLoadData.

Option 2: One callback function

If the code to handle all of the returned data streams is similar or the JavaScript programmer wishes to keep all of the handling code in one function, the GUID returned by xmlIOProxyLoadData can be used to identify the data stream being returned.

Each call to xmlIOProxyLoadData will return a unique GUID. This GUID is passed to the proxy server and then returned to the client in callback function. If the GUIDs returned by xmlIOProxyLoadData are saved in a global list, the data being returned to the callback function can be easily identified by comparing the GUID returned in the callback function with the GUIDs stored in the global list.

NOTE: JavaScript does *not* serialize the callback function. If two external data streams are returned at virtually the same time, it is possible that the callback function will not function as expected. Use care when choosing this option.


Example:
<script type="text/javascript">
var gGUID;
var callbackCalled = false;
function getExternalData(){
//get external data
var pURL = "https://www.myproxyurl.com/proxy";
var resID = "2";
var cbFunction = "myCallbackFunc";
var authCode = "myVeryStrongAuthenticationCode";

//make the call to the proxy server
gGUID = xmlIOProxyLoadData(pUrl, resID, cbFunction, authCode);

//If something goes really wrong, let the user know
window.setTimeout("getError()", 5000);
}

function myCallbackFunc(data, GUID, returnCode){
//ensure the GUID returned is the one we expect;
if (gGUID != GUID) {
alert("incorrect GUID!");
return;
}

//make sure we have valid XML
if (returnCode == "error"){
alert("PROXY ERROR: The error was:\n" + data);
return;
}

//we have valid data. Show it to the user
alert("The XML returned was:\n" + data);
}

function getError(){
alert(xmlIOProxyGetLastLoadStatus());
}

</script>
toolsxmlIOProxyGetLastLoadStatus

toolsxmlIOProxyGetLastLoadStatus()

accepts:
N/A

returns:
String with the last result of the xmlIOProxyLoadData function

If for some reason the JavaScript programmer's callback function never gets called after an invocation of xmlIOProxyLoadData, more information about why may be available by calling the xmlIOProxyGetLastLoadStatus method.

After a successful call to the callback function, the xmlIOProxyGetLastLoadStatus will always return the string "xmlIOProxyLoadData-Called callbackFunction".

The most common reason for the callback function not being called is a misspelled callback function name in the call to xmlIOProxyLoadData function. In this case, JavaScript cannot call the callback function. In cases such as these, the error message detailing what went wrong will be returned by calling xmlIOProxyGetLastLoadStatus.



Example:
<script type="text/javascript">
var gGUID;
var callbackCalled = false;
function getExternalData(){
//get external data
var pURL = "https://www.myproxyurl.com/proxy";
var resID = "2";
var cbFunction = "myCallbackFunc";
var authCode = "myVeryStrongAuthenticationCode";

//make the call to the proxy server
gGUID = xmlIOProxyLoadData(pUrl, resID, cbFunction, authCode);

//If something goes really wrong, let the user know
window.setTimeout("getError()", 5000);
}

function myCallbackFunc(data, GUID, returnCode){
//ensure the GUID returned is the one we expect;
if (gGUID != GUID) {
alert("incorrect GUID!");
return;
}

//make sure we have valid XML
if (returnCode == "error"){
alert("PROXY ERROR: The error was:\n" + data);
return;
}

//we have valid data. Show it to the user
alert("The XML returned was:\n" + data);
}

function getError(){
alert(xmlIOProxyGetLastLoadStatus());
}

</script>
What do I have to do on the server side to use this API?

To use this API, a server-side component must be installed on your web server. This server-side component (proxy) is responsible for actually fetching the data the JavaScript is requesting.

A number of pre-built proxies are shipped with XML for <SCRIPT>. See the next section for a complete list. If you use a platform/web server not supported "out of the box" by XML for <SCRIPT>, full documentation on the proxy solution is also provided allowing you to build your own solution.

What server-side proxies come pre-built with XML for <SCRIPT>?

Currently, the following server-side architectures have pre-built proxies available:

  • Java Servlet
  • JSP
  • PHP
  • mod_perl

These proxies may be found under the pre-builtProxyServers directory.

How do I configure the proxies?

Each proxy must have the following parameters configured in order to fetch data on behalf of the JavaScript:

  • A resource list of URLs that can be associated with a zero-based list
  • An authentication code string

Each proxy implementation is different, but the designs are similar for all of them. See the comments in the code for each different proxy for specific configuration instructions.

Building your own server-side proxies

If you are unable to use one of the pre-built server-side proxies, full documentation is provided in the file "proxyDocumentation.txt" that will allow you to build your own.

This file is located in the pre-builtProxyServers directory.

Licensing for custom server-side proxies

If you build your own server-side proxy for use with XML for <SCRIPT>, you are under no obligation to return the source code to the main project. Building your own proxy is simply a matter of implementing a published API, thus your code does not fall under the terms of the LGPL.

That being said, you are highly encouraged to contribute your source code back to the main project. That is, after all, how Free Software works.

Java Proxy Reference Distribution

Since SourceForge.net does not allow outbound connections from its hosting servers, it is impossible to properly demonstrate the interaction of the JavaScript API and the server-side proxies.

To allow for easy demonstrations, a Java Proxy Reference Distribution has been developed that includes a pre-configued version of the Apache Tomcat Java web server. This pre-configured web server contains a version of the Java Servlet reference proxy that is configured to run the xmlIOProxy test suite.

To install and run the Java Proxy Reference Distribution, perform the following steps:

  • Download and extract the Java Proxy Reference Distribution
  • Copy the entire XML for <SCRIPT> distribution into the webapps/jsproxy/xmljs directory
  • Ensure you have JDK 1.3 (or higher) installed on your machine
  • Set the environment variable JAVA_HOME to the root directory of your JDK
  • In the bin directory, run startup.sh or startup.bat, depending on your platform
  • Point your browser to http://localhost:8080/xmljs/website/testSuites.html
  • Go to the xmlIOProxy tab, launch the test suite and follow the directions on the screen
How can I save XML to the clients hard drive?

In many instances, it is nice to be able to save an XML stream onto a client's hard drive. Sadly (or thankfully, depending on your perspective) this is made difficult if not impossible to do by the browsers. Each browser does have methods allowing this type of activity, but these methods are not cross platform and can raise serious security concerns with users.

XML for <SCRIPT> attempts to resolve this situation by providing an interface for saving and retrieving XML streams using cookies. This interface allows programmers to save data for a specified period of time and retrieve that data when needed. It is not a requirement to save XML, any string data is supported by the interface.

What browsers does this API work with?

Please be aware of some browser compatibility issues using this API. This API is compatible with Netscape, Mozilla, Internet Explorer, Opera 7 and Konqueror versions 3.03 and above. Konqueror versions prior to 3.03 and Opera versions prior to 7.0 don't support JavaScript manipulation of cookies at all and do not work with this API.

Safari versions as of April 2003 do not work with this API. A bug report has been filed. The issue is in the code where the cookie is told when to expire. This bug may be fixed by the time Safari ships as a 1.0 product.

The following functions are affected by this limitation:

  • xmlIODeleteData
  • xmlIOGetData
  • xmlIOListSavedDataNames
  • xmlIOSaveData
xmlIODeleteData

xmlIODeleteData(<Stream Name>)

accepts:
<Stream Name>: name of the saved data stream to delete

returns:
N/A

On browsers that support JavaScript manipulation of cookies, xmlIODelete will remove a named data stream from the cookie on the client's machine by setting that cookie's expiration date to a time in the past.

Example:
//delete the XML Stream named savedXML
xmlIODeleteData("savedXML");
xmlIOGetData

xmlIOGetData(<Stream Name>)

accepts:
<Stream Name>: name of the saved data stream to retrieve

returns:
string containing the data stream requested

On browsers that support JavaScript manipulation of cookies, xmlIOGetData will return the saved data from the cookie on the client's machine.

Example:
//get the saved XML named savedXML from the cookie
var myXML = xmlIOGetData("savedXML");
xmlIOSaveData

xmlIOSaveData(<Stream Name>, <Data> [,expiration date])

accepts:
<Stream Name>: name of data stream to save
<Data>: The data to save
[expiration date]: JavaScript date object reflecting the time the saved data will be automatically deleted

returns:
N/A

On browsers that support JavaScript manipulation of cookies, xmlIOSaveData will save the data passed in to the cookie on the client's machine. This data will remain until either the user deletes it manually, the programmer deletes it via xmlIODeleteData, or the expiration date has passed.

If the expiration date parameter is not passed in, xmlIOSaveData will set the cookie to automatically expire on January 1st, 10 years in the future.

Example:
var xml = ""
+ "<?xml version=\"1.0\"?>"
+ "<ROOT>"
+ "<TAG1>"
+ "<TAG3>"
+ "value"
+ "</TAG3>"
+ "</TAG1>"
+ "</ROOT>";
//save the xml to the client's hard drive until Jan 1, 2003
var expDate = new Date("January 1, 2003");
xmlIOSaveData("savedXML", xml, expDate);
xmlIOListSavedDataNames

xmlIOListSavedDataNames()

accepts:
N/A
returns:
An array containing all of the names of the saved data streams.

This function is useful for building dialogs that allow users to choose which data stream that they would like to open. It also can can be used by developers to ensure that a data stream name is not already in use before saving.

How can I make my escaped XML easy to read and smaller?

Escaping XML into valid HTML can be an error prone and expensive process. The escaped HTML is very difficult to read with the human eye and is much larger than the original XML source. For example, if you had some original XML such as the following:

<root>
<node></node>
</root>

your escaped HTML would look like this:

&lt;root&gt;
&lt;node&gt;&lt;/node&gt;
&lt;/root&gt;

This escaped HTML is hard to read and can be much larger than the original XML text.

XML for <SCRIPT> attempts to resolve this situation by converting your XML into valid HTML not by escaping the XML, but by replacing the XML markup tags with high ascii characters which are not likely to be found in your XML data. Consider the same example as before:

<root>
<node></node>
</root>

After running that XML through the XML for <SCRIPT> xmlEscape functions, your XML would look like this:

«root»
«node»«/node»
«/root»

This data is valid HTML and can be placed anywhere in your HTML form safely. It is also much easier to read and no larger than the original XML.

If you need to convert your XML on the server side before sending the XML to the client, XML for <SCRIPT> performs the following conversions in its xmlEscape functions.

< == « == String.fromCharCode(171)
> == » == String.fromCharCode(187)
& == § == String.fromCharCode(167)

What browsers does this API work with?

This API is known to work with all browsers supported by XML for <SCRIPT>.

xmlEscapeXMLToHTML

xmlEscapeXMLToHTML(<XML Data>)

accepts:
<XML Data>: XML Data to be escaped

returns:
String containing a representation of the XML data in valid HTML

xmlEscapeXMLToHTML is a useful function to help you escape out your XML to valid HTML. The valid HTML that is returned is smaller than standard escaped HTML and is still human readable. xmlEscapeXMLToHTML converts the following characters:

< == « == String.fromCharCode(171)
> == » == String.fromCharCode(187)
& == § == String.fromCharCode(167)

For example, calling xmlEscapeXMLToHTML on the following XML:

Before:
<root>
<node></node>
</root>

will yield the following text:

After:
«root»
«node»«/node»
«/root»
xmlUnescapeHTMLToXML

xmlUnescapeHTMLToXML(<HTML Data>)

accepts:
<HTML Data>: Escaped HTML data

returns:
String containing the original XML data before it was escaped

xmlUnescapeHTMLToXML is the companion function to xmlEscapeXMLToHTML. This function will take a string that has been run through xmlEscapeXMLToHTML and return it to its original form.

For example, calling xmlUnescapeHTMLToXML on the following escaped HTML:

Before:
«root»
«node»«/node»
«/root»

will yield the following text:

After:
<root>
<node></node>
</root>