DP_YODEL ColFusion Component
Download | Revision History | Usage | Methods | Examples
The DP_YODEL ColdFusion Component provides ColdFusion 7+ 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 CFC supports a simple method of parsing custom datatypes using the YODEL custom attribute and user-defined custom data handlers. Several default handlers (which may be over-ridden by the user) are provided.
- The CFC supports XSD validation via the isYODEL() and validate() methods.
- The library supports two-styles of serialization and automatic metadata generation for CFML queries.
You can also find out more about the YODEL specification.
This component requires ColdFusion 7.x (or better). All downloads and code are covered by our Source Code Policy.
DP_YODEL.zip, 9.99kb Zip-Format Archive
October 30, 2005
The library consists of a single ColdFusion Component, DP_YODEL.cfc.
Using the Library
The library must be made available for use. See http://livedocs.macromedia.com for information on using and accessing CFCs.
Once the library has been made accessible you can access it as any CFC using the CreateObject() function, the <cfobject> or the <cfinvoke> tag. For example:
See the Methods section for full details.
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 CFML's error handling capacity and wrap all of your YODEL processing in a <cftry> 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 DP_YODEL will almost certainly (due to the endless loop being created) result in an application crash.
When creating Query objects using the QueryNew() function it is recommended to always use the columntypelist parameter. This allows the serializer to automatically generate metadata for your query which can greatly reduce the resulting packet size.
Following are methods available in the DP_YODEL component:
Note that in method/function signatures a pipe ("|") indicates "OR" while arguments in square brackets are optional.
isYodel()
Determines if a passed value is a valid YODEL packet.
Method Signature
isYodel(XMLDoc)
Arguments
- XMLDoc: Required. The value to examine.
Return
Boolean. "True" if the passed value is a valid YODEL packet, "false" if not.
validateYODEL()
Validates a YODEL packet using the YODEL XSD.
Method Signature
validateYodel(XMLDoc)
Arguments
- XMLDoc: Required. The value to validate.
Return
Struct. Returns the same validation information structure as the XMLValidate() function.
serialize()
Serializes a native CFML date item into a YODEL packet (converts native CFML data to YODEL).
If datatype information is available for queries (true for most database queries and developer-defined queries which use the "columntypelist" attribute of the QueryNew() function) YODEL metadata for the query will be automatically generated.
Method Signature
serialize(Input, [QueryStyle], [TimeStyle], [XSDURL])
Arguments
- Input: Any Type, Required. The value to serialize.
- QueryStyle: String ("cols" or "rows"), Optional. Determines the way queries will be serialized: either "cols" (the default, serializes to an object of arrays, one array for each column of the query) or "rows" (serializes to an array of objects, an object for each row of the query). Serialized query nodes will be assigned YODEL custom data type labels of "recordsetByCols" or "recordsetByRows" depending on the value of this attribute. Note that column order can only be maintained properly using the "cols" setting.
- TimeStyle: String ("offset", "local" or "utc"), Optional. Determines the method for specifying times. "offset" (the default, includes timezone offset), "local" (no timezone offset), "utc" (adds the UTC indicator). Note that no time conversion will take place, this parameter only specify the iso8601 format to use.
- XSDURL: String (a URL), Optional. The URL to the YODEL XSD if you wish the reference to be included in the results.
Return
Struct. Returns the same validation information structure as the XMLValidate() function.
deserialize()
Deserialize a YODEL packet into native CFML data.
Method Signature
validateYodel(XMLDoc)
Arguments
- Input: String (a YODEL packet), Required. The XML packet to deserialize.
- CustomHandlers: Struct, Optional. A structure containing custom handler functions. Three default custom handlers are always included in the process (unless overridden by the developer) these are: "recordsetByRows" and "recordsetByCols" (both convert to a CFML query object) and "GUID" (validates the data format as CFML GUID). See the Examples section for more details.
Return
Struct. Returns the same validation information structure as the XMLValidate() function.
For examples of YODEL and information about how to use it see the YODEL Information available.
Serialization
Here are examples of calling the CFC to serialize native CFML data to YODEL (note these examples assume the CFC is in the same directory as the calling template):
<cfinvoke component="DP_YODEL" method="serialize" Input="#myData#" returnvariable="foo" />
<cfset foo = CreateObject("Component", "DP_YODEL").serialize(myData) />
Deserialization
Examples of calling the CFC to deseerialize a YODEL packet into native CFML data:
<cfinvoke component="DP_YODEL" method="deserialize" Input="#myYODEL#" returnvariable="foo" />
<cfset foo = CreateObject("Component", "DP_YODEL").deserialize(myYODEL) />
Using Custom Handlers
By using the CustomHandlers feature of the DP_YODEL CFC 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. DP_YODEL processes custom handlers as follows:
- The parser first deserializes the node normally using the standard datatype provided.
- 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".
- The parser passes two parameters to the custom handler: "Input" (the current, deserialized data) and "CurFields" (the field list for objects, empty for other values).
- The custom handler performs its processing.
- 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) the two parameters "Input" and "CurFields" (although the latter may be ignored if not required).
- They must return the value to be included in the deserialized data.
The DP_YODEL CFC contains three default custom handlers. These may be overridden by the user if desired. They are:
- recordsetByRows: Converts parsed data to a CFML query object.
- recordsetByCols: Converts parsed data to a CFML query object.
- guid: Ensures that the data is in the format of a CFML GUID.
To create a CustomHandlers structure 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 a user-defined function. This struct may contain any number of custom handlers (although of course each one must be linked to a unique name):
<cfset CustomHandlers = StructNew()>
<cfset CustomHandlers.myCustomDataType = MyCustomFunction>
With the above code whenever the parser encounters a custom value of "myCustomDataType" it will first deserialize the value as its standard YODEL type and then pass the result to the MyCustomFunction() function. The results of the function will then appear in the deserializer output. Note defining custom handlers for any of the default data types ("recordsetByRows", "recordsetByCols" or "guid") will override the default handling of that type.
Once you've generated all of your custom code and created the CustomHandlers struct you can call deserializer like so:
<cfset foo = CreateObject("Component", "DP_YODEL").deserialize(myYODEL, CustomHandlers) />
Using custom handlers developers might:
- Validate the value provided to ensure that it's follows some defined format (as is done in the guid default handler). Since the custom handler can perform any processing the validations required can be as complex as required.
- 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. You can then define CFML custom handlers to treat these types differently.
- Return a custom or platform-specifc object rather than simply returning an "object" or an "array". This is what's done with Query objects by default. Custom handlers can also be constructed to convert certain data to CFC instances or other custom data containers.
- 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 any functionality possible can be linked using custom handlers.