views:

44

answers:

2

I have an existing data structure which is stored as an xml doc. It is essentially a sitemap. Every node has some associated metadata (e.g., keywords and description associated with the node). I would like to be able to use the xml_data plugin to be able to load directly from that source. From a quick look at both the documentation and the source, it doesn't look like that is possible - I'm limited to the two formats described in the documentation.

However, I can't imagine that this is a completely unique use case. It seems like my options would be to extend jstree so that I could add my own XSLT to the xsl var to handle my format, preprocess the format of the file server side so that the result is in the expected format, or change my data interchange format to JSON and convert between JSON and XML serverside. The sense I get from the posts I have seen is that it is at least possible to serialize/deserialize metadata with the json_data plugin, but I'm not 100% sure on that.

Can anyone help refine my direction based on your experience?

Thanks, Rob

A: 

I looks to me that it is possible.

See:

http://www.jstree.com/documentation/xml_data

The JsTree function called .parse_xml can be used to convert XML strings or objects to the DOM structure required by jstree.

Edit: Wrong!

If you post an example of your site map XML I'd be happy to create a working example for you.

Edit: Working example below

You can make JsTree process an external XML source but via the ajax options. Imagine you had an XBEL file like this:

<xbel version="1.0">    
    <bookmark href="http://stackoverflow.com"&gt;
        <title>Stack Overflow</title>
    </bookmark>
    <folder>
        <title>Stack Exchange</title>
        <folder>
            <title>Programming</title>
            <bookmark href="http://stackoverflow.com"&gt;
                <title>Stack Overflow</title>
            </bookmark>
            <bookmark href="http://stackapps.com"&gt;
                <title>Stack Apps</title>
            </bookmark>
            <bookmark href="http://webapps.stackexchange.com"&gt;
                <title>Web Applications</title>
            </bookmark>
            <bookmark href="http://programmers.stackexchange.com/"&gt;
                <title>Programmers</title>
            </bookmark>
        </folder>
        <folder>
            <title>Systems</title>
            <bookmark href="http://serverfault.com"&gt;
                <title>Server Fault</title>
            </bookmark>
            <bookmark href="http://superuser.com"&gt;
                <title>Super User</title>
            </bookmark>
        </folder>
        <bookmark href="http://careers.stackoverflow.com"&gt;
            <title>Careers</title>
        </bookmark>
        <bookmark href="http://meta.stackoverflow.com"&gt;
            <title>Meta</title>
        </bookmark>
        <bookmark href="http://area51.stackexchange.com"&gt;
            <title>Area 51</title>
        </bookmark>
        <bookmark href="http://gaming.stackexchange.com"&gt;
            <title>Gaming</title>
        </bookmark>
    </folder>
</xbel>

You can process this with JsTree like this:

<html>
    <head>
        <title></title>
        <script type="text/javascript" src="_lib/jquery.js"></script>
        <script type="text/javascript" src="_lib/jquery.cookie.js"></script>
        <script type="text/javascript" src="_lib/jquery.hotkeys.js"></script>
        <script type="text/javascript" src="jquery.jstree.js"></script>
        <script type="text/javascript">

            $(function () {
                $("#xbel").jstree({
                    "xml_data" : {
                        "ajax" : {
                            "url" : "stackexchange.xml",
                            "success" : function(data, textStatus, XMLHttpRequest){
                                var result = $('<dom></dom>');
                                var root = $('<root></root>');          
                                var doc = traverseXbel($(data), root);
                                result.append(doc);
                                return result.html();
                            }
                        },
                        "xsl" : "nest"
                    },
                    "plugins" : [ "themes", "xml_data" ]
                });

            });

           function traverseXbel(xbel, doc){
                var title, href, item, name, content, innerdoc;
                // folder => item
                // bookmark => item with href attribute

                // Deal with this level bookmarks                
                $(xbel).children('bookmark').each(function(){
                    href = $(this).attr('href');
                    title = $(this).find('title').text();
                    if(title && href){
                        item = $('<item></item>');
                        content = $('<content></content>');
                        name = $('<name></name>');
                        name.attr("href", href);                        
                        name.text(title);                        
                        content.append(name);
                        item.append(content);                        
                        doc.append(item);
                    }
                });                
                $(xbel).children('folder').each(function(){
                    title = $(this).find('title:first').text();
                    if(title){
                        item = $('<item></item>');
                        content = $('<content></content>');
                        name = $('<name></name>');
                        name.text(title);                        
                        content.append(name);
                        item.append(content);                        
                        item = traverseXbel($(this), item);
                        doc.append(item);                            
                    }
                });                
                return doc;
           }


        </script>
    </head>
    <body>
        <div id="xbel"></div>
    </body>
</html>

Okay I feel less of an idiot now, my first answer was wrong because I misunderstood the JsTree API docs.

Mark McLaren
A: 

Thanks!

That approach was completely non-obvious to me from the documentation, but I believe I can work with that. I may have to do a little playing to see if I can easily reserialize it back to the same format when I want to post it to the server after editing.

I also realized that the answer to my other piece was obvious once I looked at the stylesheet more closely. The nest XSLT will pass arbitrary attributes on the item element of the XML right on through to the corresponding li element of the tree. Thus, I can serialize my metadata and pass it along that way. I'll definitely have to do some preprocessing when I send the XML back to the server, though.