{"id":28002941,"url":"https://github.com/crowbait/xmlmath","last_synced_at":"2026-03-11T02:07:05.863Z","repository":{"id":291874795,"uuid":"976616075","full_name":"crowbait/xmlmath","owner":"crowbait","description":"Math batch operations on XML documents","archived":false,"fork":false,"pushed_at":"2025-06-16T21:15:53.000Z","size":87,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-16T22:31:34.571Z","etag":null,"topics":["bash","math","xml","xml-parsing"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/crowbait.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","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,"zenodo":null},"funding":{"ko_fi":"crowbait"}},"created_at":"2025-05-02T12:35:39.000Z","updated_at":"2025-06-16T21:15:57.000Z","dependencies_parsed_at":"2025-05-09T01:45:23.014Z","dependency_job_id":null,"html_url":"https://github.com/crowbait/xmlmath","commit_stats":null,"previous_names":["crowbait/xmlmath"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/crowbait/xmlmath","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crowbait%2Fxmlmath","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crowbait%2Fxmlmath/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crowbait%2Fxmlmath/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crowbait%2Fxmlmath/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/crowbait","download_url":"https://codeload.github.com/crowbait/xmlmath/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crowbait%2Fxmlmath/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30367811,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-10T21:41:54.280Z","status":"online","status_checked_at":"2026-03-11T02:00:07.027Z","response_time":84,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["bash","math","xml","xml-parsing"],"created_at":"2025-05-09T01:45:21.192Z","updated_at":"2026-03-11T02:07:05.831Z","avatar_url":"https://github.com/crowbait.png","language":"Shell","funding_links":["https://ko-fi.com/crowbait"],"categories":[],"sub_categories":[],"readme":"# XMLMath \u003c!-- omit in toc --\u003e\n\n\u003cdiv align=\"center\"\u003e\n  \u003ca href=\"https://github.com/crowbait/xmlmath/releases/latest\"\u003e\u003cimg src=\"https://img.shields.io/github/v/release/crowbait/xmlmath\" alt=\"Latest Release\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/crowbait/xmlmath/blob/main/LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/github/license/crowbait/xmlmath\" alt=\"License\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/crowbait/xmlmath/actions/workflows/test.yml\"\u003e\u003cimg src=\"https://github.com/crowbait/xmlmath/actions/workflows/test.yml/badge.svg\" alt=\"Tests\"\u003e\u003c/a\u003e\n\u003c/div\u003e\n\n**XMLMath** is a command-line tool for performing arithmetic operations directly on XML files.\nIt allows batch modifications of attributes and values using a flexible set of filters and modifiers, allowing automated XML numeric data transformations.\n\n### Features \u003c!-- omit in toc --\u003e\n- Run arbitrary (*awk*-compatible) mathematic operations on attribute or element values\n- Target elements or attributes via tag names, or additional regex\n- Clamp and/or round results\n- Modify files in-place or output changes to a file or stdout\n- Optionally diff changes to stdout or a file\n- Small [dependency footprint](#requirements)\n\n#### What this is not\n- Fast. It really isn't.\n- Suitable for non-math operations. You'll be better off with regex-based find-replace in any text editor.\n\n## Contents \u003c!-- omit in toc --\u003e\n- [Getting Started](#getting-started)\n  - [Requirements](#requirements)\n  - [Download](#download)\n- [Usage](#usage)\n  - [Examples](#examples)\n  - [Operations](#operations)\n  - [Options](#options)\n- [Development](#development)\n\n\n## Getting Started\n### Requirements\n**XMLMath** relies on *awk*, *sed*, *diff* and *xmllint*.\nWith the exception of *xmllint*, these are already included in many distributions.\nOn *Debian*-/*Ubuntu*-based distros, *xmllint* can be installed with:\n```bash\nsudo apt install libxml2-utils\n```\n\n### Download\nDownload the built version of **XMLMath** from the latest release.\nYou could put it somewhere that's in your PATH to make it available globally.\n```bash\ncurl -L -o xmlmath https://github.com/crowbait/xmlmath/releases/latest/download/xmlmath\nchmod +x xmlmath\n```\nYou can also run it directly; this ensures you're always working with the latest release and doesn't put the script file on your drive.\n```bash\ncurl -sL https://github.com/crowbait/xmlmath/releases/latest/download/xmlmath | bash -s -- \"parameter1\" \"parameter2\" \"...\"\n```\nYou'll need to supply all parameters in quotes.\n\n## Usage\nSyntax:\n```bash\n./xmlmath \u003cattr|value\u003e \u003coperation\u003e \u003cmodifier\u003e [options] \u003c...targets\u003e\n```\n\n### Examples\nThis multiplies the value (between tags) of all XML elements named \"someval\" *or* \"otherval\" in `input.xml` by 2, writing the results back to the same file:\n```bash\n./xmlmath value multiply 2 --file input.xml --inplace someval otherval\n```\nThis multiplies the value all attributes in the file `in.xml` with names matching the regex `.*someattr` AND which are attributes of a tag \"tagname\" by 1.1, rounding the results to the neares integer and ensuring they are always greater than or equal to 2:\n```bash\n./xmlmath attr multiply 1.1 --int --min 2 --file in.xml --regex -w tagname '.*someattr'\n```\nYou can run arbitrary operations on the found values, providing they can be expressed in *awk*-compatible syntax - in this case, all attribute values (see regex) will be replaced with their root added to their squared value.\n**The token `x` will be substituted for the found value**:\n```bash\n./xmlmath attr expression 'sqrt(x)+x*x' --file in.xml -r '.*'\n```\nYou can get more examples from the tests: `test.sh` list commands.\nThe index names of those commands correspond to files in `test/`, which contain the transformed output when running these commands on `test/_expectation-template.xml`.\n\n### Operations\n| **Operation**  | **Short** | **Description**                                                                                    |\n| -------------- | --------- | -------------------------------------------------------------------------------------------------- |\n| **add**        | a         | Add the modifier to the found values                                                               |\n| **subtract**   | s         | Subtract the modifier from the found values                                                        |\n| **multiply**   | m         | Multiply the found values with the modifier                                                        |\n| **divide**     | d         | Divide the found values by the modifier                                                            |\n| **set**        |           | Set the found values *to* the modifier                                                             |\n| **expression** | e         | Treat the modifier as an expression; must be *awk*-compatible syntax and should be (single-)quoted |\n\n\n### Options\n| **Option**                                 | **Short** | **Arg** | **Description**                                                                                                                                        |\n| ------------------------------------------ | --------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| **--file**                                 | -f        | Path    | Specifies a file to be used as input. If not given, input is taken from stdin.                                                                         |\n| *requires `-f`*\u003cbr\u003e**--inplace**           | -p        |         | Writes the output back to the same file used as input.                                                                                                 |\n| **--out**                                  | -o        | Path    | Writes the output to *Path*. **Cannot be used with --inplace.**                                                                                        |\n| **--int**                                  | -i        |         | Rounds results to the nearest integer.                                                                                                                 |\n| **--min**                                  |           | Number  | Clamps all operation results to a minimum value of *Number*.                                                                                           |\n| **--max**                                  |           | Number  | Clamps all operation results to a maximum value of *Number*.                                                                                           |\n| **--regex**                                | -r        |         | Treats all targets (the list of attribute or value identifiers) as regex patterns instead of exact matches. You should quote each entry; see examples. |\n| **--within**                               | -w        | Tag     | For *attr*: only matches attributes within the tag *Tag*.\u003cbr\u003eFor *val*: only matches values that are a child element of *Tag* - within any depth.      |\n| *requires `-w`*\u003cbr\u003e**--within-additional** | --wa      | Regex   | Only accepts a match on `--within` if that line (containing the tag) also satisfies *Regex*.                                                          |\n| **--diff**                                 | -d        |         | Displays changes after all operations have finished.                                                                                                   |\n| *requires `-d`*\u003cbr\u003e**--diff-line-length**  | --dl      | Number  | Limits the length of lines in `--diff`'s output to *Number*, truncating as needed.                                                                     |\n| *requires `-d`*\u003cbr\u003e**--diff-file**         | --df      | Path    | Writes diff to a file instead of stdout.                                                                                                               |\n| **--verbose**                              | -v        |         | Prints detailed information about what's happening. **This WILL make your stdout unusable as XML.**                                                    |\n| **--progress**                             |           |         | Prints progress information. Prints to stderr, so the stdout *should* not be affected. **Cannot be used with `-v`.**                                   |\n\n## Development\nThe main script is modularized and `source`s its modules, which are in `parts/*`.\nThis is done for maintainability and is mostly personal preference.\nIt can be run directly in its development form or can be \"compiled\" by injecting the external modules into the script.\nThis is done by `build.sh` and writes a complete, self-contained file to `build/xmlmath`.\n\nTesting is done using `test.sh`.\nWithin that script, there is an array, mapping a \"test-id\" to a command to run against the main script.\nThe input for that test run is the file `test/test.xml`, which is intentionally ill-formatted.\nThere must be a file `test/[test-id].xml`, which represents the expected output of the run.\nNew test-target-XMLs should be created from `test/_expectation-template.xml` (same content as `test.xml`, but well formatted).","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcrowbait%2Fxmlmath","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcrowbait%2Fxmlmath","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcrowbait%2Fxmlmath/lists"}