Skip to content

Instantly share code, notes, and snippets.

@r-lyeh
Last active March 7, 2020 09:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save r-lyeh/28b45725a11b452c831cd29bc92c3d97 to your computer and use it in GitHub Desktop.
Save r-lyeh/28b45725a11b452c831cd29bc92c3d97 to your computer and use it in GitHub Desktop.

QueryData (QD)

A Query Data specification that resembles files and directories.

C API

char *result = qd_query(doc,"query");           // Return a single value from your data
array(char*) result = qd_queries(doc,"query");  // Return a result set from your data (array)

Operators

Operators Description
. The current element
.. The parent of current element
/ The root element
// Recursive descent.
*? Wildcards. Available anywhere a name or numeric are required.
child/ or [child] Child operator (also array index operator)
[,] Union operator, allows alternate names or array indices as a set.
[start:end] Array slice operator
$child Convert child to string
#child Convert child to number

Filters

Filters Description
== left is equal to right (note that 1 is not equal to '1')
!= left is not equal to right
< left is less than right
<= left is less than or equal to right
> left is greater than right
>= left is greater than or equal to right
=~ left matches regular expression name =~ /foo*/
=~~ left matches regular expression name =~~ /foo*/ (case insensitive)
- + - * div mod left and right arithmetical operation (double)
in left exists in right
nin left does not exists in right
subsetof left is a subset of right
anyof left has an intersection with right
noneof left has no intersection with right
empty left (array or string) should be empty
and && or || not ! @todo
() grouping @todo

LINQ functions

  • Valid syntax: function(element), function(set) or set.function()
  • function(element) operates on single element.
  • function(set) operates on first element of set. Equivalent to function(set[0]).
  • set.function() operates on all elements in set. Used for chaining (eg set.function1().function2().function3())
Prepare LINQ Description
from(source) Continues if selection exists.
Debugging LINQ Description
debug(bool) Continues into debug mode
print() Continues after printing current query
break() Continues after user agrees on debugger.
Filtering LINQ Description
where(query) Continues if expression matches.
==(query) Continues if two fields are equal
<(query) Continues if A is less than B.
>(query) Continues if A is greater than B.
<=(query) Continues if A is less than or equal to B.
>=(query) Continues if A is greater than or equal to B.
between(query) Continues if A belongs to (B,C) range.
range(query) Continues if A belongs to [B,C] range.
empty(query) Continues if A is empty.
in(query) Continues if A is in B.
contains(query) Continues if B is in A. find(B) instead?
startsWith(query) Continues if the first element in A vgfbvis equal to B
endsWith(query) Continues if the last element in A is equal to B
and(action) Continues if A was true
or(action) Continues if A was false, else skip next chained LINQ
Result LINQ Description
any(selection) Continues if any of A matched the query
all(selection) Continues if all of A matched the query
none(selection) Continues if none of A matched the query
Action LINQ Description
each(action) Continues after executing action to each A record
attach(selection) Continues after attaching a property to each A record
detach(selection) Continues after detaching a property from each A record
Grouping LINQ Description
subtract(selection) Continues after removing all A present in B values (difference:123-234=1)
unique(selection) Continues after extracting distinct A and B values (symmetric difference:123^234=14)
shared(selection) Continues after extracting repeated A and B values (intersection:123&234=23)
join(selection) Continues after merging A and B both together (union:123+234=1234)
Ordering LINQ Description
reverse(bool) Continues after reversing ordering logic.
sort(pred) Continues after sorting by predicate.
shuffle(N) Continues after shuffling N elements.
at(selection) Continues after selecting the element at the specified index (allows a default match if nothing is found).
last(selection) Continues after selecting the last match of the set (allows a default match if nothing is found).
first(selection) Continues after selecting the first match of the set (allows a default match if nothing is found).
others(selection) Continues after selecting all elements but the first excluded.
Stack LINQ Description
push() Continues after pushing current LINQ into stack for further usage
use(N) Continues after using Nth query from stack
pop() Continues after popping current LINQ from stack
Conversion LINQ Description
select(record,...) Returns A as array of matching records.
string() Returns A as string.
number() Returns A as number.
bool() Returns A as bool.
type() Returns A type.
Numerical LINQ Description
min() Returns minimum value of A (as double)
max() Returns maximum value of A (as double)
avg() Returns average value of A (as double)
sdv() Returns standard deviation value of A (as double)
sum() Returns sum value of A (as double)
floor() Returns floor value of A (as double)
ceil() Returns ceil value of A (as double)
round() Returns round value of A (as double)
count() Returns total records found in A (as integer)
String LINQ Description
case(bool) Makes string comparisons and search case sensitive or not.
matches(query) Continues if A matches regular expression of B. Allows wildcards.
begins() Continues if A starts with B
ends() Continues if A ends with B
finds() Continues if A is found in B
cat(B) Returns concatenated A and B strings
sub(start [,count]) Returns substring of A "1999/04/01".sub(5,2) -> "04"
left(B) Returns left of A after first B find "1999/04/01".left("/") -> "1999"
right(B) Returns right of A after first B find "1999/04/01".right("/") -> "04/01"
len() Returns number of characters in A
trim() Returns trimmed A of leading/trailing/in-between whitespaces excesses.
map(src,dst) Returns remapped A string "--bar123--".map("abc-","ABC") -> "BAr123"
lower() Returns A in lowercase
upper() Returns A in UPPERCASE
camel() Returns A in camelCase

Demo: data

{
    "store": {
        "book": [
            {
                "category": "reference",
                "author": "Nigel Rees",
                "title": "Sayings of the Century",
                "price": 8.95
            },
            {
                "category": "fiction",
                "author": "Evelyn Waugh",
                "title": "Sword of Honour",
                "price": 12.99
            },
            {
                "category": "fiction",
                "author": "Herman Melville",
                "title": "Moby Dick",
                "isbn": "0-553-21311-3",
                "price": 8.99
            },
            {
                "category": "fiction",
                "author": "J. R. R. Tolkien",
                "title": "The Lord of the Rings",
                "isbn": "0-395-19395-8",
                "price": 22.99
            }
        ],
        "bicycle": {
            "color": "red",
            "price": 19.95
        }
    },
    "expensive": "10"
}

Demo: queries

Query Result
/store/book[*]/author The authors of all books in the store
//author All authors in document
//* All elements in document
/store/* All things in store, which are some books and a red bicycle
/store//price The price of everything in the store.
//book[2] The third book
//book[0,1] The first two books
//book[1:2] Second and third books (from index 1 (inclusive) until index 2 (exclusive))
//book[2:] All books from index 2 (inclusive) till end
//book[:2] The first two books (from index 0 (inclusive) until index 2 (exclusive))
//book[-2] The second to last book
//book[-2:] Last two books
//book[-1:] The last book
//book[isbn] All books with an ISBN number
//book[price<10] All books in store cheaper than 10
//book[price <= #expensive] All books in store that are not "expensive" (see # to number operator)
//book[author =~ //*REES/] All books matching regex
//category All categories
//category[2] 'fiction'
//book/*[1]/category 'fiction'
/book[2]/category 'fiction'
//book/*[2] Objects
count(//book) The number of books
count(//category) 2
count(//book//*) 2
type(//book/*[2]/title) 'string'
type(*/*[2]/price) 'number'
len(//book/*[2]/title) 9
p[x] Selects all P elements with a child named X, in current element.
//p[x] Selects all P elements with a child named X, in current document.
//item[price > 2*discount] Selects all items whose price child is greater than twice their discount child.
v[x or y] | w[z] Selects all V elements with X or Y child-elements, and all W elements with Z child-elements, that were found in the current context.
a[1][href=='help.php'] Selects a match only if the first A child of the context node satisfies the condition HREF='HELP.PHP', while
a[href=='help.php'][0] Selects the first A child that satisfies this condition.
a[/html/lang=='en'][href=='help.php'][0]/target Selects the value of the TARGET child of the first A element among the children of the context node that has its HREF child set to HELP.PHP, provided the document's html top-level element also has a LANG child set to EN.
from(//records).reverse(1).sort(name) @todo
from(//records).join(//data/locations).sort(/location/city) @todo
from(/data/emails).match("@.com").any() @todo
from(/data/fruits).startsWith("s").or().startsWith("m").count() @todo
from(/data/fruits).case(0).equals("STRAWBERRY").count() @todo

Changelog

  • v0.0.0 xxxx/xx/xx first draft

Credits

  • Grabbed ideas and samples from XPath, JsonPath and Jsel READMEs.
  • Additional work by @r-lyeh.

License

  • QueryData (QD) spec dual licensed into the public domain and CC0.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment