/jquery-objtree

converts javascript objects to xml for simple serialization when xml is required.

Primary LanguageJavaScript

jquery-objtree is an xml<→javascipt utility plugin for jquery-jspath.

it provides a thin wrapper around yusuke kawasaki’s http://www.kawa.net/XML (modified) source code.
we largely use it as a stand-in for e4x for use as an html template engine. in particular
it focuses on js to xml conversion, and though it supports xml to js conversion, we would recommend
http://github.com/thatcher/jquery-xslt as it’s much faster,if you need to do a lot of xml to js conversion.

how about a simple example before I loose interest

sure, good idea. let’s pretend we have a big js object we loaded


var addressbook = [{
    $first:'chris',
    $last:'thatcher',
    $cell:'555-555-5555',
    $fax:'444-444-4444',
    address: {
      $line1:'po box 1234',
      $city: 'shepherdstown',
      $state: 'WV',
      $zipcode: '25425'
    }
},{
    $first:'ariel',
    $last:'flesler',
    $cell:'222-222-2222',
    address: {
      $line1:'123 smart way',
      $city: 'new york',
      $state: 'NY',
      $zipcode: '34526'
    }
},{
    $first:'yusuke',
    $last:'kawasaki',
    $cell:'888-888-8888',
    $fax:'999-999-9999',
    address: {
      $line1:'po box 8765',
      $city: 'san fransisco',
      $state: 'CA',
      $zipcode: '87654'
    }
}];

then I could easily serialize out a particular contact:


var xml = _('[?(@.$last == 'thatcher')]', addressbook).x();
alert( xml );			
/* 
<contact 	first='chris'
			last='thatcher'
			cell='555-555-5555'
			fax='444-444-4444'>
	<address 	line1='po box 1234'
				city='shepherdstown'
				state='WV'
				zipcode='25425'/>
</contact>
*/

dang dawg! that blew my mind. let’s turn the tables real quick and show the xml to js conversion:


/*
 here xml is 
 <addressbook>
	<contact 	first='chris'
				last='thatcher'
				cell='555-555-5555'
				fax='444-444-4444'>
		<address 	line1='po box 1234'
					city='shepherdstown'
					state='WV'
					zipcode='25425'/>
	</contact>
	<contact 	first='ariel'
				last='flesler'
				cell='222-222-2222'>
		<address 	line1='123 smart way'
					city='new york'
					state='NY'
					zipcode='34526'/>
	</contact>
	<contact 	first='yusuke'
				last='kawasaki'
				cell='888-888-8888'
				fax='999-999-9999'>
		<address 	line1='po box 8765'
					city='san fransisco'
					state='CA'
					zipcode='87654'/>
	</contact>
 </addressbook>
*/
$.get(url, function(xml){
	var addressbook = _.xml2js(xml).addressbook;
	//addressbook is now exactly the addressbook of our previous example!
});

e4x-like templates

e4x is an awesome extension to the ecma standard (that’s javascript if’n you didn’t already know).
it makes xml objects native javascript objects like Object and Array. i highly recommend this
overview http://www.rephrase.net/days/07/06/e4x .

Of course IEpre8 has no support so you may have never heard of it. jquery-objtree has includes
a 10 line plugin to let you emulate the construction of e4x XML objects! which probably means
nothing to you so lets see what the heck that mean.

e3x – a very fast an clean templating language when e4x isn’t available

lets pretend we have this html snippet in a file on our server and we load it via
ajax into a local variable named ‘template’


<div id='todo'>
    <h2 class='e3x'>{title}</h2>
    <ul class='e3x'>{
        _('.*',todo).map(function(index, value){
            return {li:{
                $:[ 
                    this.note, 
                    {strong:this.duedate}
                ]
            }}
        }).x()
    }</ul>
</div>

Note:
The use of the jQuery map function in combination with the x() plugin is a trick we learned
from actual use of e4x as a templating engine, and it rocks!

so each element with the class ‘e3x’ will be rendered just like an e4x xml instance when we do this:


	$.ajax({
        url:'mytemplate.html',
        dataType:'html',
        async:false,
        success: function(xml){
            var template = $(xml);
            var rendered = _.e3x(template, {
                _:_,//include jspath
                title:'Do or Die!',
                todo: [{
                    note:'wash socks',
                    duedate: '9/11/09'
                },{ 
                    note:'finish taxes',
                    duedate: '9/12/09'
                },{
                    note:'sleep in',
                    duedate: '9/13/09'
               }]
            });
            console.log( $(rendered).outerHTML() );
        }
    });

and the result is a dom object that would serialze to look like:


<div id="todo">  
	<h2 class="e3x">Do or Die!</h2>  
	<ul class="e3x">
		<li> wash socks <strong>9/11/09</strong> </li> 
		<li> finish taxes <strong>9/12/09</strong> </li> 
		<li> sleep in <strong>9/13/09</strong> </li>
	 </ul>  
</div>

There is tons of fun to be had with this and it can keep your project cleaner too (keep
that html out of your javascript whenever possible!)

javascript object tree conventions

properties with simple value

javascript


{
'family': {
    '$name':    'Kawasaki',
    'father':   'Yasuhisa',
    'mother':   'Chizuko',
    'children': {
        'girl': 'Shiori'
        'boy': [
            'Yusuke',
            'Kairi'
        ]
    }
}
};

xml

<family name="Kawasaki">
    <father>Yasuhisa</father>
    <mother>Chizuko</mother>
    <children>
        <girl>Shiori</girl>
        <boy>Yusuke</boy>
        <boy>Kairi</boy>

’’’note’’’

  • the property prefixed with $ becomes an attribute.
  • all other properties with simple values are treated as elements with text content
  • arrays of simple values become a sequence of elements

property with text content and attributes

javascript


{
'msg': {
    '$user': 'thatcher',
    '$':     'Hey, yt?',
}
};

xml

<msg user="thatcher">
	Hey, yt?

’’’note’’’

  • the property prefixed with $ becomes an attribute.
  • the node named $ is treated as a text node if the value is simple (arrays become mixed context)

objtree namespacing

javascript


{
'feed': {
	$xmlns:'http://www.w3.org/2005/Atom'
	$xmlns$xhtml:'http://www.w3.org/1999/xhtml',
	title:'example feed',
	updated: 'Tue, 21 Apr 2009 22:42:45 GMT',
	id: 'urn:uuid:124652-3264-2346231-rw3r3-1',
	entry:[{
		title:'example entry',
        link: { $href='http://www.example.org' },
        id:'urn:uuid:25234-45yewg-356234-fq34-23',
        updated: 'Tue, 21 Apr 2009 22:42:45 GMT',
        summary:{
        	 $type:"xhtml",
            ul: {
            	$xmlns:'http://www.w3.org/1999/xhtml',
            	li:['a','b','c']
            }
        }
	}]
}
};

xml

<feed xmlns='http://www.w3.org/2005/Atom'
	xmlns:xhtml='http://www.w3.org/1999/xhtml'
	<title>example feed</title>
	<updated>Tue, 21 Apr 2009 22:42:45 GMT</updated>
	<id>urn:uuid:124652-3264-2346231-rw3r3-1</id>
	<entry>
		<title>example entry</title>
        <link href='http://www.example.org/'/>
        <id>urn:uuid:25234-45yewg-356234-fq34-23</id>
        <updated>Tue, 21 Apr 2009 22:42:45 GMT</updated>
        <summary type='xhtml'>
            <ul xmlns='http://www.w3.org/1999/xhtml'>
            	<li>a</li>
            	<li>b</li>
            	<li>c</li>

’’’note’’’

  • any occurance of ‘$’ not at the begining of the property name will be replaced with ‘:’
  • jquery-object has no knowledge of what a namespace means, but allows you to use them

mixed content

javascript


{
'p': {
    '$': [
	    'this is a ',
	    {a:{$href:'http:www.example.org', $:'link'}},
	    'to a great page I found on the web'
    ]
}
};

xml

<p>
	this is a 
	<a href='http://www.example.org'>link</a> 
	to a great page I found on the web

’’’note’’’

  • the property named $ is an array, so each item is treated treated as text nodes when
    its a simple type or an element when its an object or array.

CONFIGURATION OPTIONS

The options may either be set globally by using _.objtree() static method on the jquery-jspath namespace.
The options for configuring are given below.

opts.force_array = [ “rdf$li”, “item”, “$xmlns” ];

This property allows you to specify a list of element names
which should always be forced into an array representation.
The default value is null, it means that context of the elements
will determine to make array or to keep it scalar.

opts.attr_prefix = ‘$’;

This property allows you to specify a prefix character which is
inserted before each attribute names.
The default character is ‘$’.
Or set ‘@’ to access attribute values like E4X, ECMAScript for XML.
The length of attr_prefix must be just one character and not be empty.

opts.ns_colon = ‘$’;

This property allows you to specify a character which is
replaced as the namespace colon on each xml name.
The default character is ‘$’.
The length of ns_colon must be just one character and not be empty.

xotree.xmlDecl = ’’;

This library generates an XML declaration on writing an XML code per default.
This property forces to change or leave it empty.

METHODS

tree = _.xml2js( xmlsrc );

This method loads an XML document using the supplied string
and returns its JavaScript object converted.

tree = _.dom2js( domnode );

This method parses a DOM tree (ex. responseXML.documentElement)
and returns its JavaScript object converted.

xmlsrc = _x( tree ) = _.js2xml( tree );

xmlsrc = _( path, tree ).x();

This method parses a JavaScript object tree
and returns its XML source generated.

_.fn.tmpl


xmlsrc = _('.*',[
	{name:'chris'},
	{name:'thatcher'}
]).tmpl({a:{$href:'|:name|', $:'|:name|'}}).x();

This method allows you to create an object-to-object template, of couse you can always use
map


_('.*',[
    {name:'chris'},
    {name:'thatcher'}
]).map(function(){
    return {a:{$href:this.name, $:this.name}};
}).x()

both will produce


<a href="chris">chris</a>
<a href="thatcher">thatcher</a>

also check out these
jquery-jspath plugins:

also please check out the spec for each plugin (test/test.html). special thanks to aaron quint for the
jqunit-spec plugin that all of these plugins use!

ORIGINAL AUTHOR Yusuke Kawasaki http://www.kawa.net/

COPYRIGHT AND LICENSE

Copyright © 2005-2006 Yusuke Kawasaki. All rights reserved.
This program is free software; you can redistribute it and/or
modify it under the Artistic license. Or whatever license I choose,
which I will do instead of keeping this documentation like it is.