<HTML> | |
<BODY BGCOLOR="#FFFFFF" onload="windowLoad()"> | |
<H2>XML Tree Viewer</H2> | |
<HR> | |
<B>Enter the location of the XML file: </B> | |
<INPUT ID="XMLFile" TYPE="text" SIZE="30" VALUE="sample.xml" | |
onkeydown="loadEnter()"></INPUT> | |
<INPUT ID="loadButton" TYPE="button" onClick="loadXML()" | |
VALUE="Load XML and Display Tree"></INPUT> | |
<HR> | |
<BUTTON onClick="displayTree()">Refresh Tree Display</BUTTON> | |
<BUTTON onClick="showXML()">Show XML</BUTTON> | |
<HR> | |
<B>Using the XML Object Model, navigate to an XML element, attribute, or node list (for | |
example, enter xmldoc.documentElement in the text area to navigate to the root node). The | |
node(s) you navigate to will be highlighted in blue: </B> | |
<INPUT ID="selectionString" TYPE="text" SIZE="40" | |
onkeydown="selectionEnter()" VALUE=""></INPUT> | |
<INPUT ID="selectionButton" TYPE="button" | |
onClick="genericSelect()" VALUE="Display Selection"></INPUT> | |
<BR> | |
<HR> | |
Legend: <FONT COLOR="red">Text</FONT>, <FONT COLOR="green">Attribute</FONT>, <FONT COLOR="purple">Comment</FONT>, <FONT COLOR="blue">Highlighted node(s)</FONT> | |
</BODY> | |
<xml id=xmldoc></xml> | |
<SCRIPT LANGUAGE="JScript"> | |
// ********************************************************************* | |
// * Constants declarations | |
// ********************************************************************* | |
var blue = "#0000FF"; | |
var black = "#000000"; | |
var attributeColor = "green"; | |
var textColor = "red"; | |
var commentColor = "purple"; | |
var attID = "tv:TreeViewerID"; // Name of the attribute add to the | |
// tree to point to the span id. | |
var nsName = "msTreeViewer"; // Name of the namespace that will hold | |
// the attribute that is added. | |
var ELEMENT_NODE = 1; | |
var ATTRIBUTE_NODE = 2; | |
var NAMESPACE_NODE = 7; // 7 is for processing instruction. | |
var TEXT_NODE = 3; | |
var COMMENT_NODE = 8; | |
var CDATA_NODE = 4; | |
var ENTITYREF_NODE = 5; | |
// ********************************************************************* | |
// * Variable declarations | |
// ********************************************************************* | |
var strStruct; // string that holds the html version of the tree. | |
var elementNum; // Counter to keep track of what to call the | |
// span id in the html display version of | |
// the tree. | |
var code; // Array that holds information about whether | |
// to display the | or not. | |
var selectedNodes; // Keeps track of which nodes are highlighted. | |
var selectedNodesType; | |
var selectedNodesLength; // Keeps track of how many nodes are highlighted. | |
var displayFrame; // display frame (displayFrame = parent.display) | |
var treeViewNS = "urn:tv";// The Tree Viewer namespace node. | |
var tempNode; // Used by user in executeString. | |
// ********************************************************************* | |
// * Helper functions | |
// ********************************************************************* | |
// Reset on reload. | |
function windowLoad() | |
{ | |
displayFrame = parent.display; | |
displayFrame.document.open(); | |
displayFrame.document.write(""); | |
displayFrame.document.close(); | |
selectionString.value = ""; | |
XMLFile.focus(); | |
} | |
// Automatically click button when user presses enter. | |
function loadEnter() | |
{ | |
if (event.keyCode == 13) // 13 is keyCode for enter. | |
{ | |
loadButton.click(); | |
selectionString.focus(); | |
} | |
} | |
// Automatically click button when user presses enter. | |
function selectionEnter() | |
{ | |
if (event.keyCode == 13) | |
selectionButton.click(); | |
} | |
// *********************************************************************** | |
// * Selection highlighting functions | |
// *********************************************************************** | |
// Called by the 'Display Selection' button. | |
// Unhighlights the previously highlighted nodes. | |
// Decides if the entry points to an attribute node, element node or node list and calls | |
// the appropriate handler. | |
function genericSelect() | |
{ | |
if (xmldoc == null) | |
{ | |
alert("No xml file has been loaded."); | |
selectionString.value = ""; | |
} | |
else | |
{ | |
// Only choices are nodeList, node or attributes. | |
// This try...catch block needs JScript version 5 which comes with IE5. | |
try | |
{ | |
selection = eval(selectionString.value); | |
} | |
catch(e) | |
{ | |
selection = null; | |
} | |
if (selection == null) | |
alert("Only element nodes, attribute nodes and node lists can be specified."); | |
else | |
{ | |
// Unselect previously selected nodes. | |
if (selectedNodesLength != 0) | |
{ | |
for (var i = 0; i < selectedNodesLength; i++) | |
{ | |
if (selectedNodesType[i] == "attribute") | |
parent.display.document.all.item(selectedNodes[i]).style.color = attributeColor; | |
else | |
parent.display.document.all.item(selectedNodes[i]).style.color = black; | |
} | |
} | |
selectedNodesLength = 0; | |
// Call appropriate handler. | |
if (selection.length != null) // Note this is also true for | |
//strings and other non nodeLists. | |
selectNodeList(selection); | |
else if (selection.nodeTypeString == "element") | |
selectNode(selection); | |
else if (selection.nodeTypeString == "attribute") | |
selectAtt(selection); | |
else | |
alert("Only element nodes, attribute nodes and node lists can be specified."); | |
} | |
} | |
} | |
// Highlight an attribute node. | |
// | |
// Since attributes can't have attributes, they are counted off | |
// from the parent element. | |
function selectAtt(att) | |
{ | |
var elem = att.selectSingleNode("ancestor(.)"); | |
attNum = elem.attributes.length; | |
// Find the offset for the attribute. | |
for (var i = 0; i < attNum; i++) | |
if (elem.attributes.item(i).nodeName == att.nodeName) | |
break; | |
if (elem.attributes.getNamedItem(attID) != null) { | |
var nodeID = elem.attributes.getNamedItem(attID).nodeValue + "_att_" + i; | |
selectedNodes[selectedNodesLength] = nodeID; | |
selectedNodesType[selectedNodesLength] = "attribute"; | |
selectedNodesLength++; | |
parent.frames("display").document.all(nodeID).style.color = blue; | |
} | |
} | |
// Highlight an element node. | |
function selectNode(node) | |
{ | |
var nodeID; | |
if (node.attributes.getNamedItem(attID) != null) { | |
nodeID = node.attributes.getNamedItem(attID).nodeValue; | |
selectedNodes[selectedNodesLength] = nodeID; | |
selectedNodesType[selectedNodesLength] = "element"; | |
selectedNodesLength++; | |
parent.display.document.all(nodeID).style.color = blue; | |
} | |
} | |
// Highlight a node list. | |
function selectNodeList(list) | |
{ | |
selectedNodesLength = list.length; | |
for (var i = 0; i < list.length; i++) | |
{ | |
// Only highlight elems and attrs (other stuff isn't in tree) | |
if (list(i).nodeTypeString == "element") | |
selectNode(list(i)); | |
else if (list(i).nodeTypeString == "attribute") | |
selectAtt(list(i)); | |
} | |
} | |
// ******************************************************************** | |
// * Tree loading and displaying functions | |
// ******************************************************************** | |
// Create the msxml object and load the specified xml file. | |
function loadXML() | |
{ | |
if (XMLFile.value == "") | |
{ | |
alert("An xml file must be specified for loading to occur."); | |
} | |
else | |
{ | |
xmldoc.async = false; | |
xmldoc.load(XMLFile.value); | |
if (xmldoc.parseError.errorCode != 0) | |
{ | |
alert(errtxt); | |
windowLoad(); | |
} | |
if (xmldoc.documentElement != null) | |
{ | |
// Create the TreeViewer namespace here. | |
//treeViewNS = xmldoc.createNode("attribute","xmlns:treeview", ""); | |
//treeViewNS = nsName; // Setup the short name. | |
//xmldoc.documentElement.attributes.setNamedItem(treeViewNS); | |
//xmldoc.insertNode(treeViewNS); | |
displayTree(); | |
selectionString.value = "xmldoc."; | |
} | |
} | |
} | |
// This function isolates the process of add the xml to the tree view. | |
function addhtml(text) | |
{ | |
strStruct += text; | |
} | |
// Use the recursive function buildTree to build the html | |
// version of the tree. Display the tree in a seperate frame. | |
function displayTree() | |
{ | |
if (xmldoc == null) | |
{ | |
alert("No xml file has been loaded."); | |
} | |
else | |
{ | |
selectedNodes = new Array(); | |
selectedNodesType = new Array(); | |
selectedNodesLength = 0; | |
//displayFrame = parent.display; | |
//displayFrame.document.open(); | |
strStruct = ""; | |
//addhtml("<HTML><BODY BGCOLOR=\"#FFFFFF\">"); // #FFFFFF is white. | |
elementNum = 0; | |
code = new Array(); | |
//buildTree(xmldoc.documentElement, 0, ("XMLtree_" + elementNum),0); | |
buildTree(xmldoc.documentElement, 0, 0); | |
displayFrame.document.open(); | |
displayFrame.document.write(strStruct); | |
displayFrame.document.close(); | |
} | |
} | |
// buildTree is recursive. | |
// level is the depth of the tree. | |
// last is a boolean to tell the element if it's the last one | |
// in the list. 1=true, 0=false. The last one needs corner.gif. | |
function buildTree(node, level, last) | |
{ | |
if (level != 0) | |
{ | |
// Add | and whitespace | |
for (var j = 0; j < (level-1); j++) | |
{ | |
if (code[j] == 0) | |
addhtml("<IMG SRC=\"vertical.gif\" ALIGN=\"absbottom\"> "); | |
else | |
addhtml( "<IMG SRC=\"blank.gif\" ALIGN=\"absbottom\"> "); | |
} | |
// Add the appropriate corner piece. | |
if (last == 1) | |
addhtml("<IMG SRC=\"corner.gif\" ALIGN=\"absbottom\"> "); | |
else | |
addhtml("<IMG SRC=\"corner_continue.gif\" ALIGN=\"absbottom\"> "); | |
} | |
// Process a text node. | |
if (node.nodeType == TEXT_NODE) | |
addhtml("<FONT COLOR=\"" + textColor + "\">" + node.text + "</FONT>"); | |
else if (node.nodeType == COMMENT_NODE) | |
addhtml("<FONT COLOR=\"" + commentColor + "\">" + node.text + "</FONT>"); | |
else | |
{ | |
// Don't do the following on text nodes. Don't give them | |
// spans or check for attributes. | |
// Make a span with a unique ID for each element to be able to | |
// access them later. | |
var elementID = "TreeViewer_" + elementNum; | |
addhtml("<SPAN ID=\"" + elementID + "\">" + node.nodeName + "</SPAN>"); | |
elementNum++; // Increment ID counter. | |
// Put an attribute on each element that acts as pointers to | |
// their corresponding span tags. | |
//node.setAttribute(attID, elementID, treeViewNS); | |
var tvNode = xmldoc.createNode("attribute",attID,treeViewNS); | |
tvNode.text = elementID; | |
node.attributes.setNamedItem(tvNode); | |
// Display attributes | |
var attNum = node.attributes.length; | |
if (attNum > 0) | |
{ | |
for (var i = 0; i < attNum; i++) | |
{ | |
// Don't display attributes from the Tree Viewer namespace. | |
if (node.attributes.item(i).namespace != null) | |
{ | |
if (node.attributes.item(i).namespace != treeViewNS) | |
addhtml("<B> ; </B><SPAN ID=\"" + elementID + "_att_" + i + "\" STYLE=\"color:green\">" + node.attributes.item(i).nodeName + "</SPAN>"); | |
//+ " = \"" + node.attributes.item(i).text + "\""; | |
} | |
else | |
{ | |
addhtml("<B> ; </B><SPAN ID=\"" + elementID + "_att_" + i + "\" STYLE=\"color:green\" >" + node.attributes.item(i).nodeName + "</SPAN>"); // + " = \"" + node.attributes.item(i).text + "\""; | |
} | |
} | |
} | |
} | |
addhtml("<BR>"); | |
// If there are children under this node, call buildTree on them. | |
var children = node.childNodes.length; | |
if (children != 0) | |
{ | |
for (var i = 0; i < children; i++) | |
{ | |
if (i == (children - 1) ) | |
{ | |
// This case means we are at the last element. | |
code[level] = 1; | |
buildTree(node.childNodes.item(i), (level + 1), 1); | |
} | |
else | |
{ | |
code[level] = 0; | |
buildTree(node.childNodes.item(i), (level + 1), 0); | |
} | |
} | |
} | |
} | |
// ******************************************************************** | |
// * Displaying XML in a seperate window functions | |
// ******************************************************************** | |
function showXML() | |
{ | |
if (xmldoc == null) | |
{ | |
alert("No xml file has been loaded."); | |
} | |
else | |
{ | |
var txtToShow = dumpTree(xmldoc.documentElement, 0); | |
var wNew = window.open(); | |
wNew.document.body.innerHTML = "<B>"+txtToShow+"</B>"; | |
} | |
} | |
// Format the XML into HTML | |
function dumpTree(node, i) | |
{ | |
var result = "<DL class=xml><DD>"; | |
if (node != null) | |
{ | |
if (node.nodeTypeString == "comment") | |
{ | |
result += "<span class=comment><!--" + node.text + "--></span>" + "</DD></DL>"; | |
return result; | |
} | |
result += "<span class=tag><" + node.nodeName + "</span>"; | |
// determine if the tag has children or is empty | |
var num; | |
// process the attributes | |
if (node.attributes.length > 0) | |
{ | |
var a, i, l; | |
l = node.attributes.length; | |
for (i = 0; i < l; i++) | |
{ | |
a = node.attributes.item(i); | |
// Don't display attributes from the Tree Viewer namespace. | |
if (a.namespace != treeViewNS) | |
result += "<span class=attr> " + a.nodeName + "=\"" + a.text + "\"</span>" | |
} | |
} | |
if (node.childNodes != null) | |
num = node.childNodes.length; | |
else | |
num = 0; | |
// close the element tag (if empty, use shorthand) | |
if (num == 0) // tag is empty | |
result += "<span class=tag>/></span>"; | |
else | |
result += "<span class=tag>></span>"; | |
// process the children of the element if it has any | |
if (num > 0) // tag has children | |
{ | |
if (isMixed(node,num) > 0) | |
{ | |
result += node.text; | |
} | |
else | |
{ | |
var j; | |
for (j = 0; j < num; j++) | |
{ | |
result += "\n"; | |
var child = node.childNodes.item(j); | |
// uncommented following line | |
result += dumpTree(child,i + 1); | |
} | |
} | |
result += "<span class=tag></" + node.nodeName + "></span>\n"; | |
} | |
} | |
result += "</DD></DL>" | |
return result; | |
} | |
// checks to see if all children of the element are | |
// the same node type | |
function isMixed(node,num) | |
{ | |
var j; | |
for (j = 0; j < num; j++) | |
{ | |
var child = node.childNodes.item(j); | |
var type = child.nodeTypeString; | |
if (type == "text" || type == "cdata_section" || | |
type == "entity_reference") | |
return 1; | |
} | |
return 0; | |
} | |
</SCRIPT> | |
</HTML> |