DP_YODEL Library

Download | Revision History | Usage | Functions | Examples

The DP_YODEL library provides JavaScript support for the YODEL (Yet another Open Data Exchange Language) standard.

  • All features of the YODEL specification are fully supported (including full metadata deserialization).
  • The library supports a simple method of parsing custom datatypes using the YODEL custom attribute via user-defined custom handlers.
  • The library supports XSD validation under Internet Explorer.
  • The library has a very small footprint. Only the documented functions are added and nothing else (no properties, global variables or other suprises).

You can also find out more about the YODEL specification.

Download back to top

This component requires a JavaScript (ECMAScript) 1.3 (or better) development enviroment. All downloads and code are covered by our Source Code Policy.

DP_YODEL.zip, 6.12kb Zip-Format Archive

Revision History back to top

November 15, 2006

This is an important release which changes some subtle behavior. Please read the notes below if you're upgrading from a previous release.

  • Changed the handling of Metadata to meet the new specification rules (metadata can now be overridden by attribute values in the data tags).
  • Improved the string parsing code to better support ampersands and "double escaping". (For example the double-escaped string "&amp;lt;" is now properly deserialized to "&lt;" rather than "<".)
  • Deserilization of simple values has been, well, simplified. Previously strings, booleans and numbers without values would be deserialized into new objects (as "new String()", "new Boolean()" and "new Number()" respectively). Now they will be deserialized as simple values (as "", "false" and "0" respectively).

July 12, 2006

  • Further improved the DOM-parser discovery to ensure that any MS parser-related errors are delivered properly.

July 05, 2006

  • Fixed a small bug. An extraneous global variable ("SerializeChars") was being created. It is now a function-local variable as intended.

June 21, 2006

  • Added code by drefty[at]gmail.com to improve the DOM-discovery process. With this new code in place the library will now work when called via Windows Scripting Host and other non-browser containers.
  • Added code by drefty[at]gmail.com to improve the handling of field name lists. Specifically field name lists can now include spaces in the list delimiter.
  • Tightened several of the regular expressions to eliminate false positives in the deserialization process.

October 3, 2005

  • Fixed a bug in the libary which may cause string conversion issues when the same object instance was used to both serialize and deserialize.

September 19, 2005

  • Added the "CustomHandlers" feature. Thanks to Barney Boisvert for his great help with this feature.

September 9, 2005

  • Initial Release.

Usage back to top

The library consists of a single JavaScript file with a .JS extension.

Importing the Library

The library must be imported before it is used. To import the library use the <script> tag. For example:
<script type="text/javascript" src="DP_YODEL.js"></script>.

Your path may vary depending on the location of the script on your server.

Using the Library

Once the library has been imported you may access any of the functions within it directly. For example:

var MyYODEL = dpYODEL("serialize", MyObject);

See the Functions section for more information.

General Recommendations

There are many reason that YODEL processing may fail. Corrupt (or badly constructed) packets, unexpected data structures, human error, etc. For this reason it's suggested that you take advantage of modern JavaScript's error handling capacity and wrap all of your YODEL processing in a try {} catch() {} structure. You can then gracefully recover from parsing errors within the application.

YODEL is a purely aggregated dialect: there is no capacity to handle circular or recursive references. Passing objects with such references to dpYODEL will almost certainly (due to the endless loop being created) result in an application crash.

Functions back to top

There is only one function currently available in the library, the dpYODEL function:

dpYODEL()

Function Signature

dpYODEL(Action, Input, [XSDURL], [CustomHandlers])

Arguments

  • Action: String, Required. The action to perform. Can be either "serialize" (convert a native object to a YODEL packet) or "deserialize" (convert a YODEL packet to a native object).
  • Input: Object or String. Required. If Action is "serialize" this argument is the native object to be converted. If Action is "deserialize" this argument is the YODEL packet to be converted.
  • XSDURL: String (URL), Optional (defaults to null). This argument is ignored when Action is "deserialize". If you wish to include the YODEL XSD (enabling XSD validation for capable clients) in your packets include the full URL to the XSD here.
  • CustomHandlers: Object (Hash Table), Optional (defaults to an empty object). This argument is ignored when Action is "serialize". If present this will contain a hash table object of references to custom handler functions. See the examples below for more information.

Return

Object or String. If Action is "serialize" returns a YODEL XML packet. If Action is "deserialize" returns the native object constructed from the packet.

Examples back to top

For examples of YODEL and information about how to use it see the YODEL Specification.

Serialization

To serialize a native JavaScript object to YODEL you might do this:

var MyYODEL = dpYODEL("serialize", MyObject);

To serialize a native JavaScript object to YODEL and include an XSD you might do this:

var MyYODEL = dpYODEL("serialize", MyObject, "[XSD URL]");

The YODEL XSD is available. For best performance and reliability in your application we strongly suggest that you place the XSD on the same server from which your YODEL application is served.

Deserialization

To deserialize a YODEL packet into a native JavaScript object you might do this:

var MyObject = dpYODEL("deserialize", MyYODEL);

Using Custom Handlers

By using the CustomHandlers feature of the dpYODEL() function developer's can easily implement custom deserialization processing by defining external data handler functions and linking them to pre-defined values of the custom attribute in YODEL. dpYODEL() processes custom handlers as follows:

  1. The parser first deserializes the node normally using the standard datatype provided.
  2. The parser then checks the value of the custom attribute against the list of defined custom handlers. If there's a match we continue. If there's no match we return the node value "as is".
  3. The parser passes the deserialized node value to the custom handler (a JavaScript function) as a single attribute.
  4. The custom handler performs its processing.
  5. The custom handler returns the value to be included in the results. This value will replace the orginal value in the deserialization result.

So, considering this, custom handlers must follow some simple rules:

  • They must accept (at least) a single parameter representing the generically deserialized value.
  • They must return the value to be included in the deserialized packet.

Let's examine a simple example. Consider the following YODEL packet:

<yodel>
     <d type="string" custom="GUID">2b8bc980-1e96-11da-8cd6-0800200c9a66</d>
</yodel>

This packet defines a single string value. Any YODEL parser will be able to read this packet as a string. However the packet also defines a custom value of "GUID" (Globally Unique Identifier) in relation to the string.

Now consider the following JavaScript function which represents a GUID object. It validates input against a Regular Expression and returns a simple object with a "value" property containing the passed GUID. If the value passed does not validate the function throws a (catchable) error. The function accepts one parameter ("Input") and (if validation is successful) returns itself as a value:

	// Create a custom "GUID" class
function GUID(Input) {
    if ( Input.match(/^\{?[a-fA-F\d]{8}-(?:[a-fA-F\d]{4}-){3}[a-fA-F\d]{12}\}?$/)[0] == Input ) {
        this.value = Input;
        return this;
    } else {
        throw new Error("The value passed is not a GUID.");
    };
}; 

To create a CustomHandlers object we generate a new object and create a key whose name is the value of the related YODEL custom attribute and whose value is a reference to the function. This object may contain any number of custom handlers (although of course each one must be linked to a unique name):

	// Create a CustomHandlers object
CustomHandlers = new Object();
CustomHandlers["GUID"] = GUID;

With the above code whenever the parser encounters a custom value of "GUID" it will first deserialize the value (as a string in our case) and then pass the resulting value to the defined GUID() function. The results of the GUID function will then appear in the deserializer output.

Once you've generated all of your custom code and created the CustomHandlers table you can call deserializer like so:

var MyObject = dpYODEL("deserialize", MyYODELPacket, "", CustomHandlers);

Using custom handlers developers might:

  • Validate the value provided to ensure that it's follows some defined format (as in our example). Since the custom handler can perform any processing the validations required can be as complex as required (in some cases the custom handler may even access other YODEL-based Web services to validate data).
  • Extend YODEL's built in datatypes with more specific types. For example a Java-based application may wish to specifically define float vrs double numeric types.
  • Return a custom or platform-specifc object rather than simply returning an "object" or an "array". The ColdFusion platform, for example, features the concept of a RecordSet ("Query") object. Custom handlers may be created to convert ColdFusion queries to a specially-defined "RecordSet" JavaScript object.
  • Launch any other processing or data parsing that might be needed based on the value of the attribute. Although it's generally not recommended to muddy the parsing process anything that can be done in JavaScript can be done using custom handlers.

23 Current Sessions; Time: 01:55:42 22-11-2008; Tick: 484