Table of Contents
As far as importing data into an LZX app is concerned, we always work in XML. The XML declaration is not required, but a single
root XML node is. Data is represented by the <dataset>
element.
Example 11.1. Datasets
<canvas height="80" width="500" > <dataset name="myData"> <myXML> <person show="simpsons"> <firstName>Homer</firstName> <lastName>Simpson</lastName> </person> <person show="simpsons"> <firstName>Marge</firstName> <lastName>Simpson</lastName> </person> <person show="simpsons"> <firstName>Montgomery</firstName> <lastName>Burns</lastName> </person> </myXML> </dataset> <text datapath="myData:/myXML[1]/person[1]/firstName[1]/text()"/> </canvas>
In the above example, the single root element is myXML. The datapath
attribute of the <text>
tag binds it to the data.
Datapaths use XPath attributes to navigate through the XML data. So the name of the dataset to use goes before the colon myData:
, followed by the nodes, separated by forward slashes (/). The square brackets provide a (one-based) space to enter which
sibling node we want.
In plain English, the above example says: "get me the text from the first firstName node, of the first person node of the first (and of course, only) myXML node." The text() method call returns that node's text.
To get Marge's name, we could rewrite the <text>
tag as follows:
<text datapath="myData:/myXML/person[2]/firstName/text()" />
To get the "show" attribute of Montgomery, we could write:
<text datapath="myData:/myXML/person[3]/@show" />
The /text()
path segment is unnecessary with the
datapath
attribute.
So far we've used the <text>
tag in conjunction with a single datapath. If we wanted to present tabular information, this would mean each text element
would need its own datapath, and would be cumbersome and difficult to write. Instead let's make a quick table, by giving a
<view>
a datapath:
Example 11.2. Assigning a datapath to a view
<canvas height="80" width="500"> <dataset name="myData"> <myXML> <person show="simpsons"> <firstName>Homer</firstName> <lastName>Simpson</lastName> </person> <person show="simpsons"> <firstName>Marge</firstName> <lastName>Simpson</lastName> </person> <person show="simpsons"> <firstName>Montgomery</firstName> <lastName>Burns</lastName> </person> </myXML> </dataset> <view name="rowOfData" datapath="myData:/myXML[1]/person[1]"> <simplelayout axis="x" /> <text datapath="firstName/text()" /> <text datapath="lastName/text()" /> <text datapath="@show" /> </view> </canvas>
The datapath of the entire rowOfData
view has now become Homer's person
node. The child elements of rowOfData
inherit this, so their datapaths can be referenced relatively.
In the above example we used a single rowOfData
node. Next, we shall use a range of nodes:
Example 11.3. Range of nodes
<canvas height="80" width="500" > <dataset name="myData"> <myXML> <person show="simpsons"> <firstName>Homer</firstName> <lastName>Simpson</lastName> </person> <person show="simpsons"> <firstName>Marge</firstName> <lastName>Simpson</lastName> </person> <person show="simpsons"> <firstName>Montgomery</firstName> <lastName>Burns</lastName> </person> </myXML> </dataset> <view name="myTable"> <simplelayout axis="y" /> <view name="rowOfData" datapath="myData:/myXML[1]/person"> <simplelayout axis="x" /> <text datapath="firstName/text()" /> <text datapath="lastName/text()" /> <text datapath="@show" /> </view> </view> </canvas>
Whichever tag contains the datapath
attribute will get repeated as often as is necessary.
Remember that datapaths bind themselves to a view, so if the data changes, so will the view. We shall come to that a little later.
So far we've been using embedded data; i.e. XML that is written into the document. This is fine for very small amounts of static data, but there are other methods better suited to larger (or dynamic) data.
How is it included? | When is it loaded? | Syntax |
---|---|---|
Embedded | Compile-time |
<dataset name="myData"> <myXML> <!-- ... other XML tags ... --> </myXML> </dataset> |
Included | Compile-time |
<dataset name="myData" src="myXMLDoc.xml"/> |
HTTP data | Runtime |
<dataset name="myData" request="true" type="http" src="myXMLDoc.xml" /> |
Embedded data is XML between the <dataset>
tags. When the OpenLaszlo Server compiles the application, the data is bound into it. The data can still be changed after
the application runs. Included data is static.
Included data is essentially the same as embedded data, except that the XML itself is kept in a separate file. The size of the initial download will be the same as with embedded data.
It is locally referenced via the filesystem, so it can be placed in other directories. Included data is static.
Remote data goes over HTTP, which means it can (but doesn't have to) be dynamic. If it is static, then the only difference
between it and included or embedded data is that it is downloaded after the application loads. The type="http"
attribute indicates that this is an HTTP request. The requests can be either GET or POST.
There are several points at which the client requests the data:
The client will request the data as soon as the app loads if the dataset's request
attribute is true.
If the request
attribute is set to "true", the client will also request the data every time the querystring or base URL of the dataset changes
(using the setQueryString()
or setSrc()
respectively) methods of the LzHTTPDataset object.
In the table above, we referenced a file locally (myXMLDoc.xml), but we could have done it absolutely, or we could have hit
a server-side (PHP, ASP, JSP or some CGI) that returned an XML document. We could add the query string to the <dataset>
tag:
<dataset name="myData"
src="http://www.myServer.com/cgi-bin/myXMLDoc.cgi?return=addresses"/>
The type="http"
attribute gets implied when the src
attribute contains "http://
".
Datapaths are extremely handy, but if you need more control over the data, they can become cumbersome. Datapaths are actually extensions of datapointers, but are easier to learn, which is why we introduced them first. A datapointer is a pointer into the dataset, which can be moved around. It can only be in one place of the dataset at a time, but you can have multiple datapointers, each pointing to a different part of a dataset.
Datapointers are not bound to views like datapaths are, but they do have a place in the view hierarchy (i.e. they know about parents and children).
You will use a datapointer when you need to operate on the data in some way. For example, using the same format of data as in the previous examples, say you wanted to find all the people who were in the South Park show:
Example 11.4. Manipulating datapointers
<canvas height="180" width="500" debug="true"> <dataset name="myData" src="../myShowData.xml" /> <datapointer xpath="myData:/" ondata="processData()"> <method name="processData"> this.selectChild(2); do { if (this.xpathQuery( '@show' ) == 'south park') { Debug.write(this.xpathQuery('firstName/text()')); } } while (this.selectNext()); </method> </datapointer> </canvas>
For brevity's sake, we are writing to the debugger, and we are including the data from a local file. You can download that XML file at http://www.openlaszlo.org/lps-latest/docs/guide/myShowData.xml.
The first selectNext(2)
method call selects first the <myXML>
node, then the South Park <person>
node. It selects two because of the depth argument "2" we pass it (otherwise it would default to 1.
The other selectNext
method call returns true
as long as an XML node was successfully selected (i.e. until there aren't any more). We exploit this by using it in a do
loop, so that the same iteration occurs for every …
while<person>
node.
We could also have given the <datapointer>
onerror
and ontimeout
event handlers to capture any problems.
Copyright © 2002-2007 Laszlo Systems, Inc. All Rights Reserved. Unauthorized use, duplication or distribution is strictly prohibited. This is the proprietary information of Laszlo Systems, Inc. Use is subject to license terms.