PDA

View Full Version : XML loader for TreeNodes



zeppelin
17 Apr 2007, 2:01 AM
I've read on the forum that there is no other source data format but JSON for async tree nodes. I've wrote a little custom xml2json function and I don't know what method should I rewrite to make the conversion before the default json node processing, can you help me?

Many Thanks

JeffHowden
18 Apr 2007, 12:58 AM
It'd probably be helpful to know a) what does the XML you're converting from look like and b) what does the JSON result after that conversion look like so far. With that, I think there'll be enough information to get you going in the right direction.

Also, have you taken a look at the JSON that's returned to the async trees in the examples?

Animal
18 Apr 2007, 2:22 AM
Would the following code help? It's a demo page which should drop into examples/tree



<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Tree Test</title>

<link rel="stylesheet" type="text/css" href="../../resources/css/ext-all.css" />
<script type="text/javascript" src="../../yui-utilities.js"></script>
<script type="text/javascript" src="../../ext-yui-adapter.js"></script>
<script type="text/javascript" src="../../ext-all-debug.js"></script>
<script type="text/javascript">
/**
Create an Ext.tree.TreePanel in the passed Element using
an XML document from the passed URL, calling the passed
callback on completion.
@param el {String/Element/HtmlElement} The tree's container.
@param url {String} The URL from which to read the XML
@param callback {function:tree.render} The function to call on completion,
defaults to rendering the tree.
*/
function createXmlTree(el, url, callback) {
var tree = new Ext.tree.TreePanel(el);
var p = new Ext.data.HttpProxy({url:url});
p.on("loadexception", function(o, response, e) {
if (e) throw e;
});
p.load(null, {
read: function(response) {
var doc = response.responseXML;
tree.setRootNode(treeNodeFromXml(doc.documentElement || doc));
}
}, callback || tree.render, tree);
return tree;
}
/**
Create a TreeNode from an XML node
*/
function treeNodeFromXml(XmlEl) {
// Text is nodeValue to text node, otherwise it's the tag name
var t = ((XmlEl.nodeType == 3) ? XmlEl.nodeValue : XmlEl.tagName);

// No text, no node.
if (t.replace(/\s/g,'').length == 0) {
return null;
}

// Special case of an element containing no attributes and just one text node
var leafTextNode = ((XmlEl.attributes.length == 0) && (XmlEl.childNodes.length == 1) && (XmlEl.firstChild.nodeType == 3));
if (leafTextNode ) {
return new Ext.tree.TreeNode({
tagName: XmlEl.tagName,
text: XmlEl.firstChild.nodeValue
});
}

var result = new Ext.tree.TreeNode({
text : t
});

// For Elements, process attributes and children
if (XmlEl.nodeType == 1) {
Ext.each(XmlEl.attributes, function(a) {
var c = new Ext.tree.TreeNode({
text: a.nodeName
});
c.appendChild(new Ext.tree.TreeNode({
text: a.nodeValue,
}));
result.appendChild(c);
});
if (!leafTextNode) {
Ext.each(XmlEl.childNodes, function(el) {
// Only process Elements and TextNodes
if ((el.nodeType == 1) || (el.nodeType == 3)) {
var c = treeNodeFromXml(el);
if (c) {
result.appendChild(c);
}
}
});
}
}
return result;
}
Ext.onReady(function() {
createXmlTree( 'tree-div', '../grid/plants.xml');
});
</script>
</head>
<body>
<div id="tree-div" style="overflow:auto; height:300px;width:300px;border:1px solid #c3daf9;"></div>
</body>
</html>

zeppelin
19 Apr 2007, 12:22 AM
Well, I've coded the next:


Ext.tree.TreeXMLLoader = function(config){
this.baseParams = {};
this.requestMethod = "POST";
Ext.apply(this, config);

this.events = {
"beforeload" : true,
"load" : true,
"loadexception" : true
};
};

Ext.extend(Ext.tree.TreeXMLLoader, Ext.tree.TreeLoader, {
processResponse : function(response, node, callback){
try {
var o = xml2obj(response.responseXML).children;
for(var i = 0, len = o.length; i < len; i++){
var n = this.createNode(o[i]);
if(n){
node.appendChild(n);
}
}
if(typeof callback == "function"){
callback(this, node);
}
}catch(e){
this.handleFailure(response);
}
}
});

Where xml2obj converts my xml to a JS object. Anyway, I will take a look for Animal's suggestion, for a more standar functionality.
Do you see any problem to the solution I've taken?

Thanks!!

efege
20 Apr 2007, 7:45 AM
Thanks Animal for your code. I'm not sure whether you intended it to work for arbitrary XML, anyway this could be of interest to some people... Using the following simplified XML file:


<?xml version="1.0" encoding="ISO-8859-1"?>
<catalog>
<plant id="1">
<common>Bloodroot</common>
<botanical>Sanguinaria canadensis</botanical>
<zone>4</zone>
<light>Mostly Shady</light>
<price>2.44</price>
<availability>03/15/2006</availability>
<indoor>true</indoor>
</plant>
<info type="trivial">hello</info>
</catalog>

an error occurs, shown in detail in the screenshot. It is caused by the presence of an attribute on an element (<info>) which itself has no child element.

Don't know if I'd be able to patch the code though...

becomcs
6 Jun 2007, 5:10 AM
I found somthing which seems to be an error into Animal's code.



// For Elements, process attributes and children
if (XmlEl.nodeType == 1) {
Ext.each(XmlEl.attributes, function(a) {
var c = new Ext.tree.TreeNode({
text: a.nodeName
});
c.appendChild(new Ext.tree.TreeNode({
text: a.nodeValue,
}));
result.appendChild(c);
});
if (!leafTextNode) {
Ext.each(XmlEl.childNodes, function(el) {
// Only process Elements and TextNodes


Tree node constructor isn't complete.

Anyway, when I modify the code, it return an error code "0" uncaught exception.

Animal
6 Jun 2007, 6:16 AM
OK, this seems much better:



<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Tree Test</title>

<link rel="stylesheet" type="text/css" href="../../resources/css/ext-all.css" />
<script type="text/javascript" src="../../yui-utilities.js"></script>
<script type="text/javascript" src="../../ext-yui-adapter.js"></script>
<script type="text/javascript" src="../../ext-all-debug.js"></script>
<script type="text/javascript">
/**
Create an Ext.tree.TreePanel in the passed Element using
an XML document from the passed URL, calling the passed
callback on completion.
@param el {String/Element/HtmlElement} The tree's container.
@param url {String} The URL from which to read the XML
@param callback {function:tree.render} The function to call on completion,
defaults to rendering the tree.
*/
function createXmlTree(el, url, callback) {
var tree = new Ext.tree.TreePanel(el);
var p = new Ext.data.HttpProxy({url:url});
p.on("loadexception", function(o, response, e) {
if (e) throw e;
});
p.load(null, {
read: function(response) {
var doc = response.responseXML;
tree.setRootNode(treeNodeFromXml(doc.documentElement || doc));
}
}, callback || tree.render, tree);
return tree;
}
/**
Create a TreeNode from an XML node
*/
function treeNodeFromXml(XmlEl) {
// Text is nodeValue to text node, otherwise it's the tag name
var t = ((XmlEl.nodeType == 3) ? XmlEl.nodeValue : XmlEl.tagName);

// No text, no node.
if (t.replace(/\s/g,'').length == 0) {
return null;
}

var result = new Ext.tree.TreeNode({
text : t
});

// For Elements, process attributes and children
if (XmlEl.nodeType == 1) {
Ext.each(XmlEl.attributes, function(a) {
result.appendChild(new Ext.tree.TreeNode({text: a.nodeName}))
.appendChild(new Ext.tree.TreeNode({text: a.nodeValue}));
});
Ext.each(XmlEl.childNodes, function(el) {
var c = treeNodeFromXml(el);
if (c) result.appendChild(c);
});
}
return result;
}
Ext.onReady(function() {
// var tree = createXmlTree( 'tree-div', '../grid/plants.xml', function(){
var tree = createXmlTree( 'tree-div', '../grid/sheldon.xml', function(){
this.render();
this.getRootNode().expand();
});
});
</script>
</head>
<body>
<div id="tree-div" style="overflow:auto; height:300px;width:300px;border:1px solid #c3daf9;"></div>
</body>
</html>

becomcs
6 Jun 2007, 7:23 AM
Sorry...

I still have an uncaught exception near

p.on("loadexception", function(o, response, e) {
if (e) throw e;
});

Thank a lot for your help

Animal
6 Jun 2007, 7:30 AM
With what XML?

Animal
6 Jun 2007, 7:35 AM
That's a load exception. Check your Firebug tab to check the HTTP status. You know it's looking for a certain file in a certain location using a relative URL. You can't just drop that file anywhere and expect it to work.

becomcs
6 Jun 2007, 2:20 PM
OK.

I checked at home and it worked fine.

However I'd checked the relative path 3 time.

It seems to be a

bruneaum
8 Jan 2008, 9:56 AM
Good day,

Using the code above, I am getting an exception:

Error: 'this.root' is null or not an object

XML:
--------------------------------------
<inventory>
<operator>
<name>Test Operator</name>
<facility>
<facilityname>My Awesome Facility</facilityname>
<source>Boiler 1</source>
</facility>
</operator>
</inventory>
--------------------------------
thanks.

tdv
8 Jan 2008, 2:59 PM
http://extjs.com/forum/showthread.php?t=3987&highlight=column+tree+xml&page=11

see post by colinexl