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>
<?xml version="1.0"?>
<ROOTNODE>
<NODE>
value
</NODE>
</ROOTNODE>
</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. "<")
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:
& == &
< == <
> == >
Convenience Functions - convertToEscapes function
convertToEscapes(<string>)
accepts:
<string>: string with unescaped characters (i.e. "<")
returns:
string with escaped characters (i.e. "<")
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:
< == <
> == >
& == &
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.
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:
<root>
<node></node>
</root>
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>