JavaFXComposerQLExamples
JavaFX Composer Data Sources Query Language Examples
This page explains the query language used by the JavaFX Composer Data Sources framework on examples. Examples are divided into two groups. One group shows how to query data coming from XML and the other shows querying data originating from JSON. Strictly speaking, query language itself is the same for both but there are some semantic nuances that you should be aware of. Most of these differences arise from the fact that XML uses elements and attributes while JSON uses only attributes (class fields) and arrays. Both examples uses roughly the same data, a small bookstore structure, just to demonstrate how data is organized in RecordSet and Record structures.
All textual representations of RecordSets on this page are produced by calling the dump() method on them.
var rs : RecordSet;
rs.dump();
XML
Original source of data
<?xml version='1.0' encoding='UTF-8'?>
<bookstore>
<location>
<address street="V Parku 10" city="Prague" country="Czech Republic" zip="14800"/>
<phone>4208827618</phone>
<email>books@books.cz</email>
</location>
<books>
<book>
<title lang="en">Universe</title>
<author>J.P. Smith</author>
</book>
<book >
<title lang="en">Dogs</title>
<author>Robert Clown</author>
</book>
<book>
<title lang="en">Birds</title>
<author>Laura Keys</author>
</book>
</books>
</bookstore>
rs - original RecordSet without filtering
| Result
| Type
| Notes
|
ROOT = RECORDSET [
RECORD {
.elements = RECORDSET [
RECORD {
.elements = RECORDSET [
RECORD {
zip: 14800
street: V Parku 10
.name: address
city: Prague
country: Czech Republic
}
RECORD {
.text: 4208827618
.name: phone
}
RECORD {
.text: books@books.cz
.name: email
}
]
.name: location
}
RECORD {
.elements = RECORDSET [
RECORD {
.elements = RECORDSET [
RECORD {
.text: Universe
.name: title
}
RECORD {
.text: J.P. Smith
.name: author
}
]
.name: book
}
RECORD {
.elements = RECORDSET [
RECORD {
.text: Dogs
.name: title
}
RECORD {
.text: Robert Clown
.name: author
}
]
.name: book
}
RECORD {
.elements = RECORDSET [
RECORD {
.text: Birds
.name: title
}
RECORD {
.text: Laura Keys
.name: author
}
]
.name: book
}
]
.name: books
}
]
.name: bookstore
}
]
| RecordSet
| Notice how XML data maps to RecordSet structure. Attributes are placed directly in a Record's fields while child XML elements are stored in a special field called ".elements" as a RecordSet.
|
rs.filter("location")
| Result
| Type
| Notes
|
ROOT = RECORDSET [
RECORD {
.elements = RECORDSET [
RECORD {
zip: 14800
street: V Parku 10
.name: address
city: Prague
country: Czech Republic
}
RECORD {
.text: 4208827618
.name: phone
}
RECORD {
.text: books@books.cz
.name: email
}
]
.name: location
}
]
| RecordSet
| An anternative would be calling rs.filter("/bookstore/location"). The root element "bookstore" is optional.
|
rs.filter("location/address")
| Result
| Type
| Notes
|
ROOT = RECORDSET [
RECORD {
zip: 14800
street: V Parku 10
.name: address
city: Prague
country: Czech Republic
}
]
| RecordSet
| .name" holds an XML element's name, all other fields are XML element's attributes. Notice that there is no ".text" field because this element has no body (inner text)
|
rs.eval("location/address/@city")
| Result
| Type
| Notes
|
"Prague"
| String
| Notice the use of "at sign" in the query string. This is because XML distinguishes elements and attributes and the query string evaluator needs to know whether to look for a field named "city" in the current Record or look for a Record with a field ".name" containing "city" in the ".elements" RecordSet.
|
rs.eval("location/email")
| Result
| Type
| Notes
|
"books@books.cz"
| String
|
|
rs.filter("books/book[0]/title")
| Result
| Type
| Notes
|
ROOT = RECORDSET [
RECORD {
.text: Universe
.name: title
}
]
| RecordSet
| ".text" field holds an XML element's inner text, ".name" holds an XML element's name
|
rs.eval("books/book[0]/title")
| Result
| Type
| Notes
|
"Universe"
| String
|
|
JSON
Original source of data
{
"location": {
"address" : {
"street" : "V Partku 10",
"city" : "Prague",
"country" : "Czech Republic",
"zip" : "14800"
},
"phone" : "4208827618",
"email" : "books@books.cz"
},
"books" : [
{
"title" : "Universe",
"author" : "J.P. Smith"
},
{
"title" : "Dogs",
"author" : "Robert Clown"
},
{
"title" : "Birds",
"author" : "Laura Keys"
}
]
}
rs - original RecordSet without filtering
ROOT = RECORDSET [
RECORD {
books = RECORDSET [
RECORD {
author: J.P. Smith
title: Universe
}
RECORD {
author: Robert Clown
title: Dogs
}
RECORD {
author: Laura Keys
title: Birds
}
]
location = RECORD {
phone: 4208827618
email: books@books.cz
address = RECORD {
zip: 14800
street: V Partku 10
country: Czech Republic
city: Prague
}
}
}
]
rs.filter("location/address")
| Result
| Type
| Notes
|
ROOT = RECORDSET [
RECORD {
zip: 14800
street: V Partku 10
country: Czech Republic
city: Prague
}
]
| RecordSet
|
|
rs.filter("location/address/zip")
| Result
| Type
| Notes
|
ROOT = RECORDSET [
RECORD {
zip: 14800
}
]
| RecordSet
| Notice the difference between eval and filter methods.
|
rs.eval("location/address/zip")
| Result
| Type
| Notes
|
"14800"
| String
| The same result can be achieved by calling rs.filter("location/address/zip").currentString("zip") or rs.filter("location/address").currentString("zip")
|