The Problem
You want to create your own XML object to store data in. Perhaps to be passed to a Javscript AJAX handler or another service. You can do this in Obyx by simply constructing your object and referencing it using xpath.
A Simple Example
In this example, we're using Obyx to return an XML object to a javascript AJAX handler. The javascript is expecting an XML object in a particular format as shown below. Note that the message element contains an HTML fragment. This is just to make the example more interesting!
Example response object:
<response>
<success>YES</success>
<message>
<div>
Your changes were saved <strong>successfuly</strong>
</div>
</message>
</response>
In order to demonstrate this example we need three files:
message.xml: A simple HTML message for use as an example
object.xml: Our object template
custom.obyx: The Obyx file we'll be using to test
The first two files are simply resources and are shown below:
message.xml:
<!DOCTYPE div PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<div xmlns="http://www.w3.org/1999/xhtml">
Your changes were saved <strong>successfuly</strong>
</div>
object.xml:
<response>
<success><!-- success code here --></success>
<message><!-- message here --></message>
</response>
Using The Object
Our example first loads the object template from file into a store called
xmlobject. We then populate this with our values (a strong and an HTML fragment from a file) before finally outputting to screen.
custom.obyx:
<instruction xmlns="http://www.obyx.org">
<input>
<!-- Load the object template -->
<instruction>
<output space="store" value="xmlobject" />
<input space="file" value="object.xml" />
</instruction>
<!-- Populate the object -->
<instruction>
<output space="store" value="xmlobject#//success/comment()" />
<input value="YES" />
</instruction>
<instruction>
<output space="store" value="xmlobject#//message/comment()" />
<input space="file" value="message.xml"/>
</instruction>
<!-- Output the object -->
<instruction>
<input space="store" value="xmlobject" />
</instruction>
</input>
</instruction>
This returns the following result:
<response>
<success>YES</success>
<message>
<div xmlns="http://www.w3.org/1999/xhtml">Your changes were saved
<strong>successfuly</strong>
</div>
</message>
</response>
As you can see, using custom XML objects is pretty straightforward. However this example is not so great as the object is not name spaced, meaning its difficult to use it in Obyx after creation. Also if OBYX_VALIDATE_ALWAYS is set then you will get errors with validation of the object. To solve these issues and improve the object you should create a grammar to accompany it.
Validated Custom XML Objects
In order to validate a custom XML object you need to specify a grammar. If the object is an XHTML fragment then you simply need to include the DOCTYPE and xmlns directives for XHTML. However, if its your own object then you shall need to create your own grammar to accompany the object. The benefit of producing a grammar such as this is that it allows your to ensure your objects are valid and well formed.
Creating The Grammar Schema
Schemas are relatively easy to create. They allow you to specify how the XML object should be used. We'll be creating a grammar schema for object.xml as listed above.
object.xsd:
<schema xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:j="http://www.your-url-here.net/jsresult"
elementFormDefault="qualified" attributeFormDefault="unqualified"
targetNamespace="http://www.your-url-here.net/jsresult">
<element name="response" >
<complexType mixed="false">
<sequence>
<element name="success" minOccurs="1" maxOccurs="1" type="string" />
<element name="message" minOccurs="1" maxOccurs="1" type="j:xmlfragment" />
</sequence>
</complexType>
</element>
<!-- a generic type for allowing XHTML fragments -->
<complexType name="xmlfragment" mixed="false">
<sequence minOccurs="0" maxOccurs="unbounded">
<any namespace="##other" processContents="lax"/>
</sequence>
</complexType>
</schema>
This schema is very basic, but extensible. Essentially we define one containing element
response, within this we define a sequence of elements that must appear:
success and
message. (You could use
choice instead of
sequence if you dont care about the order of the elments in your object.)
Here you may also see that we have abstracted out the type "xmlfragment". This allows us to specify as many elements as we like all using the same type. The success element is simply of type string.
Using the Grammar Schema
To use the schema, you need to tell Obyx where the schema is and how you wish to reference it. This is done with two simple instructions, one to load the grammar, the other to link it to the namespace (we've chosen 'jr' in this example)
<instruction>
<output space="grammar" value="http://www.your-url-here.net/jsresult" />
<input space="file" value="object.xsd" />
</instruction>
<instruction>
<output space="namespace" value="jr" />
<input value="http://www.your-url-here.net/jsresult" />
</instruction>
Putting it all together
customvalid.obyx:
<instruction xmlns="http://www.obyx.org">
<input>
<!-- Load the grammar schema -->
<instruction>
<output space="grammar" value="http://www.your-url-here.net/jsresult" />
<input space="file" value="object.xsd" />
</instruction>
<!-- Assign the name space -->
<instruction>
<output space="namespace" value="jr" />
<input value="http://www.your-url-here.net/jsresult" />
</instruction>
<!-- Load the object template -->
<instruction>
<output space="store" value="xmlobject" />
<input space="file" value="object.xml" />
</instruction>
<!-- Populate the object -->
<instruction>
<output space="store" value="xmlobject#//jr:success/comment()" />
<input value="YES" />
</instruction>
<instruction>
<output space="store" value="xmlobject#//jr:message/comment()" />
<input space="file" value="message.xml"/>
</instruction>
<!-- Output the object -->
<instruction>
<input space="store" value="xmlobject" />
</instruction>
</input>
</instruction>
Note that the XPaths now include the
jr reference. Be sure to add the namespace into the object template so that the XPaths work, as below:
<response xmlns="http://www.your-url-here.net/jsresult">
<success><!-- success code here --></success>
<message><!-- message here --></message>
</response>
Last Modified: Thu, 15 Jan 2015