{"id":15063825,"url":"https://github.com/prixladi/xq","last_synced_at":"2026-01-02T10:51:16.050Z","repository":{"id":249811134,"uuid":"830441273","full_name":"prixladi/xq","owner":"prixladi","description":"CLI application for querying XML","archived":false,"fork":false,"pushed_at":"2024-10-24T20:51:43.000Z","size":80,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-01-22T08:37:43.411Z","etag":null,"topics":["haskell","xml","xpath"],"latest_commit_sha":null,"homepage":"","language":"Haskell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/prixladi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-07-18T09:25:09.000Z","updated_at":"2024-10-28T10:41:26.000Z","dependencies_parsed_at":"2024-07-26T22:14:49.323Z","dependency_job_id":"7707b4b3-496f-485c-9d7c-6e5ea3df63f6","html_url":"https://github.com/prixladi/xq","commit_stats":null,"previous_names":["prixladi/xq"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/prixladi%2Fxq","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/prixladi%2Fxq/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/prixladi%2Fxq/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/prixladi%2Fxq/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/prixladi","download_url":"https://codeload.github.com/prixladi/xq/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243779078,"owners_count":20346656,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["haskell","xml","xpath"],"created_at":"2024-09-25T00:07:42.992Z","updated_at":"2026-01-02T10:51:15.995Z","avatar_url":"https://github.com/prixladi.png","language":"Haskell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# xq\n\n`xq` is a command-line utility for querying `XML`. It is written in `Haskell` and has zero dependencies. It uses `XQuery` (a subset of the language `XPath`) for querying, read more about `XQuery` in the following sections.\n\n## Project structure\n\n- `/app` - Command line application entry point\n- `/lib` - Core functionality of `xq`\n- `/test` - Unit tests\n\n## Building \u0026 Installing\n\n`xq` requires:\n\n- [GHC](https://www.haskell.org/ghc/) (Compiler)\n- [Cabal](https://www.haskell.org/cabal/) (Build system)\n- [Stack](https://docs.haskellstack.org/en/stable/#__tabbed_1_1) (Build system)\n\nYou can run your program directly using stack using:\n\n```sh\nstack run\n```\n\nThis is just for development and testing purposes. If you want to install xq on your system or run benchmarks you should build the binary:\n\n```sh\nstack build\n```\n\nand copy it to your `/bin` folder, eg.:\n\n```sh\ncp $(stack path --local-install-root)/bin/xq-exe ~/bin/xq\n```\n\n## Usage\n\nThe first argument of xq is always `XQuery`, the second argument is either path to XML file `xq \u003cxQuery\u003e \u003cxmlFilePath\u003e` or is not present at all and XML must be provided in stdin `xq \u003cxQuery\u003e {xmlStdin}`.\n\nFile example:\n\n```sh\nxq \"//book/*\" \"./bookstore.xml\"\n```\n\nStdin example:\n\n```sh\ncat \"./bookstore.xml\" | xq \"//book/*\"\n```\n\n## XQuery\n\n`XQuery` (also referenced as `XQ`) is a language used for querying parsed `XML`. It is a small subset of the `XPath` language and aims to be completely replaced by `XPath` if every functionality gets implemented.\n\n### Supported features\n\nSupported features can be seen in the examples below. More exhaustive documentation is currently in progress. Right now you can check source code directly if you need specific. Parsing of the XQuery can be found in the [parser file](lib/XqParser.hs) and usage in querying XML can be found in the [runner file](lib/XqRunner.hs).\n\n### Examples\n\n**Descendant selectors**\n\nDescendant selectors must start with '//' or '/'. The relative syntax without the **slash** qualifier is not supported.\n\n| XQuery    | CSS selector equivalent |\n| --------- | ----------------------- |\n| //div     | div                     |\n| //div//a  | div a                   |\n| //div//\\* | div \\*                  |\n| //div/\\*  | div \u003e \\*                |\n| /body     | :root \u003e body            |\n| /\\*       | :root                   |\n\n**Attribute selectors**\n\n| XQuery                  | CSS selector equivalent |\n| ----------------------- | ----------------------- |\n| //input[@type='submit'] | input[type='submit']    |\n| //a[@rel]               | a[rel]                  |\n\n**Position selectors**\n| XQuery | CSS selector equivalent |\n| -------------------- | ----------------------- |\n| //ul/li[position()=1] | ul \u003e li:first-of-type |\n| //ul/li[last()] | ul \u003e li:last-of-type |\n| //ul[@test='true']/li[@test='true'][last()] | ul[test='true'] \u003e li[test='true']:last-of-type |\n\n**Content selectors**\n\nFor number comparisons currently only the integer types are supported. A floating point number will result in an XQuery parse error.\n\n| XQuery                     | Description                                                                        |\n| -------------------------- | ---------------------------------------------------------------------------------- |\n| //price[text()='100 EUR']  | Selects all price nodes that have content that equals to string \"100 EUR\"          |\n| //price[text()!='100 EUR'] | Selects all price nodes that have content that does not equal to string \"100 EUR\"  |\n| //price[text()\u003e100]        | Selects all price nodes that have content that is parsable to int greater than 100 |\n| //price[text()=100]        | Selects all price nodes that have content that is parsable to int equal 100        |\n\n**Child selectors**\n\nChild selectors allow to nest the additional XQuery into the selector and its result is treated as a boolean value. Child selectors support the same syntax as root XQuery with one exception - the first descendant selector must be relative (must start directly with tag without the **/** or **//** prefix)\n\n| XQuery                                               | Description                                                                                                                                     |\n| ---------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |\n| //book[price[text()\u003c500]]/title                      | Selects all titles of boots that have a price that is a number lesser than 500                                                               |\n| //bookstore[book[@lang='en']/genre[text()\u003e'comedy']] | Selects all bookstores that have at least one book that has attribute 'lang' set to 'en' and has genre subnode that contains the text 'comedy'. |\n\n## Known issues and limitations\n\nSome of the issues and limitations that are known to the maintainer/developers.\n\n1. **Missing error hints** - _When parsing of the XML or XQ fails there are no error hints of which line and character the error occurred._\n2. **XML parsing** -\n\n   - _Parsing of the XML is not as strict as it should be. Such as:_\n\n     - _XML tag with duplicate attributes is not considered invalid but it should be._\n     - _Tags that start with the string **'xml'** are considered valid_\n     - _XML prelude is not validated at all and can be included anywhere in the document_\n     - _XML tag/attribute can contain multiple namespace indicators and can end with a namespace indicator (:)_\n     - _And many more ..._\n\n     _But this should not be so much of an issue since **xq** primary use is querying and not validating the XML_\n\n   - _On the other hand, many of the XML valid constructs are not supported. Such as:_\n\n     - _DTD._\n     - _CDATA_\n     - _Single quotes for attribute definitions_\n     - _And many more ..._\n\n## Unit tests\n\nBasic `xq` use cases are written as tests in folder `/test`.\n\nThe tests can be started using\n\n```sh\nstack test\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprixladi%2Fxq","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fprixladi%2Fxq","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprixladi%2Fxq/lists"}