XML Engine
A lightning-fast, zero-dependency, modular XML parsing, XPath generation, and indexing engine designed specifically for VS Code. Provides intelligent element indexing, XPath generation (absolute and child-predicate modes), and an XPath search engine.
Overview
The XML Engine is a complete rewrite and consolidation of legacy XML extensions (xml-xpath, xml-element-indexer) into a single cohesive, high-performance architecture. By ditching slow DOM-based parsers in favor of a custom Regex-based token streaming engine, this extension operates instantly on massive XML documents without locking up the VS Code UI.
Requirements
- VS Code 1.74+
- Node.js 18+
Installation
- Clone or copy this extension to your local machine
- Open the folder in VS Code
- Press
F5 to launch the extension in debug mode
Or package as a VSIX:
npm install -g @vscode/vsce
vsce package
Features
- Blazing Fast Tokenizer: Custom regex-based XML token stream parser that extracts tags, attributes, and text content while preserving byte-offsets. Skips CDATA and Comments automatically.
- Intelligent Indexing:
- Parent-Scoped Sibling Indexing: Standard XPath indexing where elements are numbered relative to their identical siblings under the same parent.
- Global Depth Indexing: Numbers elements based on their global depth position in the tree.
- Attribute-Based Partitioning: Numbers elements relative to a configured partitioning attribute (e.g.,
[@id='foo'][1]).
- Robust XPath Generation:
- Absolute XPath: Generates precise positional paths like
/catalog[1]/book[2]/title[1].
- Successor-Predicate XPath: Generates smart, human-readable descendant paths using landmark attributes or identifying children (e.g.,
//book[@id='b1']//title).
- Child-Predicate XPath: Uses child elements as predicates for precise identification (e.g.,
//book[title='Clean Code']/author).
- XPath Search Engine: A fully custom, dependency-free XPath 1.0 subset evaluator that executes lightning-fast searches against the token stream.
- VS Code Presentation Layer:
- Live UI Badges: Injects
[1], [2] inline text editor decorations using window.createTextEditorDecorationType.
- Status Bar: Displays the XPath of the element currently under the cursor.
- Tree View: A sidebar explorer showing the XML structure combined with the engine's indices.
- Hover Provider: Markdown popups on tag hover displaying the XPath and a direct "Copy" action.
- CodeLens: Injects inline "Copy XPath" actions above important tags or virtual roots.
- Search QuickPick: A live search interface to query and navigate to XPath matches.
Usage
Basic Usage
- Open any XML file in VS Code
- The extension automatically indexes elements
- Element indices appear inline (e.g.,
[1], [2])
- The status bar shows the XPath at cursor position
Commands
| Command |
Shortcut |
Description |
xmlEngine.toggleMode |
Ctrl+Shift+X Ctrl+Shift+M |
Cycle through indexing modes |
xmlEngine.copyXPath |
Ctrl+Shift+C |
Copy XPath to clipboard |
xmlEngine.searchXPath |
Ctrl+Shift+F |
Search with XPath |
xmlEngine.refresh |
Ctrl+Shift+X Ctrl+Shift+F |
Refresh index |
xmlEngine.setVirtualRoot |
Ctrl+Shift+X Ctrl+Shift+R |
Set virtual root element |
xmlEngine.toggleEnabled |
— |
Enable/disable extension |
Indexing Modes
- full: Index all elements in the document
- cursor: Index elements around the cursor only
- inline: Index elements as you type
- range: Index elements within a configurable range
XPath Generation Strategies
Absolute (default):
/catalog[1]/book[2]/title[1]
Child-Predicate:
//book[title='Clean Code'][author='Robert Martin']/isbn
Configuration
The extension is highly configurable via standard VS Code settings (settings.json):
General Settings
| Setting |
Type |
Default |
Description |
xmlEngine.enabled |
boolean |
true |
Enable/disable the extension |
xmlEngine.mode |
string |
cursor |
Indexing mode (full, cursor, inline, range) |
xmlEngine.enableIndexer |
boolean |
true |
Enable positional indexing |
XPath Generation
| Setting |
Type |
Default |
Description |
xmlEngine.xpathGenerationStrategy |
string |
child-predicate |
Strategy (absolute, child-predicate) |
xmlEngine.preferredAttributes |
array |
['id', 'type', 'name'] |
Attributes for predicates |
xmlEngine.childPredicateIdentifyingChildren |
array |
['title', 'name', 'id', 'key', 'value'] |
Child tags for predicates |
xmlEngine.childPredicateMaxDepth |
number |
3 |
Max predicate depth |
xmlEngine.useDescendantAxis |
array |
[] |
Elements using // instead of / |
Indexing Options
| Setting |
Type |
Default |
Description |
xmlEngine.skipSingleIndex |
boolean |
false |
Omit [1] for only children |
xmlEngine.forceIndexOneFor |
array |
[] |
Tags that always emit [1] |
xmlEngine.ignoreIndexTags |
array |
[] |
Tags that never receive index |
xmlEngine.disableLeafIndex |
boolean |
false |
Don't index leaf nodes |
Visual Options
| Setting |
Type |
Default |
Description |
xmlEngine.indexPrefix |
string |
▶ |
Prefix for index display |
xmlEngine.indexFormat |
string |
tag |
Format (tag, number, short) |
xmlEngine.indexColor |
string |
#7ec699 |
Index badge color |
xmlEngine.hideLeafNodeLabels |
boolean |
false |
Hide labels on leaf nodes |
| Setting |
Type |
Default |
Description |
xmlEngine.enableCache |
boolean |
true |
Enable LRU caching |
xmlEngine.cacheSize |
number |
50 |
Max cached documents |
xmlEngine.largeFileThreshold |
number |
5000 |
Lines for large file warning |
xmlEngine.refreshDelay |
number |
300 |
Debounce delay (ms) |
Example Configuration
{
"xmlEngine.enabled": true,
"xmlEngine.mode": "cursor",
"xmlEngine.xpathGenerationStrategy": "child-predicate",
"xmlEngine.preferredAttributes": ["id", "type", "name", "key"],
"xmlEngine.childPredicateIdentifyingChildren": ["title", "name", "label", "id", "key", "value"],
"xmlEngine.indexColor": "#7ec699",
"xmlEngine.enableCache": true,
"xmlEngine.cacheSize": 100
}
Architecture
src/
├── engine/ # Core XML logic (headless)
│ ├── tokenizer.js # Regex-based XML parser
│ ├── indexer.js # Element indexing
│ ├── path/ # XPath generation
│ │ ├── absolute.js
│ │ └── child-predicate.js
│ └── search/ # XPath evaluator
├── vscode/ # VS Code integration
│ ├── extension.js # Entry point
│ ├── config-manager.js
│ ├── decoration-manager.js
│ ├── status-bar.js
│ ├── tree-view.js
│ ├── hover-provider.js
│ ├── search-ui.js
│ └── copy-lens.js
└── shared/ # Common utilities
├── constants.js
├── logger.js
└── debug.js
Development
Install dependencies:
npm install
Run tests:
npm run test
Run integration tests:
npm run test:integration
Debug the extension:
- Press
F5 in VS Code to launch extension host
- Open an XML file to test
Keybindings
All keybindings require the editor to be an XML language file (xml, xsl, xsd, wsdl, xaml, svg, xhtml):
| Shortcut |
Command |
Ctrl+Shift+X Ctrl+Shift+M |
Toggle Mode |
Ctrl+Shift+X Ctrl+Shift+R |
Set Virtual Root |
Ctrl+Shift+X Ctrl+Shift+C |
Clear Virtual Root |
Ctrl+Shift+X Ctrl+Shift+Q |
Quick Actions |
Ctrl+Shift+X Ctrl+Shift+F |
Refresh |
Ctrl+Shift+X Ctrl+Shift+V |
Copy Leaf Value |
Ctrl+Shift+C |
Copy XPath (when XML) |
Ctrl+Shift+F |
Search XPath (when XML) |
Language Support
The extension activates for these languages:
- XML (
.xml)
- XSL (
.xsl, .xslt)
- XSD (
.xsd)
- WSDL (
.wsdl)
- XAML (
.xaml)
- SVG (
.svg)
- XHTML (
.xhtml)
License
MIT