Creating a Tree from attribute heavy XML

The examples that I have seen illustrate how to populate a tree from an XML document with nested elements where each element/tag name identifies a file or a folder.

For my project, I’m working with an XML document that I assume will need a custom driver that can parse attributes of the tags to determine the type (file or folder) to display in the ui.

Here’s an example:

<?xml version="1.0" encoding="ISO-8859-1"?>

Has anyone had any success using this type of document to drive the tree?

The XML that was missing from the original post:

<?xml version="1.0" encoding="ISO-8859-1"?>
<stat directory="/477198/DDDD-AAAA-DDDD-AAAA-CCCC-D/Assets/Video">
<file type="file" name="BehindTheScenes.mov" mtime="1481919685" size="5511192819" md5="bc901962fb52bbb5098de4dd497284de"/>
<file type="file" name="OutTakes.m3u8" mtime="1481134024" size="605" md5="2b35e64857ce50481e0e1b460b0952d4"/>
<file type="dir" name="BonusMaterial" mtime="1481134090"/>
<file type="file" name="ActionFootage.mov" mtime="1481918753" size="3081289698" md5="a21a43aab8578e6007f2f811d7b56927"/>
<file type="file" name="Loving_VirginiaALovingBackdrop.m3u8" mtime="1481134024" size="689" md5="8d761f6c07f8b78b0915db0e591c058f"/>
</stat>

Looks like this will do the job, maybe someone else will find it useful

    var txt='<?xml version="1.0" encoding="ISO-8859-1"?><stat directory="/477198/DDDD-AAAA-DDDD-AAAA-CCCC-D/Assets/Video"><file type="file" name="BehindTheScenes.mov" mtime="1481919685" size="5511192819" md5="bc901962fb52bbb5098de4dd497284de"/><file type="file" name="OutTakes.m3u8" mtime="1481134024" size="605" md5="2b35e64857ce50481e0e1b460b0952d4"/><file type="dir" name="BonusMaterial" mtime="1481134090"/><file type="file" name="ActionFootage.mov" mtime="1481918753" size="3081289698" md5="a21a43aab8578e6007f2f811d7b56927"/></stat>';

    var myxml2 = webix.DataDriver.myxml2 =  webix.copy(webix.DataDriver.xml);
    myxml2.records = "/stat";
    myxml2.child = function(obj){ return obj.file; }

    tree = new webix.ui({ 
        view: "tree", 
        template:"{common.icon()} {common.folder()} #name#", 
        data: txt, datatype: "myxml2"
    });

Here is a better implementation. Printing only the values that are defined. Next improvement will be to change the icons to display ‘files’ and ‘folders’ appropriately; FileManager implementation is the ultimate goal.

var txt='<?xml version="1.0" encoding="ISO-8859-1"?><stat directory="/477198/DDDD-AAAA-DDDD-AAAA-CCCC-D/Assets/Video"><file type="file" name="BehindTheScenes.mov" mtime="1481919685" size="5511192819" md5="bc901962fb52bbb5098de4dd497284de"/><file type="file" name="OutTakes.m3u8" mtime="1481134024" size="605" md5="2b35e64857ce50481e0e1b460b0952d4"/><file type="dir" name="BonusMaterial" mtime="1481134090"/><file type="file" name="ActionFootage.mov" mtime="1481918753" size="3081289698" md5="a21a43aab8578e6007f2f811d7b56927"/></stat>';

var myxml2 = webix.DataDriver.myxml2 =  webix.copy(webix.DataDriver.xml);
myxml2.records = "/stat";
myxml2.child = function(obj){
  if (obj.$level == 1)
  {
    obj.value = obj.directory;
    return obj.file;
  }
  if (obj.$level == 2)
  {
    obj.value = obj.name;
  }
}

tree = new webix.ui({ 
    view: "tree", 
    data: txt, datatype: "myxml2"
});

And finally, here we see an implementation that will present directory icons for elements of type ‘dir’. Investigation into onDataRequest continues to load branches as we descend through the graph.

var txt='<?xml version="1.0" encoding="ISO-8859-1"?><stat directory="/477198/DDDD-AAAA-DDDD-AAAA-CCCC-D/Assets/Video"><file type="file" name="BehindTheScenes.mov" mtime="1481919685" size="5511192819" md5="bc901962fb52bbb5098de4dd497284de"/><file type="file" name="OutTakes.m3u8" mtime="1481134024" size="605" md5="2b35e64857ce50481e0e1b460b0952d4"/><file type="dir" name="BonusMaterial" mtime="1481134090"/><file type="file" name="ActionFootage.mov" mtime="1481918753" size="3081289698" md5="a21a43aab8578e6007f2f811d7b56927"/></stat>';

var myxml2 = webix.DataDriver.myxml2 =  webix.copy(webix.DataDriver.xml);
myxml2.records = "/stat";
myxml2.child = function(obj){
  if (obj.$level == 1)
  {
    obj.value = obj.directory;
    return obj.file;
  }
  if (obj.$level == 2)
  {
    obj.value = obj.name;
  }
  if (obj.type == "dir")
  {
    obj.webix_kids = true;
  }
}

tree = new webix.ui({ 
    view: "tree", 
    data: txt, datatype: "myxml2"
});

And for those of you looking for an answer to the “extra credit assignment” of loading branches… here you go!

tree.attachEvent("onDataRequest", function (id, callback, url) { 
  // Save the id of this node so that the asynchronous request has context on where to 
  // attach the results when the call returns.
  window.parent_id = id;
  var object = this.getItem(id);
  var path = this.getItem(object.$parent);
  var item = object.name;

  while (!path.directory) {
    item = path.name+"/"+item;
    path = this.getItem(path.$parent);
  }
  item = path.directory+"/"+item;

  // Remove the CP-Code '/477198' prefixed to the string
  this.parse( webix.ajax().headers({
      "X-Akamai-ACS-Action": 'version=1&action=dir&format=xml'}).get(item.substring("/477198".length)).then(function (data) {
    var drop = data.xml ();
    var clone = new Object ();
    clone.parent= this.window.parent_id; 
    if( Object.prototype.toString.call( drop.stat.file ) === '[object Array]' ) {
      clone.data = new Array (drop.stat.file.length);
      for (var i = 0; i  < drop.stat.file.length; ++i)
      {
        clone.data[i] = new Object ();
        clone.data[i].value=clone.data[i].name=drop.stat.file[i].name;
        clone.data[i].mtime=drop.stat.file[i].mtime;
        clone.data[i].type=drop.stat.file[i].type;
        if (clone.data[i].type == "dir")
        {
          clone.data[i].webix_kids = true;
        }
      }
    }
    else 
    {
      clone.data = new Array (1);
      clone.data[0] = new Object ();
      clone.data[0].value=clone.data[0].name=drop.stat.file.name;
      clone.data[0].mtime=drop.stat.file.mtime;
      clone.data[0].type=drop.stat.file.type;
      if (clone.data[0].type == "dir")
      {
        clone.data[0].webix_kids = true;
      }
  } 
  return clone; 
  }) ); 
return false; 
});