Skip to content

Instantly share code, notes, and snippets.

@r-lyeh
Last active March 7, 2020 09:50

Revisions

  1. r-lyeh revised this gist Mar 7, 2020. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions QueryData.md
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    # QueryData
    # QueryData (QD)
    A Query Data specification that resembles files and directories.

    ## C API
    @@ -251,4 +251,4 @@ array(char*) result = qd_queries(doc,"query"); // Return a result set from your
    - Additional work by @r-lyeh.

    ## License
    - QueryData spec dual licensed into the public domain and CC0.
    - QueryData (QD) spec dual licensed into the public domain and CC0.
  2. r-lyeh revised this gist Mar 7, 2020. 1 changed file with 10 additions and 7 deletions.
    17 changes: 10 additions & 7 deletions QueryData.md
    Original file line number Diff line number Diff line change
    @@ -44,9 +44,9 @@ array(char*) result = qd_queries(doc,"query"); // Return a result set from your
    ## LINQ functions
    - Valid syntax: `function(element)`, `function(set)` or `set.function()`
    - `function(element)` evaluates on single element.
    - `function(set)` evaluates to first element of set. Equivalent to `function(set[0])`.
    - `set.function()` evaluates to all elements in set. Used for chaining (eg `set.function1().function2().function3()`)
    - `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 |
    | ---: | :--- |
    @@ -74,7 +74,7 @@ array(char*) result = qd_queries(doc,"query"); // Return a result set from your
    |[startsWith(query) ](https://#)|Continues if the first element in A vgfbvis equal to B
    |[endsWith(query) ](https://#)|Continues if the last element in A is equal to B
    |[and(action) ](https://#)|Continues if A was true
    |[or(action) ](https://#)|Continues if A was false, else skip next chained linq
    |[or(action) ](https://#)|Continues if A was false, else skip next chained LINQ
    ||
    ||
    | **Result LINQ** | Description |
    @@ -113,7 +113,7 @@ array(char*) result = qd_queries(doc,"query"); // Return a result set from your
    ||
    ||
    | **Conversion LINQ** | Description |
    |[select(record,...) ](https://#)|Returns array of matching records.
    |[select(record,...) ](https://#)|Returns A as array of matching records.
    |[string() ](https://#)|Returns A as string.
    |[number() ](https://#)|Returns A as number.
    |[bool() ](https://#)|Returns A as bool.
    @@ -243,9 +243,12 @@ array(char*) result = qd_queries(doc,"query"); // Return a result set from your
    |[from(/data/fruits).startsWith("s").or().startsWith("m").count() ](https://#)|@todo
    |[from(/data/fruits).case(0).equals("STRAWBERRY").count() ](https://#)|@todo

    ## Changelog
    - v0.0.0 xxxx/xx/xx first draft

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

    ## License
    - Data-query spec dual licensed into the public domain and CC0.
    - QueryData spec dual licensed into the public domain and CC0.
  3. r-lyeh revised this gist Mar 7, 2020. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions QueryData.md
    Original file line number Diff line number Diff line change
    @@ -186,7 +186,7 @@ array(char*) result = qd_queries(doc,"query"); // Return a result set from your
    "price": 19.95
    }
    },
    "expensive": 10
    "expensive": "10"
    }
    ```

    @@ -209,7 +209,7 @@ array(char*) result = qd_queries(doc,"query"); // Return a result set from your
    |[//book[-1:] ](https://#)|The last book
    |[//book[isbn] ](https://#)|All books with an ISBN number
    |[//book[price<10] ](https://#)|All books in store cheaper than 10
    [[//book[price <= #expensive] ](https://#)|All books in store that are not "expensive"
    |[//book[price <= #expensive] ](https://#)|All books in store that are not "expensive" (see `#` to number operator)
    |[//book[author =~ //\*REES/] ](https://#)|All books matching regex
    ||
    ||
  4. r-lyeh revised this gist Mar 7, 2020. 1 changed file with 3 additions and 2 deletions.
    5 changes: 3 additions & 2 deletions QueryData.md
    Original file line number Diff line number Diff line change
    @@ -195,7 +195,8 @@ array(char*) result = qd_queries(doc,"query"); // Return a result set from your
    | Query |Result
    |:---|:---|
    |[/store/book[\*]/author ](https://#)|The authors of all books in the store
    |[//author ](https://#)|All authors
    |[//author ](https://#)|All authors in document
    |[//\* ](https://#)|All elements in document
    |[/store/* ](https://#)|All things in store, which are some books and a red bicycle
    |[/store//price ](https://#)|The price of everything in the store.
    |[//book[2] ](https://#)|The third book
    @@ -208,7 +209,7 @@ array(char*) result = qd_queries(doc,"query"); // Return a result set from your
    |[//book[-1:] ](https://#)|The last book
    |[//book[isbn] ](https://#)|All books with an ISBN number
    |[//book[price<10] ](https://#)|All books in store cheaper than 10
    |[//\* ](https://#)|All Elements in XML document. All members of JSON structure.
    [[//book[price <= #expensive] ](https://#)|All books in store that are not "expensive"
    |[//book[author =~ //\*REES/] ](https://#)|All books matching regex
    ||
    ||
  5. r-lyeh revised this gist Mar 7, 2020. 1 changed file with 16 additions and 16 deletions.
    32 changes: 16 additions & 16 deletions QueryData.md
    Original file line number Diff line number Diff line change
    @@ -39,8 +39,8 @@ array(char*) result = qd_queries(doc,"query"); // Return a result set from your
    |[anyof ](https://#)|left has an intersection with right
    |[noneof ](https://#)|left has no intersection with right
    |[empty ](https://#)|left (array or string) should be empty
    |[and && or \|\| not ! ](https://#)|
    |[() grouping ](https://#)|
    |[and && or \|\| not ! ](https://#)|@todo
    |[() grouping ](https://#)|@todo
    ## LINQ functions
    - Valid syntax: `function(element)`, `function(set)` or `set.function()`
    @@ -139,12 +139,12 @@ array(char*) result = qd_queries(doc,"query"); // Return a result set from your
    |[ends() ](https://#)|Continues if A ends with B
    |[finds() ](https://#)|Continues if A is found in B
    |[cat(B) ](https://#)|Returns concatenated A and B strings
    |[sub(start [,count]) ](https://#)|Returns substring of A "1999/04/01".sub(5,2) -> "04"
    |[left(B) ](https://#)|Returns left of A after first B find "1999/04/01".left("/") -> "1999"
    |[right(B) ](https://#)|Returns right of A after first B find "1999/04/01".right("/") -> "04/01"
    |[sub(start [,count]) ](https://#)|Returns substring of A `"1999/04/01".sub(5,2) -> "04"`
    |[left(B) ](https://#)|Returns left of A after first B find `"1999/04/01".left("/") -> "1999"`
    |[right(B) ](https://#)|Returns right of A after first B find `"1999/04/01".right("/") -> "04/01"`
    |[len() ](https://#)|Returns number of characters in A
    |[trim() ](https://#)|Returns trimmed A of leading/trailing/in-between whitespaces excesses.
    |[map(src,dst) ](https://#)|Returns remapped A string "--bar123--".map("abc-","ABC") -> "BAr123"
    |[map(src,dst) ](https://#)|Returns remapped A string `"--bar123--".map("abc-","ABC") -> "BAr123"`
    |[lower() ](https://#)|Returns A in lowercase
    |[upper() ](https://#)|Returns A in UPPERCASE
    |[camel() ](https://#)|Returns A in camelCase
    @@ -200,9 +200,9 @@ array(char*) result = qd_queries(doc,"query"); // Return a result set from your
    |[/store//price ](https://#)|The price of everything in the store.
    |[//book[2] ](https://#)|The third book
    |[//book[0,1] ](https://#)|The first two books
    |[//book[1:2] ](https://#)|All books from index 1 (inclusive) until index 2 (exclusive)
    |[//book[1:2] ](https://#)|Second and third books (from index 1 (inclusive) until index 2 (exclusive))
    |[//book[2:] ](https://#)|All books from index 2 (inclusive) till end
    |[//book[:2] ](https://#)|All books from index 0 (inclusive) until index 2 (exclusive) *the first 2 books*
    |[//book[:2] ](https://#)|The first two books (from index 0 (inclusive) until index 2 (exclusive))
    |[//book[-2] ](https://#)|The second to last book
    |[//book[-2:] ](https://#)|Last two books
    |[//book[-1:] ](https://#)|The last book
    @@ -213,9 +213,9 @@ array(char*) result = qd_queries(doc,"query"); // Return a result set from your
    ||
    ||
    |[//category ](https://#)|All categories
    |[//category[2] ](https://#)|'Fiction'
    |[//book/\*[1]/category ](https://#)|'Fiction'
    |[/book[2]/category ](https://#)|'Fiction'
    |[//category[2] ](https://#)|`'fiction'`
    |[//book/\*[1]/category ](https://#)|`'fiction'`
    |[/book[2]/category ](https://#)|`'fiction'`
    |[//book/\*[2] ](https://#)|Objects
    ||
    ||
    @@ -236,11 +236,11 @@ array(char*) result = qd_queries(doc,"query"); // Return a result set from your
    |[a[/html/lang=='en'][href=='help.php'][0]/target](https://#)|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) ](https://#)|todo: writeme
    |[from(//records).join(//data/locations).sort(/location/city) ](https://#)|todo: writeme
    |[from(/data/emails).match("*@*.com").any() ](https://#)|todo: writeme
    |[from(/data/fruits).startsWith("s").or().startsWith("m").count() ](https://#)|todo: writeme
    |[from(/data/fruits).case(0).equals("STRAWBERRY").count() ](https://#)|todo: writeme
    |[from(//records).reverse(1).sort(name) ](https://#)|@todo
    |[from(//records).join(//data/locations).sort(/location/city) ](https://#)|@todo
    |[from(/data/emails).match("*@*.com").any() ](https://#)|@todo
    |[from(/data/fruits).startsWith("s").or().startsWith("m").count() ](https://#)|@todo
    |[from(/data/fruits).case(0).equals("STRAWBERRY").count() ](https://#)|@todo

    ## Credits
    - Grabbed ideas from XPath, JsonPath and Jsel READMEs.
  6. r-lyeh revised this gist Mar 7, 2020. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion QueryData.md
    Original file line number Diff line number Diff line change
    @@ -67,7 +67,7 @@ array(char*) result = qd_queries(doc,"query"); // Return a result set from your
    |[<=(query) ](https://#)|Continues if A is less than or equal to B.
    |[>=(query) ](https://#)|Continues if A is greater than or equal to B.
    |[between(query) ](https://#)|Continues if A belongs to (B,C) range.
    |[between=(query) ](https://#)|Continues if A belongs to [B,C] range.
    |[range(query) ](https://#)|Continues if A belongs to [B,C] range.
    |[empty(query) ](https://#)|Continues if A is empty.
    |[in(query) ](https://#)|Continues if A is in B.
    |[contains(query) ](https://#)|Continues if B is in A. find(B) instead?
  7. r-lyeh revised this gist Mar 7, 2020. 1 changed file with 9 additions and 9 deletions.
    18 changes: 9 additions & 9 deletions QueryData.md
    Original file line number Diff line number Diff line change
    @@ -219,15 +219,6 @@ array(char*) result = qd_queries(doc,"query"); // Return a result set from your
    |[//book/\*[2] ](https://#)|Objects
    ||
    ||
    |[p[x] ](https://#)|Selects all P elements with a child named X, in current context.
    |[//p[x] ](https://#)|Selects all P elements with a child named X, in any context from current.
    |[//item[price > 2\*discount] ](https://#)|Selects all items whose price child is greater than twice their discount child.
    |[v[x or y] \| w[z] ](https://#)|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'] ](https://#)|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] ](https://#)|Selects the first A child that satisfies this condition.
    |[a[/html/lang='en'][href=='help.php'][0]/target](https://#)|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.
    ||
    ||
    |[count(//book) ](https://#)|The number of books
    |[count(//category) ](https://#)|2
    |[count(//book//\*) ](https://#)|2
    @@ -236,6 +227,15 @@ array(char*) result = qd_queries(doc,"query"); // Return a result set from your
    |[len(//book/\*[2]/title) ](https://#)|9
    ||
    ||
    |[p[x] ](https://#)|Selects all P elements with a child named X, in current element.
    |[//p[x] ](https://#)|Selects all P elements with a child named X, in current document.
    |[//item[price > 2\*discount] ](https://#)|Selects all items whose price child is greater than twice their discount child.
    |[v[x or y] \| w[z] ](https://#)|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'] ](https://#)|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] ](https://#)|Selects the first A child that satisfies this condition.
    |[a[/html/lang=='en'][href=='help.php'][0]/target](https://#)|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) ](https://#)|todo: writeme
    |[from(//records).join(//data/locations).sort(/location/city) ](https://#)|todo: writeme
    |[from(/data/emails).match("*@*.com").any() ](https://#)|todo: writeme
  8. r-lyeh revised this gist Mar 7, 2020. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions QueryData.md
    Original file line number Diff line number Diff line change
    @@ -10,9 +10,9 @@ array(char*) result = qd_queries(doc,"query"); // Return a result set from your
    ## Operators
    |Operators |Description
    |---:|:---|
    |[. ](https://#)|The current object/element
    |[.. ](https://#)|Parent operator
    |[/ ](https://#)|The root object/element
    |[. ](https://#)|The current element
    |[.. ](https://#)|The parent of current element
    |[/ ](https://#)|The root element
    |[// ](https://#)|Recursive descent.
    |[\*? ](https://#)|Wildcards. Available anywhere a name or numeric are required.
    |[child/ or [child] ](https://#)|Child operator (also array index operator)
  9. r-lyeh revised this gist Mar 7, 2020. 1 changed file with 7 additions and 8 deletions.
    15 changes: 7 additions & 8 deletions QueryData.md
    Original file line number Diff line number Diff line change
    @@ -14,9 +14,8 @@ array(char*) result = qd_queries(doc,"query"); // Return a result set from your
    |[.. ](https://#)|Parent operator
    |[/ ](https://#)|The root object/element
    |[// ](https://#)|Recursive descent.
    |[child/ or [child] ](https://#)|Child operator (also array index)
    |[\*? ](https://#)|Wildcards. Available anywhere a name or numeric are required.
    |[[] ](https://#)|Subscript operator.
    |[child/ or [child] ](https://#)|Child operator (also array index operator)
    |[[,] ](https://#)|Union operator, allows alternate names or array indices as a set.
    |[[start:end] ](https://#)|Array slice operator
    |[$child ](https://#)|Convert child to string
    @@ -31,8 +30,8 @@ array(char*) result = qd_queries(doc,"query"); // Return a result set from your
    |[<= ](https://#)|left is less than or equal to right
    |[> ](https://#)|left is greater than right
    |[>= ](https://#)|left is greater than or equal to right
    |[=~ ](https://#)|left matches regular expression [name =~ /foo\*/]
    |[=~~ ](https://#)|left matches regular expression [name =~~ /foo\*/] (case insensitive)
    |[=~ ](https://#)|left matches regular expression `name =~ /foo*/`
    |[=~~ ](https://#)|left matches regular expression `name =~~ /foo*/` (case insensitive)
    |[- + - \* div mod ](https://#)|left and right arithmetical operation (double)
    |[in ](https://#)|left exists in right
    |[nin ](https://#)|left does not exists in right
    @@ -44,10 +43,10 @@ array(char*) result = qd_queries(doc,"query"); // Return a result set from your
    |[() grouping ](https://#)|
    ## LINQ functions
    - Valid syntax: function(element), function(set) or set.function()
    - function(element) evaluates on single element.
    - function(set) evaluates to first element of set. Equivalent to function(set[0]).
    - set.function() evaluates to all elements in set. Used for chaining (eg set.function1().function2().function3())
    - Valid syntax: `function(element)`, `function(set)` or `set.function()`
    - `function(element)` evaluates on single element.
    - `function(set)` evaluates to first element of set. Equivalent to `function(set[0])`.
    - `set.function()` evaluates to all elements in set. Used for chaining (eg `set.function1().function2().function3()`)
    | **Prepare LINQ** | Description |
    | ---: | :--- |
  10. r-lyeh revised this gist Mar 7, 2020. 1 changed file with 45 additions and 45 deletions.
    90 changes: 45 additions & 45 deletions QueryData.md
    Original file line number Diff line number Diff line change
    @@ -19,7 +19,6 @@ array(char*) result = qd_queries(doc,"query"); // Return a result set from your
    |[[] ](https://#)|Subscript operator.
    |[[,] ](https://#)|Union operator, allows alternate names or array indices as a set.
    |[[start:end] ](https://#)|Array slice operator
    |[@child ](https://#)|Attribute access. An attribute is some @meta info added to a document.
    |[$child ](https://#)|Convert child to string
    |[#child ](https://#)|Convert child to number
    @@ -154,39 +153,41 @@ array(char*) result = qd_queries(doc,"query"); // Return a result set from your
    ## Demo: data
    ```json
    {
    "books": [{
    "@class": "book(ssf)",
    "@category": "reference",
    "author": "Nigel Rees",
    "title": "Sayings of the Century",
    "price": 8.95
    },
    {
    "@class": "book(ssf)",
    "@category": "fiction",
    "author": "Evelyn Waugh",
    "title": "Sword of Honour",
    "price": 12.99
    },
    {
    "@class": "book(ssf)",
    "@category": "fiction",
    "author": "Herman Melville",
    "title": "Moby Dick",
    "price": 8.99
    },
    {
    "@class": "book(ssf)",
    "@category": "fiction",
    "author": "J. R. R. Tolkien",
    "title": "The Lord of the Rings",
    "price": 22.99
    "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
    }
    ],
    "bicycle": {
    "color": "red",
    "price": 19.95
    }
    },
    "expensive": 10
    }
    ```

    @@ -212,24 +213,24 @@ array(char*) result = qd_queries(doc,"query"); // Return a result set from your
    |[//book[author =~ //\*REES/] ](https://#)|All books matching regex
    ||
    ||
    |[//@category ](https://#)|All categories
    |[//@category[2] ](https://#)|'Fiction'
    |[//book/\*[1]/@category ](https://#)|'Fiction'
    |[/book[2]/@category ](https://#)|'Fiction'
    |[//category ](https://#)|All categories
    |[//category[2] ](https://#)|'Fiction'
    |[//book/\*[1]/category ](https://#)|'Fiction'
    |[/book[2]/category ](https://#)|'Fiction'
    |[//book/\*[2] ](https://#)|Objects
    ||
    ||
    |[p[@x] ](https://#)|Selects all P elements with an attribute named X, in current context.
    |[//p[@x] ](https://#)|Selects all P elements with an attribute named X, in any context from current.
    |[//item[@price > 2\*@discount] ](https://#)|Selects all items whose price attribute is greater than twice their discount attribute.
    |[p[x] ](https://#)|Selects all P elements with a child named X, in current context.
    |[//p[x] ](https://#)|Selects all P elements with a child named X, in any context from current.
    |[//item[price > 2\*discount] ](https://#)|Selects all items whose price child is greater than twice their discount child.
    |[v[x or y] \| w[z] ](https://#)|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'] ](https://#)|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] ](https://#)|Selects the first A child that satisfies this condition.
    |[a[/html/@lang='en'][@href=='help.php'][0]/@target](https://#)|Selects the value of the TARGET attribute of the first A element among the children of the context node that has its HREF attribute set to HELP.PHP, provided the document's html top-level element also has a LANG attribute set to EN.
    |[a[1][href=='help.php'] ](https://#)|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] ](https://#)|Selects the first A child that satisfies this condition.
    |[a[/html/lang='en'][href=='help.php'][0]/target](https://#)|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.
    ||
    ||
    |[count(//book) ](https://#)|The number of books
    |[count(//@category) ](https://#)|2
    |[count(//category) ](https://#)|2
    |[count(//book//\*) ](https://#)|2
    |[type(//book/\*[2]/title) ](https://#)|'string'
    |[type(\*/\*[2]/price) ](https://#)|'number'
    @@ -248,4 +249,3 @@ array(char*) result = qd_queries(doc,"query"); // Return a result set from your

    ## License
    - Data-query spec dual licensed into the public domain and CC0.

  11. r-lyeh renamed this gist Mar 7, 2020. 1 changed file with 4 additions and 4 deletions.
    8 changes: 4 additions & 4 deletions DataQuery.md → QueryData.md
    Original file line number Diff line number Diff line change
    @@ -1,10 +1,10 @@
    # Data-query
    Data-query specification that resembles files and directories.
    # QueryData
    A Query Data specification that resembles files and directories.

    ## C API
    ```C
    char *result = dq_query(doc,"query"); // Return a single value from your data
    array(char*) result = dq_queries(doc,"query"); // Return a result set from your data (array)
    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
  12. r-lyeh revised this gist Mar 6, 2020. 1 changed file with 14 additions and 14 deletions.
    28 changes: 14 additions & 14 deletions DataQuery.md
    Original file line number Diff line number Diff line change
    @@ -213,27 +213,27 @@ array(char*) result = dq_queries(doc,"query"); // Return a result set from your
    ||
    ||
    |[//@category ](https://#)|All categories
    |[//@category[2] ](https://#)|'fiction'
    |[//book/\*[1]/@category ](https://#)|'fiction'
    |[/book[2]/@category ](https://#)|'fiction'
    |[//book/\*[2] ](https://#)|objects
    |[//@category[2] ](https://#)|'Fiction'
    |[//book/\*[1]/@category ](https://#)|'Fiction'
    |[/book[2]/@category ](https://#)|'Fiction'
    |[//book/\*[2] ](https://#)|Objects
    ||
    ||
    |[p[@x] ](https://#)|selects all P elements with an attribute named X, in current context.
    |[//p[@x] ](https://#)|selects all P elements with an attribute named X, in any context from current.
    |[//item[@price > 2\*@discount] ](https://#)|selects all items whose price attribute is greater than twice their discount attribute.
    |[v[x or y] \| w[z] ](https://#)|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'] ](https://#)|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] ](https://#)|selects the first A child that satisfies this condition.
    |[a[/html/@lang='en'][@href=='help.php'][0]/@target](https://#) |selects the value of the TARGET attribute of the first A element among the children of the context node that has its HREF attribute set to HELP.PHP, provided the document's html top-level element also has a LANG attribute set to EN.
    |[p[@x] ](https://#)|Selects all P elements with an attribute named X, in current context.
    |[//p[@x] ](https://#)|Selects all P elements with an attribute named X, in any context from current.
    |[//item[@price > 2\*@discount] ](https://#)|Selects all items whose price attribute is greater than twice their discount attribute.
    |[v[x or y] \| w[z] ](https://#)|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'] ](https://#)|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] ](https://#)|Selects the first A child that satisfies this condition.
    |[a[/html/@lang='en'][@href=='help.php'][0]/@target](https://#)|Selects the value of the TARGET attribute of the first A element among the children of the context node that has its HREF attribute set to HELP.PHP, provided the document's html top-level element also has a LANG attribute set to EN.
    ||
    ||
    |[count(//book) ](https://#)|The number of books
    |[count(//@category) ](https://#)|2
    |[count(//book//\*) ](https://#)|2
    |[type(//book/\*[2]) ](https://#)|'string'
    |[type(\*/\*[2]) ](https://#)|'subData'
    |[text(\*/book/\*[2]/) ](https://#)|'val'
    |[type(//book/\*[2]/title) ](https://#)|'string'
    |[type(\*/\*[2]/price) ](https://#)|'number'
    |[len(//book/\*[2]/title) ](https://#)|9
    ||
    ||
    |[from(//records).reverse(1).sort(name) ](https://#)|todo: writeme
  13. r-lyeh revised this gist Mar 6, 2020. 1 changed file with 4 additions and 5 deletions.
    9 changes: 4 additions & 5 deletions DataQuery.md
    Original file line number Diff line number Diff line change
    @@ -236,12 +236,11 @@ array(char*) result = dq_queries(doc,"query"); // Return a result set from your
    |[text(\*/book/\*[2]/) ](https://#)|'val'
    ||
    ||
    |[from(//data/fruits).startsWith("a").or().startsWith("b").count() ](https://#)|todo: writeme
    |[from(//records).reverse() ](https://#)|todo: writeme
    |[from(//records).join(//data/locations).orderBy(/location/city) ](https://#)|todo: writeme
    |[from(//records).reverse(1).sort(name) ](https://#)|todo: writeme
    |[from(//records).join(//data/locations).sort(/location/city) ](https://#)|todo: writeme
    |[from(/data/emails).match("*@*.com").any() ](https://#)|todo: writeme
    |[from(/data/fruits).startsWith("s").or().startsWith("m").count() ](https://#)|todo: writeme
    |[from(/data/fruits).case(0).equals("STRAWBERRY").count() ](https://#)|todo: writeme
    |[from(/data/fruits).startsWith("a").union(["tomato", "carrot"]).count() ](https://#)|todo: writeme
    |[from(/data/emails).matches("*@*.com").any() ](https://#)|todo: writeme

    ## Credits
    - Grabbed ideas from XPath, JsonPath and Jsel READMEs.
  14. r-lyeh revised this gist Mar 6, 2020. 1 changed file with 8 additions and 8 deletions.
    16 changes: 8 additions & 8 deletions DataQuery.md
    Original file line number Diff line number Diff line change
    @@ -219,14 +219,6 @@ array(char*) result = dq_queries(doc,"query"); // Return a result set from your
    |[//book/\*[2] ](https://#)|objects
    ||
    ||
    |[count(//book) ](https://#)|The number of books
    |[count(//@category) ](https://#)|2
    |[count(//book//\*) ](https://#)|2
    |[type(//book/\*[2]) ](https://#)|'string'
    |[type(\*/\*[2]) ](https://#)|'subData'
    |[text(\*/book/\*[2]/) ](https://#)|'val'
    ||
    ||
    |[p[@x] ](https://#)|selects all P elements with an attribute named X, in current context.
    |[//p[@x] ](https://#)|selects all P elements with an attribute named X, in any context from current.
    |[//item[@price > 2\*@discount] ](https://#)|selects all items whose price attribute is greater than twice their discount attribute.
    @@ -236,6 +228,14 @@ array(char*) result = dq_queries(doc,"query"); // Return a result set from your
    |[a[/html/@lang='en'][@href=='help.php'][0]/@target](https://#) |selects the value of the TARGET attribute of the first A element among the children of the context node that has its HREF attribute set to HELP.PHP, provided the document's html top-level element also has a LANG attribute set to EN.
    ||
    ||
    |[count(//book) ](https://#)|The number of books
    |[count(//@category) ](https://#)|2
    |[count(//book//\*) ](https://#)|2
    |[type(//book/\*[2]) ](https://#)|'string'
    |[type(\*/\*[2]) ](https://#)|'subData'
    |[text(\*/book/\*[2]/) ](https://#)|'val'
    ||
    ||
    |[from(//data/fruits).startsWith("a").or().startsWith("b").count() ](https://#)|todo: writeme
    |[from(//records).reverse() ](https://#)|todo: writeme
    |[from(//records).join(//data/locations).orderBy(/location/city) ](https://#)|todo: writeme
  15. r-lyeh revised this gist Mar 6, 2020. 1 changed file with 6 additions and 6 deletions.
    12 changes: 6 additions & 6 deletions DataQuery.md
    Original file line number Diff line number Diff line change
    @@ -236,12 +236,12 @@ array(char*) result = dq_queries(doc,"query"); // Return a result set from your
    |[a[/html/@lang='en'][@href=='help.php'][0]/@target](https://#) |selects the value of the TARGET attribute of the first A element among the children of the context node that has its HREF attribute set to HELP.PHP, provided the document's html top-level element also has a LANG attribute set to EN.
    ||
    ||
    |[from(//data/fruits).startsWith("a").or().startsWith("b").count() ](https://#)|
    |[from(//records).reverse() ](https://#)|
    |[from(//records).join(//data/locations).orderBy(/location/city) ](https://#)|
    |[from(/data/fruits).case(0).equals("STRAWBERRY").count() ](https://#)|
    |[from(/data/fruits).startsWith("a").union(["tomato", "carrot"]).count() ](https://#)|
    |[from(/data/emails).matches("*@*.com").any() ](https://#)|
    |[from(//data/fruits).startsWith("a").or().startsWith("b").count() ](https://#)|todo: writeme
    |[from(//records).reverse() ](https://#)|todo: writeme
    |[from(//records).join(//data/locations).orderBy(/location/city) ](https://#)|todo: writeme
    |[from(/data/fruits).case(0).equals("STRAWBERRY").count() ](https://#)|todo: writeme
    |[from(/data/fruits).startsWith("a").union(["tomato", "carrot"]).count() ](https://#)|todo: writeme
    |[from(/data/emails).matches("*@*.com").any() ](https://#)|todo: writeme

    ## Credits
    - Grabbed ideas from XPath, JsonPath and Jsel READMEs.
  16. r-lyeh revised this gist Mar 6, 2020. 1 changed file with 96 additions and 95 deletions.
    191 changes: 96 additions & 95 deletions DataQuery.md
    Original file line number Diff line number Diff line change
    @@ -7,98 +7,6 @@ char *result = dq_query(doc,"query"); // Return a single value from yo
    array(char*) result = dq_queries(doc,"query"); // Return a result set from your data (array)
    ```
    ## Demo: data
    ```json
    {
    "books": [{
    "@class": "book(ssf)",
    "@category": "reference",
    "author": "Nigel Rees",
    "title": "Sayings of the Century",
    "price": 8.95
    },
    {
    "@class": "book(ssf)",
    "@category": "fiction",
    "author": "Evelyn Waugh",
    "title": "Sword of Honour",
    "price": 12.99
    },
    {
    "@class": "book(ssf)",
    "@category": "fiction",
    "author": "Herman Melville",
    "title": "Moby Dick",
    "price": 8.99
    },
    {
    "@class": "book(ssf)",
    "@category": "fiction",
    "author": "J. R. R. Tolkien",
    "title": "The Lord of the Rings",
    "price": 22.99
    }
    ],
    "bicycle": {
    "color": "red",
    "price": 19.95
    }
    }
    ```

    ## Demo: queries

    | Query |Result
    |:---|:---|
    |[/store/book[\*]/author ](https://#)|The authors of all books in the store
    |[//author ](https://#)|All authors
    |[/store/* ](https://#)|All things in store, which are some books and a red bicycle
    |[/store//price ](https://#)|The price of everything in the store.
    |[//book[2] ](https://#)|The third book
    |[//book[0,1] ](https://#)|The first two books
    |[//book[1:2] ](https://#)|All books from index 1 (inclusive) until index 2 (exclusive)
    |[//book[2:] ](https://#)|All books from index 2 (inclusive) till end
    |[//book[:2] ](https://#)|All books from index 0 (inclusive) until index 2 (exclusive) *the first 2 books*
    |[//book[-2] ](https://#)|The second to last book
    |[//book[-2:] ](https://#)|Last two books
    |[//book[-1:] ](https://#)|The last book
    |[//book[isbn] ](https://#)|All books with an ISBN number
    |[//book[price<10] ](https://#)|All books in store cheaper than 10
    |[//\* ](https://#)|All Elements in XML document. All members of JSON structure.
    |[//book[author =~ //\*REES/] ](https://#)|All books matching regex
    ||
    ||
    |[//@category ](https://#)|All categories
    |[//@category[2] ](https://#)|'fiction'
    |[//book/\*[1]/@category ](https://#)|'fiction'
    |[/book[2]/@category ](https://#)|'fiction'
    |[//book/\*[2] ](https://#)|objects
    ||
    ||
    |[count(//book) ](https://#)|The number of books
    |[count(//@category) ](https://#)|2
    |[count(//book//\*) ](https://#)|2
    |[type(//book/\*[2]) ](https://#)|'string'
    |[type(\*/\*[2]) ](https://#)|'subData'
    |[text(\*/book/\*[2]/) ](https://#)|'val'
    ||
    ||
    |[p[@x] ](https://#)|selects all P elements with an attribute named X, in current context.
    |[//p[@x] ](https://#)|selects all P elements with an attribute named X, in any context from current.
    |[//item[@price > 2\*@discount] ](https://#)|selects all items whose price attribute is greater than twice their discount attribute.
    |[v[x or y] \| w[z] ](https://#)|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'] ](https://#)|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] ](https://#)|selects the first A child that satisfies this condition.
    |[a[/html/@lang='en'][@href=='help.php'][0]/@target](https://#) |selects the value of the TARGET attribute of the first A element among the children of the context node that has its HREF attribute set to HELP.PHP, provided the document's html top-level element also has a LANG attribute set to EN.
    ||
    ||
    |[from(//data/fruits).startsWith("a").or().startsWith("b").count() ](https://#)|
    |[from(//records).reverse() ](https://#)|
    |[from(//records).join(//data/locations).orderBy(/location/city) ](https://#)|
    |[from(/data/fruits).case(0).equals("STRAWBERRY").count() ](https://#)|
    |[from(/data/fruits).startsWith("a").union(["tomato", "carrot"]).count() ](https://#)|
    |[from(/data/emails).matches("*@*.com").any() ](https://#)|

    ## Operators
    |Operators |Description
    |---:|:---|
    @@ -243,9 +151,102 @@ array(char*) result = dq_queries(doc,"query"); // Return a result set from your
    |[upper() ](https://#)|Returns A in UPPERCASE
    |[camel() ](https://#)|Returns A in camelCase
    ## Demo: data
    ```json
    {
    "books": [{
    "@class": "book(ssf)",
    "@category": "reference",
    "author": "Nigel Rees",
    "title": "Sayings of the Century",
    "price": 8.95
    },
    {
    "@class": "book(ssf)",
    "@category": "fiction",
    "author": "Evelyn Waugh",
    "title": "Sword of Honour",
    "price": 12.99
    },
    {
    "@class": "book(ssf)",
    "@category": "fiction",
    "author": "Herman Melville",
    "title": "Moby Dick",
    "price": 8.99
    },
    {
    "@class": "book(ssf)",
    "@category": "fiction",
    "author": "J. R. R. Tolkien",
    "title": "The Lord of the Rings",
    "price": 22.99
    }
    ],
    "bicycle": {
    "color": "red",
    "price": 19.95
    }
    }
    ```

    ## Demo: queries

    | Query |Result
    |:---|:---|
    |[/store/book[\*]/author ](https://#)|The authors of all books in the store
    |[//author ](https://#)|All authors
    |[/store/* ](https://#)|All things in store, which are some books and a red bicycle
    |[/store//price ](https://#)|The price of everything in the store.
    |[//book[2] ](https://#)|The third book
    |[//book[0,1] ](https://#)|The first two books
    |[//book[1:2] ](https://#)|All books from index 1 (inclusive) until index 2 (exclusive)
    |[//book[2:] ](https://#)|All books from index 2 (inclusive) till end
    |[//book[:2] ](https://#)|All books from index 0 (inclusive) until index 2 (exclusive) *the first 2 books*
    |[//book[-2] ](https://#)|The second to last book
    |[//book[-2:] ](https://#)|Last two books
    |[//book[-1:] ](https://#)|The last book
    |[//book[isbn] ](https://#)|All books with an ISBN number
    |[//book[price<10] ](https://#)|All books in store cheaper than 10
    |[//\* ](https://#)|All Elements in XML document. All members of JSON structure.
    |[//book[author =~ //\*REES/] ](https://#)|All books matching regex
    ||
    ||
    |[//@category ](https://#)|All categories
    |[//@category[2] ](https://#)|'fiction'
    |[//book/\*[1]/@category ](https://#)|'fiction'
    |[/book[2]/@category ](https://#)|'fiction'
    |[//book/\*[2] ](https://#)|objects
    ||
    ||
    |[count(//book) ](https://#)|The number of books
    |[count(//@category) ](https://#)|2
    |[count(//book//\*) ](https://#)|2
    |[type(//book/\*[2]) ](https://#)|'string'
    |[type(\*/\*[2]) ](https://#)|'subData'
    |[text(\*/book/\*[2]/) ](https://#)|'val'
    ||
    ||
    |[p[@x] ](https://#)|selects all P elements with an attribute named X, in current context.
    |[//p[@x] ](https://#)|selects all P elements with an attribute named X, in any context from current.
    |[//item[@price > 2\*@discount] ](https://#)|selects all items whose price attribute is greater than twice their discount attribute.
    |[v[x or y] \| w[z] ](https://#)|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'] ](https://#)|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] ](https://#)|selects the first A child that satisfies this condition.
    |[a[/html/@lang='en'][@href=='help.php'][0]/@target](https://#) |selects the value of the TARGET attribute of the first A element among the children of the context node that has its HREF attribute set to HELP.PHP, provided the document's html top-level element also has a LANG attribute set to EN.
    ||
    ||
    |[from(//data/fruits).startsWith("a").or().startsWith("b").count() ](https://#)|
    |[from(//records).reverse() ](https://#)|
    |[from(//records).join(//data/locations).orderBy(/location/city) ](https://#)|
    |[from(/data/fruits).case(0).equals("STRAWBERRY").count() ](https://#)|
    |[from(/data/fruits).startsWith("a").union(["tomato", "carrot"]).count() ](https://#)|
    |[from(/data/emails).matches("*@*.com").any() ](https://#)|

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

    ## License
    - Data-query spec dual licensed into the public domain and CC0.

    ## Credits
    - Original work by @r-lyeh.
    - Grabbed some ideas from XPath, JsonPath and Jsel READMEs.
  17. r-lyeh revised this gist Mar 6, 2020. 1 changed file with 97 additions and 98 deletions.
    195 changes: 97 additions & 98 deletions DataQuery.md
    Original file line number Diff line number Diff line change
    @@ -7,14 +7,106 @@ char *result = dq_query(doc,"query"); // Return a single value from yo
    array(char*) result = dq_queries(doc,"query"); // Return a result set from your data (array)
    ```
    ## Demo: data
    ```json
    {
    "books": [{
    "@class": "book(ssf)",
    "@category": "reference",
    "author": "Nigel Rees",
    "title": "Sayings of the Century",
    "price": 8.95
    },
    {
    "@class": "book(ssf)",
    "@category": "fiction",
    "author": "Evelyn Waugh",
    "title": "Sword of Honour",
    "price": 12.99
    },
    {
    "@class": "book(ssf)",
    "@category": "fiction",
    "author": "Herman Melville",
    "title": "Moby Dick",
    "price": 8.99
    },
    {
    "@class": "book(ssf)",
    "@category": "fiction",
    "author": "J. R. R. Tolkien",
    "title": "The Lord of the Rings",
    "price": 22.99
    }
    ],
    "bicycle": {
    "color": "red",
    "price": 19.95
    }
    }
    ```

    ## Demo: queries

    | Query |Result
    |:---|:---|
    |[/store/book[\*]/author ](https://#)|The authors of all books in the store
    |[//author ](https://#)|All authors
    |[/store/* ](https://#)|All things in store, which are some books and a red bicycle
    |[/store//price ](https://#)|The price of everything in the store.
    |[//book[2] ](https://#)|The third book
    |[//book[0,1] ](https://#)|The first two books
    |[//book[1:2] ](https://#)|All books from index 1 (inclusive) until index 2 (exclusive)
    |[//book[2:] ](https://#)|All books from index 2 (inclusive) till end
    |[//book[:2] ](https://#)|All books from index 0 (inclusive) until index 2 (exclusive) *the first 2 books*
    |[//book[-2] ](https://#)|The second to last book
    |[//book[-2:] ](https://#)|Last two books
    |[//book[-1:] ](https://#)|The last book
    |[//book[isbn] ](https://#)|All books with an ISBN number
    |[//book[price<10] ](https://#)|All books in store cheaper than 10
    |[//\* ](https://#)|All Elements in XML document. All members of JSON structure.
    |[//book[author =~ //\*REES/] ](https://#)|All books matching regex
    ||
    ||
    |[//@category ](https://#)|All categories
    |[//@category[2] ](https://#)|'fiction'
    |[//book/\*[1]/@category ](https://#)|'fiction'
    |[/book[2]/@category ](https://#)|'fiction'
    |[//book/\*[2] ](https://#)|objects
    ||
    ||
    |[count(//book) ](https://#)|The number of books
    |[count(//@category) ](https://#)|2
    |[count(//book//\*) ](https://#)|2
    |[type(//book/\*[2]) ](https://#)|'string'
    |[type(\*/\*[2]) ](https://#)|'subData'
    |[text(\*/book/\*[2]/) ](https://#)|'val'
    ||
    ||
    |[p[@x] ](https://#)|selects all P elements with an attribute named X, in current context.
    |[//p[@x] ](https://#)|selects all P elements with an attribute named X, in any context from current.
    |[//item[@price > 2\*@discount] ](https://#)|selects all items whose price attribute is greater than twice their discount attribute.
    |[v[x or y] \| w[z] ](https://#)|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'] ](https://#)|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] ](https://#)|selects the first A child that satisfies this condition.
    |[a[/html/@lang='en'][@href=='help.php'][0]/@target](https://#) |selects the value of the TARGET attribute of the first A element among the children of the context node that has its HREF attribute set to HELP.PHP, provided the document's html top-level element also has a LANG attribute set to EN.
    ||
    ||
    |[from(//data/fruits).startsWith("a").or().startsWith("b").count() ](https://#)|
    |[from(//records).reverse() ](https://#)|
    |[from(//records).join(//data/locations).orderBy(/location/city) ](https://#)|
    |[from(/data/fruits).case(0).equals("STRAWBERRY").count() ](https://#)|
    |[from(/data/fruits).startsWith("a").union(["tomato", "carrot"]).count() ](https://#)|
    |[from(/data/emails).matches("*@*.com").any() ](https://#)|

    ## Operators
    |Operators |Description
    |---:|:---|
    |[. ](https://#)|The current object/element
    |[.. ](https://#)|Parent operator
    |[/ ](https://#)|The root object/element
    |[// ](https://#)|Recursive descent.
    |[/child or [child] ](https://#)|Child operator (also array index)
    |[child/ or [child] ](https://#)|Child operator (also array index)
    |[\*? ](https://#)|Wildcards. Available anywhere a name or numeric are required.
    |[[] ](https://#)|Subscript operator.
    |[[,] ](https://#)|Union operator, allows alternate names or array indices as a set.
    @@ -151,102 +243,9 @@ array(char*) result = dq_queries(doc,"query"); // Return a result set from your
    |[upper() ](https://#)|Returns A in UPPERCASE
    |[camel() ](https://#)|Returns A in camelCase

    ## Demo: data
    ```json
    {
    "books": [{
    "@class": "book(ssf)",
    "@category": "reference",
    "author": "Nigel Rees",
    "title": "Sayings of the Century",
    "price": 8.95
    },
    {
    "@class": "book(ssf)",
    "@category": "fiction",
    "author": "Evelyn Waugh",
    "title": "Sword of Honour",
    "price": 12.99
    },
    {
    "@class": "book(ssf)",
    "@category": "fiction",
    "author": "Herman Melville",
    "title": "Moby Dick",
    "price": 8.99
    },
    {
    "@class": "book(ssf)",
    "@category": "fiction",
    "author": "J. R. R. Tolkien",
    "title": "The Lord of the Rings",
    "price": 22.99
    }
    ],
    "bicycle": {
    "color": "red",
    "price": 19.95
    }
    }
    ```

    ## Demo: queries

    | Query |Result
    |:---|:---|
    |[/store/book[\*]/author ](https://#)|The authors of all books in the store
    |[//author ](https://#)|All authors
    |[/store/* ](https://#)|All things in store, which are some books and a red bicycle
    |[/store//price ](https://#)|The price of everything in the store.
    |[//book[2] ](https://#)|The third book
    |[//book[0,1] ](https://#)|The first two books
    |[//book[1:2] ](https://#)|All books from index 1 (inclusive) until index 2 (exclusive)
    |[//book[2:] ](https://#)|All books from index 2 (inclusive) till end
    |[//book[:2] ](https://#)|All books from index 0 (inclusive) until index 2 (exclusive) *the first 2 books*
    |[//book[-2] ](https://#)|The second to last book
    |[//book[-2:] ](https://#)|Last two books
    |[//book[-1:] ](https://#)|The last book
    |[//book[isbn] ](https://#)|All books with an ISBN number
    |[//book[price<10] ](https://#)|All books in store cheaper than 10
    |[//\* ](https://#)|All Elements in XML document. All members of JSON structure.
    |[//book[author =~ //\*REES/] ](https://#)|All books matching regex
    ||
    ||
    |[//@category ](https://#)|All categories
    |[//@category[2] ](https://#)|'fiction'
    |[//book/\*[1]/@category ](https://#)|'fiction'
    |[/book[2]/@category ](https://#)|'fiction'
    |[//book/\*[2] ](https://#)|objects
    ||
    ||
    |[count(//book) ](https://#)|The number of books
    |[count(//@category) ](https://#)|2
    |[count(//book//\*) ](https://#)|2
    |[type(//book/\*[2]) ](https://#)|'string'
    |[type(\*/\*[2]) ](https://#)|'subData'
    |[text(\*/book/\*[2]/) ](https://#)|'val'
    ||
    ||
    |[p[@x] ](https://#)|selects all P elements with an attribute named X, in current context.
    |[//p[@x] ](https://#)|selects all P elements with an attribute named X, in any context from current.
    |[//item[@price > 2\*@discount] ](https://#)|selects all items whose price attribute is greater than twice their discount attribute.
    |[v[x or y] \| w[z] ](https://#)|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'] ](https://#)|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] ](https://#)|selects the first A child that satisfies this condition.
    |[a[/html/@lang='en'][@href=='help.php'][0]/@target](https://#) |selects the value of the TARGET attribute of the first A element among the children of the context node that has its HREF attribute set to HELP.PHP, provided the document's html top-level element also has a LANG attribute set to EN.
    ||
    ||
    |[from(//data/fruits).startsWith("a").or().startsWith("b").count() ](https://#)|
    |[from(//records).reverse() ](https://#)|
    |[from(//records).join(//data/locations).orderBy(/location/city) ](https://#)|
    |[from(/data/fruits).case(0).equals("STRAWBERRY").count() ](https://#)|
    |[from(/data/fruits).startsWith("a").union(["tomato", "carrot"]).count() ](https://#)|
    |[from(/data/emails).matches("*@*.com").any() ](https://#)|

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

    ## License
    - Data-query spec dual licensed into the public domain and CC0.

    ## Credits
    - Original work by @r-lyeh.
    - Grabbed some ideas from XPath, JsonPath and Jsel READMEs.
  18. r-lyeh revised this gist Mar 6, 2020. 1 changed file with 97 additions and 96 deletions.
    193 changes: 97 additions & 96 deletions DataQuery.md
    Original file line number Diff line number Diff line change
    @@ -7,98 +7,6 @@ char *result = dq_query(doc,"query"); // Return a single value from yo
    array(char*) result = dq_queries(doc,"query"); // Return a result set from your data (array)
    ```
    ## Demo: data
    ```json
    {
    "books": [{
    "@class": "book(ssf)",
    "@category": "reference",
    "author": "Nigel Rees",
    "title": "Sayings of the Century",
    "price": 8.95
    },
    {
    "@class": "book(ssf)",
    "@category": "fiction",
    "author": "Evelyn Waugh",
    "title": "Sword of Honour",
    "price": 12.99
    },
    {
    "@class": "book(ssf)",
    "@category": "fiction",
    "author": "Herman Melville",
    "title": "Moby Dick",
    "price": 8.99
    },
    {
    "@class": "book(ssf)",
    "@category": "fiction",
    "author": "J. R. R. Tolkien",
    "title": "The Lord of the Rings",
    "price": 22.99
    }
    ],
    "bicycle": {
    "color": "red",
    "price": 19.95
    }
    }
    ```

    ## Demo: queries

    | Query |Result
    |:---|:---|
    |[/store/book[\*]/author ](https://#)|The authors of all books in the store
    |[//author ](https://#)|All authors
    |[/store/* ](https://#)|All things in store, which are some books and a red bicycle
    |[/store//price ](https://#)|The price of everything in the store.
    |[//book[2] ](https://#)|The third book
    |[//book[0,1] ](https://#)|The first two books
    |[//book[1:2] ](https://#)|All books from index 1 (inclusive) until index 2 (exclusive)
    |[//book[2:] ](https://#)|All books from index 2 (inclusive) till end
    |[//book[:2] ](https://#)|All books from index 0 (inclusive) until index 2 (exclusive) *the first 2 books*
    |[//book[-2] ](https://#)|The second to last book
    |[//book[-2:] ](https://#)|Last two books
    |[//book[-1:] ](https://#)|The last book
    |[//book[isbn] ](https://#)|All books with an ISBN number
    |[//book[price<10] ](https://#)|All books in store cheaper than 10
    |[//\* ](https://#)|All Elements in XML document. All members of JSON structure.
    |[//book[author =~ //\*REES/] ](https://#)|All books matching regex
    ||
    ||
    |[//@category ](https://#)|All categories
    |[//@category[2] ](https://#)|'fiction'
    |[//book/\*[1]/@category ](https://#)|'fiction'
    |[/book[2]/@category ](https://#)|'fiction'
    |[//book/\*[2] ](https://#)|objects
    ||
    ||
    |[count(//book) ](https://#)|The number of books
    |[count(//@category) ](https://#)|2
    |[count(//book//\*) ](https://#)|2
    |[type(//book/\*[2]) ](https://#)|'string'
    |[type(\*/\*[2]) ](https://#)|'subData'
    |[text(\*/book/\*[2]/) ](https://#)|'val'
    ||
    ||
    |[p[@x] ](https://#)|selects all P elements with an attribute named X, in current context.
    |[//p[@x] ](https://#)|selects all P elements with an attribute named X, in any context from current.
    |[//item[@price > 2\*@discount] ](https://#)|selects all items whose price attribute is greater than twice their discount attribute.
    |[v[x or y] \| w[z] ](https://#)|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'] ](https://#)|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] ](https://#)|selects the first A child that satisfies this condition.
    |[a[/html/@lang='en'][@href=='help.php'][0]/@target](https://#) |selects the value of the TARGET attribute of the first A element among the children of the context node that has its HREF attribute set to HELP.PHP, provided the document's html top-level element also has a LANG attribute set to EN.
    ||
    ||
    |[from(//data/fruits).startsWith("a").or().startsWith("b").count() ](https://#)|
    |[from(//records).reverse() ](https://#)|
    |[from(//records).join(//data/locations).orderBy(/location/city) ](https://#)|
    |[from(/data/fruits).case(0).equals("STRAWBERRY").count() ](https://#)|
    |[from(/data/fruits).startsWith("a").union(["tomato", "carrot"]).count() ](https://#)|
    |[from(/data/emails).matches("*@*.com").any() ](https://#)|

    ## Operators
    |Operators |Description
    |---:|:---|
    @@ -243,9 +151,102 @@ array(char*) result = dq_queries(doc,"query"); // Return a result set from your
    |[upper() ](https://#)|Returns A in UPPERCASE
    |[camel() ](https://#)|Returns A in camelCase
    ## License
    - Data-query spec dual licensed into the public domain and CC0.
    ## Demo: data
    ```json
    {
    "books": [{
    "@class": "book(ssf)",
    "@category": "reference",
    "author": "Nigel Rees",
    "title": "Sayings of the Century",
    "price": 8.95
    },
    {
    "@class": "book(ssf)",
    "@category": "fiction",
    "author": "Evelyn Waugh",
    "title": "Sword of Honour",
    "price": 12.99
    },
    {
    "@class": "book(ssf)",
    "@category": "fiction",
    "author": "Herman Melville",
    "title": "Moby Dick",
    "price": 8.99
    },
    {
    "@class": "book(ssf)",
    "@category": "fiction",
    "author": "J. R. R. Tolkien",
    "title": "The Lord of the Rings",
    "price": 22.99
    }
    ],
    "bicycle": {
    "color": "red",
    "price": 19.95
    }
    }
    ```

    ## Demo: queries

    | Query |Result
    |:---|:---|
    |[/store/book[\*]/author ](https://#)|The authors of all books in the store
    |[//author ](https://#)|All authors
    |[/store/* ](https://#)|All things in store, which are some books and a red bicycle
    |[/store//price ](https://#)|The price of everything in the store.
    |[//book[2] ](https://#)|The third book
    |[//book[0,1] ](https://#)|The first two books
    |[//book[1:2] ](https://#)|All books from index 1 (inclusive) until index 2 (exclusive)
    |[//book[2:] ](https://#)|All books from index 2 (inclusive) till end
    |[//book[:2] ](https://#)|All books from index 0 (inclusive) until index 2 (exclusive) *the first 2 books*
    |[//book[-2] ](https://#)|The second to last book
    |[//book[-2:] ](https://#)|Last two books
    |[//book[-1:] ](https://#)|The last book
    |[//book[isbn] ](https://#)|All books with an ISBN number
    |[//book[price<10] ](https://#)|All books in store cheaper than 10
    |[//\* ](https://#)|All Elements in XML document. All members of JSON structure.
    |[//book[author =~ //\*REES/] ](https://#)|All books matching regex
    ||
    ||
    |[//@category ](https://#)|All categories
    |[//@category[2] ](https://#)|'fiction'
    |[//book/\*[1]/@category ](https://#)|'fiction'
    |[/book[2]/@category ](https://#)|'fiction'
    |[//book/\*[2] ](https://#)|objects
    ||
    ||
    |[count(//book) ](https://#)|The number of books
    |[count(//@category) ](https://#)|2
    |[count(//book//\*) ](https://#)|2
    |[type(//book/\*[2]) ](https://#)|'string'
    |[type(\*/\*[2]) ](https://#)|'subData'
    |[text(\*/book/\*[2]/) ](https://#)|'val'
    ||
    ||
    |[p[@x] ](https://#)|selects all P elements with an attribute named X, in current context.
    |[//p[@x] ](https://#)|selects all P elements with an attribute named X, in any context from current.
    |[//item[@price > 2\*@discount] ](https://#)|selects all items whose price attribute is greater than twice their discount attribute.
    |[v[x or y] \| w[z] ](https://#)|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'] ](https://#)|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] ](https://#)|selects the first A child that satisfies this condition.
    |[a[/html/@lang='en'][@href=='help.php'][0]/@target](https://#) |selects the value of the TARGET attribute of the first A element among the children of the context node that has its HREF attribute set to HELP.PHP, provided the document's html top-level element also has a LANG attribute set to EN.
    ||
    ||
    |[from(//data/fruits).startsWith("a").or().startsWith("b").count() ](https://#)|
    |[from(//records).reverse() ](https://#)|
    |[from(//records).join(//data/locations).orderBy(/location/city) ](https://#)|
    |[from(/data/fruits).case(0).equals("STRAWBERRY").count() ](https://#)|
    |[from(/data/fruits).startsWith("a").union(["tomato", "carrot"]).count() ](https://#)|
    |[from(/data/emails).matches("*@*.com").any() ](https://#)|

    ## Credits
    - Original work by @r-lyeh.
    - Grabbed some ideas from XPath, JsonPath and Jsel READMEs.
    - Grabbed ideas from XPath, JsonPath and Jsel READMEs.
    - Additional work by @r-lyeh.

    ## License
    - Data-query spec dual licensed into the public domain and CC0.
  19. r-lyeh revised this gist Mar 6, 2020. 1 changed file with 34 additions and 20 deletions.
    54 changes: 34 additions & 20 deletions DataQuery.md
    Original file line number Diff line number Diff line change
    @@ -50,7 +50,7 @@ array(char*) result = dq_queries(doc,"query"); // Return a result set from your

    | Query |Result
    |:---|:---|
    |[/store/book[*]/author ](https://#)|The authors of all books in the store
    |[/store/book[\*]/author ](https://#)|The authors of all books in the store
    |[//author ](https://#)|All authors
    |[/store/* ](https://#)|All things in store, which are some books and a red bicycle
    |[/store//price ](https://#)|The price of everything in the store.
    @@ -64,30 +64,34 @@ array(char*) result = dq_queries(doc,"query"); // Return a result set from your
    |[//book[-1:] ](https://#)|The last book
    |[//book[isbn] ](https://#)|All books with an ISBN number
    |[//book[price<10] ](https://#)|All books in store cheaper than 10
    |[//* ](https://#)|All Elements in XML document. All members of JSON structure.
    |[//book[author =~ //*REES/] ](https://#)|All books matching regex
    |[//\* ](https://#)|All Elements in XML document. All members of JSON structure.
    |[//book[author =~ //\*REES/] ](https://#)|All books matching regex
    ||
    ||
    |[//@category ](https://#)|All categories
    |[//@category[2] ](https://#)|'fiction'
    |[//book/*[1]/@category ](https://#)|'fiction'
    |[//book/\*[1]/@category ](https://#)|'fiction'
    |[/book[2]/@category ](https://#)|'fiction'
    |[//book/*[2] ](https://#)|objects
    |[//book/\*[2] ](https://#)|objects
    ||
    ||
    |[count(//book) ](https://#)|The number of books
    |[count(//@category) ](https://#)|2
    |[count(//book//*) ](https://#)|2
    |[type(//book/*[2]) ](https://#)|'string'
    |[type(*/*[2]) ](https://#)|'subData'
    |[text(*/book/*[2]/) ](https://#)|'val'
    |[count(//book//\*) ](https://#)|2
    |[type(//book/\*[2]) ](https://#)|'string'
    |[type(\*/\*[2]) ](https://#)|'subData'
    |[text(\*/book/\*[2]/) ](https://#)|'val'
    ||
    ||
    |[p[@x] ](https://#)|selects all P elements with an attribute named X, in current context.
    |[//p[@x] ](https://#)|selects all P elements with an attribute named X, in any context from current.
    |[//item[@price > 2*@discount] ](https://#)|selects all items whose price attribute is greater than twice their discount attribute.
    |[//item[@price > 2\*@discount] ](https://#)|selects all items whose price attribute is greater than twice their discount attribute.
    |[v[x or y] \| w[z] ](https://#)|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'] ](https://#)|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] ](https://#)|selects the first A child that satisfies this condition.
    |[a[/html/@lang='en'][@href=='help.php'][0]/@target](https://#) |selects the value of the TARGET attribute of the first A element among the children of the context node that has its HREF attribute set to HELP.PHP, provided the document's html top-level element also has a LANG attribute set to EN.
    ||
    ||
    |[from(//data/fruits).startsWith("a").or().startsWith("b").count() ](https://#)|
    |[from(//records).reverse() ](https://#)|
    |[from(//records).join(//data/locations).orderBy(/location/city) ](https://#)|
    @@ -98,12 +102,12 @@ array(char*) result = dq_queries(doc,"query"); // Return a result set from your
    ## Operators
    |Operators |Description
    |---:|:---|
    |[/ ](https://#)|The root object/element
    |[. ](https://#)|The current object/element
    |[/child or [child] ](https://#)|Child operator (also array index)
    |[.. ](https://#)|Parent operator
    |[/ ](https://#)|The root object/element
    |[// ](https://#)|Recursive descent.
    |[*? ](https://#)|Wildcards. Available anywhere a name or numeric are required.
    |[/child or [child] ](https://#)|Child operator (also array index)
    |[\*? ](https://#)|Wildcards. Available anywhere a name or numeric are required.
    |[[] ](https://#)|Subscript operator.
    |[[,] ](https://#)|Union operator, allows alternate names or array indices as a set.
    |[[start:end] ](https://#)|Array slice operator
    @@ -120,9 +124,9 @@ array(char*) result = dq_queries(doc,"query"); // Return a result set from your
    |[<= ](https://#)|left is less than or equal to right
    |[> ](https://#)|left is greater than right
    |[>= ](https://#)|left is greater than or equal to right
    |[=~ ](https://#)|left matches regular expression [name =~ /foo*/]
    |[=~~ ](https://#)|left matches regular expression [name =~~ /foo*/] (case insensitive)
    |[- + - * div mod ](https://#)|left and right arithmetical operation (double)
    |[=~ ](https://#)|left matches regular expression [name =~ /foo\*/]
    |[=~~ ](https://#)|left matches regular expression [name =~~ /foo\*/] (case insensitive)
    |[- + - \* div mod ](https://#)|left and right arithmetical operation (double)
    |[in ](https://#)|left exists in right
    |[nin ](https://#)|left does not exists in right
    |[subsetof ](https://#)|left is a subset of right
    @@ -142,11 +146,13 @@ array(char*) result = dq_queries(doc,"query"); // Return a result set from your
    | ---: | :--- |
    |[from(source) ](https://#)|Continues if selection exists.
    ||
    ||
    | **Debugging LINQ** | Description |
    |[debug(bool) ](https://#)|Continues into debug mode
    |[print() ](https://#)|Continues after printing current query
    |[break() ](https://#)|Continues after user agrees on debugger.
    ||
    ||
    | **Filtering LINQ** | Description |
    |[where(query) ](https://#)|Continues if expression matches.
    |[==(query) ](https://#)|Continues if two fields are equal
    @@ -164,22 +170,26 @@ array(char*) result = dq_queries(doc,"query"); // Return a result set from your
    |[and(action) ](https://#)|Continues if A was true
    |[or(action) ](https://#)|Continues if A was false, else skip next chained linq
    ||
    ||
    | **Result LINQ** | Description |
    |[any(selection) ](https://#)|Continues if any of A matched the query
    |[all(selection) ](https://#)|Continues if all of A matched the query
    |[none(selection) ](https://#)|Continues if none of A matched the query
    ||
    ||
    | **Action LINQ** | Description |
    |[each(action) ](https://#)|Continues after executing action to each A record
    |[attach(selection) ](https://#)|Continues after attaching a property to each A record
    |[detach(selection) ](https://#)|Continues after detaching a property from each A record
    ||
    ||
    | **Grouping LINQ** | Description |
    |[subtract(selection) ](https://#)|Continues after removing all A present in B values (difference:123-234=1)
    |[unique(selection) ](https://#)|Continues after extracting distinct A and B values (symmetric difference:123^234=14)
    |[shared(selection) ](https://#)|Continues after extracting repeated A and B values (intersection:123&234=23)
    |[join(selection) ](https://#)|Continues after merging A and B both together (union:123+234=1234)
    ||
    ||
    | **Ordering LINQ** | Description |
    |[reverse(bool) ](https://#)|Continues after reversing ordering logic.
    |[sort(pred) ](https://#)|Continues after sorting by predicate.
    @@ -189,18 +199,21 @@ array(char*) result = dq_queries(doc,"query"); // Return a result set from your
    |[first(selection) ](https://#)|Continues after selecting the first match of the set (allows a default match if nothing is found).
    |[others(selection) ](https://#)|Continues after selecting all elements but the first excluded.
    ||
    ||
    | **Stack LINQ** | Description |
    |[push() ](https://#)|Continues after pushing current LINQ into stack for further usage
    |[use(N) ](https://#)|Continues after using Nth query from stack
    |[pop() ](https://#)|Continues after popping current LINQ from stack
    ||
    ||
    | **Conversion LINQ** | Description |
    |[select(record,...) ](https://#)|Returns array of matching records.
    |[string() ](https://#)|Returns A as string.
    |[number() ](https://#)|Returns A as number.
    |[bool() ](https://#)|Returns A as bool.
    |[type() ](https://#)|Returns A type.
    ||
    ||
    | **Numerical LINQ** | Description |
    |[min() ](https://#)|Returns minimum value of A (as double)
    |[max() ](https://#)|Returns maximum value of A (as double)
    @@ -212,6 +225,7 @@ array(char*) result = dq_queries(doc,"query"); // Return a result set from your
    |[round() ](https://#)|Returns round value of A (as double)
    |[count() ](https://#)|Returns total records found in A (as integer)
    ||
    ||
    | **String LINQ** | Description |
    |[case(bool) ](https://#)|Makes string comparisons and search case sensitive or not.
    |[matches(query) ](https://#)|Continues if A matches regular expression of B. Allows wildcards.
    @@ -229,9 +243,9 @@ array(char*) result = dq_queries(doc,"query"); // Return a result set from your
    |[upper() ](https://#)|Returns A in UPPERCASE
    |[camel() ](https://#)|Returns A in camelCase

    ## Credits
    - Grabbed some ideas from XPath, JsonPath and Jsel READMEs.
    - Original work by @r-lyeh.

    ## License
    - Data-query spec dual licensed into the public domain and CC0.

    ## Credits
    - Original work by @r-lyeh.
    - Grabbed some ideas from XPath, JsonPath and Jsel READMEs.
  20. r-lyeh created this gist Mar 6, 2020.
    237 changes: 237 additions & 0 deletions DataQuery.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,237 @@
    # Data-query
    Data-query specification that resembles files and directories.

    ## C API
    ```C
    char *result = dq_query(doc,"query"); // Return a single value from your data
    array(char*) result = dq_queries(doc,"query"); // Return a result set from your data (array)
    ```
    ## Demo: data
    ```json
    {
    "books": [{
    "@class": "book(ssf)",
    "@category": "reference",
    "author": "Nigel Rees",
    "title": "Sayings of the Century",
    "price": 8.95
    },
    {
    "@class": "book(ssf)",
    "@category": "fiction",
    "author": "Evelyn Waugh",
    "title": "Sword of Honour",
    "price": 12.99
    },
    {
    "@class": "book(ssf)",
    "@category": "fiction",
    "author": "Herman Melville",
    "title": "Moby Dick",
    "price": 8.99
    },
    {
    "@class": "book(ssf)",
    "@category": "fiction",
    "author": "J. R. R. Tolkien",
    "title": "The Lord of the Rings",
    "price": 22.99
    }
    ],
    "bicycle": {
    "color": "red",
    "price": 19.95
    }
    }
    ```

    ## Demo: queries

    | Query |Result
    |:---|:---|
    |[/store/book[*]/author ](https://#)|The authors of all books in the store
    |[//author ](https://#)|All authors
    |[/store/* ](https://#)|All things in store, which are some books and a red bicycle
    |[/store//price ](https://#)|The price of everything in the store.
    |[//book[2] ](https://#)|The third book
    |[//book[0,1] ](https://#)|The first two books
    |[//book[1:2] ](https://#)|All books from index 1 (inclusive) until index 2 (exclusive)
    |[//book[2:] ](https://#)|All books from index 2 (inclusive) till end
    |[//book[:2] ](https://#)|All books from index 0 (inclusive) until index 2 (exclusive) *the first 2 books*
    |[//book[-2] ](https://#)|The second to last book
    |[//book[-2:] ](https://#)|Last two books
    |[//book[-1:] ](https://#)|The last book
    |[//book[isbn] ](https://#)|All books with an ISBN number
    |[//book[price<10] ](https://#)|All books in store cheaper than 10
    |[//* ](https://#)|All Elements in XML document. All members of JSON structure.
    |[//book[author =~ //*REES/] ](https://#)|All books matching regex
    ||
    |[//@category ](https://#)|All categories
    |[//@category[2] ](https://#)|'fiction'
    |[//book/*[1]/@category ](https://#)|'fiction'
    |[/book[2]/@category ](https://#)|'fiction'
    |[//book/*[2] ](https://#)|objects
    ||
    |[count(//book) ](https://#)|The number of books
    |[count(//@category) ](https://#)|2
    |[count(//book//*) ](https://#)|2
    |[type(//book/*[2]) ](https://#)|'string'
    |[type(*/*[2]) ](https://#)|'subData'
    |[text(*/book/*[2]/) ](https://#)|'val'
    ||
    |[p[@x] ](https://#)|selects all P elements with an attribute named X, in current context.
    |[//p[@x] ](https://#)|selects all P elements with an attribute named X, in any context from current.
    |[//item[@price > 2*@discount] ](https://#)|selects all items whose price attribute is greater than twice their discount attribute.
    |[v[x or y] \| w[z] ](https://#)|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'] ](https://#)|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] ](https://#)|selects the first A child that satisfies this condition.
    |[a[/html/@lang='en'][@href=='help.php'][0]/@target](https://#) |selects the value of the TARGET attribute of the first A element among the children of the context node that has its HREF attribute set to HELP.PHP, provided the document's html top-level element also has a LANG attribute set to EN.
    ||
    |[from(//data/fruits).startsWith("a").or().startsWith("b").count() ](https://#)|
    |[from(//records).reverse() ](https://#)|
    |[from(//records).join(//data/locations).orderBy(/location/city) ](https://#)|
    |[from(/data/fruits).case(0).equals("STRAWBERRY").count() ](https://#)|
    |[from(/data/fruits).startsWith("a").union(["tomato", "carrot"]).count() ](https://#)|
    |[from(/data/emails).matches("*@*.com").any() ](https://#)|

    ## Operators
    |Operators |Description
    |---:|:---|
    |[/ ](https://#)|The root object/element
    |[. ](https://#)|The current object/element
    |[/child or [child] ](https://#)|Child operator (also array index)
    |[.. ](https://#)|Parent operator
    |[// ](https://#)|Recursive descent.
    |[*? ](https://#)|Wildcards. Available anywhere a name or numeric are required.
    |[[] ](https://#)|Subscript operator.
    |[[,] ](https://#)|Union operator, allows alternate names or array indices as a set.
    |[[start:end] ](https://#)|Array slice operator
    |[@child ](https://#)|Attribute access. An attribute is some @meta info added to a document.
    |[$child ](https://#)|Convert child to string
    |[#child ](https://#)|Convert child to number

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

    ## LINQ functions
    - Valid syntax: function(element), function(set) or set.function()
    - function(element) evaluates on single element.
    - function(set) evaluates to first element of set. Equivalent to function(set[0]).
    - set.function() evaluates to all elements in set. Used for chaining (eg set.function1().function2().function3())

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

    ## Credits
    - Grabbed some ideas from XPath, JsonPath and Jsel READMEs.
    - Original work by @r-lyeh.

    ## License
    - Data-query spec dual licensed into the public domain and CC0.