Xml Surgeon
Overview
Use scripts/main.py for XPath-based XML reads/edits with minimal formatting drift. Prefer dry-run + diff, then in-place write.
Quick start
- •Inspect matches:
- •
uv run scripts/main.py select --xpath "//field[@name='arch']" path/to/file.xml
- •
- •Read text or attr:
- •
uv run scripts/main.py get --xpath "//field[@name='name']" path/to/file.xml - •
uv run scripts/main.py get --xpath "//record" --attr id path/to/file.xml
- •
- •Show subtree or inner XML:
- •
uv run scripts/main.py show --xpath "//record[@id='view_form']" path/to/file.xml - •
uv run scripts/main.py show --xpath "//field[@name='arch']" --inner --max-chars 2000 path/to/file.xml
- •
- •Scan child nodes:
- •
uv run scripts/main.py children --xpath "//group" path/to/file.xml - •
uv run scripts/main.py children --xpath "//group" --list --attrs path/to/file.xml
- •
- •Outline structure:
- •
uv run scripts/main.py outline --xpath "//record[@model='ir.ui.view']" --depth 3 path/to/file.xml - •
uv run scripts/main.py outline --xpath "//record[@id='view_form']" --attr id --attr name path/to/file.xml
- •
- •Context around matches:
- •
uv run scripts/main.py context --xpath "//field[@name='arch']" --before 2 --after 6 path/to/file.xml
- •
- •Set attribute (dry-run + diff):
- •
uv run scripts/main.py set-attr --xpath "//field[@name='arch']" --name string --value my_label --diff path/to/file.xml - •add
--in-placeto write
- •
- •Set text from file:
- •
uv run scripts/main.py set-text --xpath "//field[@name='arch']" --value-file snippet.xml --diff path/to/file.xml
- •
- •Insert XML fragment:
- •
uv run scripts/main.py insert --xpath "//group" --position inside-last --xml "<field name='x'/>" --diff --reformat-ok path/to/file.xml
- •
- •Delete nodes:
- •
uv run scripts/main.py delete --xpath "//field[@name='x']" --diff --reformat-ok path/to/file.xml
- •
Workflow
- •Inspect:
selectfor match counts and sourcelines - •Read:
show,children,outline, orcontextfor subtree/structure scanning - •Dry-run: run mutating commands with
--diff(no--in-place) - •Apply: add
--in-placeafter diff looks tight - •Verify: spot-check with
selectorget
Tasks
- •Inspect/select: use
select,get,show,children,outline, andcontextfor precise targeting - •Attribute edits:
set-attr,del-attr - •Text edits:
set-textwith--valueor--value-file - •Structural edits:
insert,replace,deletewith XPath - •Batch edits: pass multiple paths or globs (e.g.,
**/*.xml)
Guardrails
- •Minimal diffs:
set-attr,del-attr, andset-textare surgical and preserve formatting - •Structural edits:
insert,replace,deletereserialize XML and can reformat; require--reformat-ok - •Large files: use
--hugeif parser complains - •Namespaces: pass
--ns prefix=uriand useprefix:tagin XPath - •Indentation drift: use
--indenton insert/replace if needed
Resources
- •
scripts/main.py: main XML edit tool (uv script) - •
scripts/lib.py: helper module used by the CLI - •
references/xml-editing.md: XPath tips, minimal-diff notes, large-file hints