{"id":28471890,"url":"https://github.com/designliquido/xpath","last_synced_at":"2026-07-31T09:31:42.946Z","repository":{"id":297543062,"uuid":"997101096","full_name":"DesignLiquido/xpath","owner":"DesignLiquido","description":"Our XPath implementation in TypeScript","archived":false,"fork":false,"pushed_at":"2026-04-28T15:51:46.000Z","size":963,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-28T17:29:34.074Z","etag":null,"topics":["javascript","typescript","xpath"],"latest_commit_sha":null,"homepage":"https://designliquido.github.io/xpath/","language":"TypeScript","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/DesignLiquido.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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-06-06T00:48:14.000Z","updated_at":"2026-04-28T15:51:51.000Z","dependencies_parsed_at":"2025-06-06T02:45:25.723Z","dependency_job_id":"f8b2843d-45b1-41b8-8f1e-eea5bd2c5eb2","html_url":"https://github.com/DesignLiquido/xpath","commit_stats":null,"previous_names":["designliquido/xpath"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/DesignLiquido/xpath","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DesignLiquido%2Fxpath","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DesignLiquido%2Fxpath/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DesignLiquido%2Fxpath/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DesignLiquido%2Fxpath/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DesignLiquido","download_url":"https://codeload.github.com/DesignLiquido/xpath/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DesignLiquido%2Fxpath/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":36114483,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-07-20T02:08:10.276Z","status":"online","status_checked_at":"2026-07-31T02:00:06.731Z","response_time":112,"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":["javascript","typescript","xpath"],"created_at":"2025-06-07T11:09:18.744Z","updated_at":"2026-07-31T09:31:42.875Z","avatar_url":"https://github.com/DesignLiquido.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# xpath\n\nOur XPath implementation in TypeScript.\n\n## Current Status\n\n- **XPath 1.0**: ✅ Fully implemented and tested\n- **XPath 2.0/3.0/3.1**: ✅ Fully implemented, including maps, arrays, and JSON support (99.9% test pass rate)\n\n## Features\n\n### Core Capabilities\n\n- **Pure TypeScript**: Written in strictly typed TypeScript for robustness and ease of use.\n- **Supported Versions**: Full support for XPath 1.0, 2.0, 3.0, and 3.1.\n- **Extensible**: Custom function support and XSLT Extensions API.\n- **Isomorphic**: Runs in Node.js and modern browsers.\n\n### XPath 3.1 \u0026 JSON Support\n\n- **Maps \u0026 Arrays**: Native support for XDM Maps and Arrays, fully interoperable with JSON.\n- **JSON Functions**: `parse-json` (with liberal mode support), `json-to-xml`, `xml-to-json`.\n- **Lookup Operator**: Drill down into data structures using the `?` operator (e.g., `$data?users?1?name`).\n- **Constructors**: Create maps and arrays using `map { ... }` and `array { ... }` (or square brackets `[]`).\n\n### Advanced Expressions\n\n- **Arrow Operator (`=\u003e`)**: Chain function calls for cleaner code (e.g., `$str =\u003e upper-case() =\u003e normalize-space()`).\n- **String Templates**: Interpolated strings using backticks (`` `Hello {$name}` ``).\n- **Inline Functions**: Define anonymous functions/lambdas (e.g., `function($x) { $x * 2 }`).\n- **Range Operator**: Generate sequences easily with `1 to 10`.\n- **Control Flow**: Support for `if/then/else`, `for`, `some/every` quantifiers, and `try/catch`.\n\n### Schema \u0026 Types\n\n- **Schema-Awareness**: Full support for validating nodes against XML Schemas and handling typed values.\n- **Type Checking**: Advanced type system handling `instance of`, `castable as`, and `treat as`.\n- **Union Types**: Support for complex type definitions and checking.\n\n### Performance \u0026 Streaming\n\n- **Streaming Evaluation**: Capable of processing large documents with low memory footprint using XSLT 3.0 capabilities (posture and sweep analysis).\n- **Profiler**: Built-in expression profiler to analyze execution time and memory usage.\n- **Optimizer**: Static analysis tools to suggest query optimizations.\n\n### Enhanced Function Library\n\n- **Regular Expressions**: Full XPath regex support including flags (`i`, `m`, `s`, `x`) and `analyze-string`.\n- **Date/Time**: Comprehensive duration, date, and time manipulation.\n- **Environment**: Access system environment variables via `fn:environment-variable`.\n- **Node Functions**: Advanced node operations like `generate-id`, `path`, `innermost`, and `outermost`.\n- **Higher-Order Functions**: Functional programming with `map`, `filter`, `fold-left`, `fold-right`, and `sort`.\n\n## Documentation\n\nComprehensive documentation is available:\n\n- **[API Documentation](https://designliquido.github.io/xpath/)** - Auto-generated TypeDoc API reference (published via GitHub Pages)\n- **[Interactive XPath Tester](https://designliquido.github.io/xpath/xpath-tester.html)** - Test XPath expressions in your browser\n- **[Custom Selectors](#custom-selectors)** - Integrate XPath with custom DOM implementations\n- **[XSLT Extensions API](#xslt-extensions-api)** - Extend XPath with XSLT functions\n- **[XPath Version Support](XPATH-VERSIONS.md)** - Infrastructure for XPath 2.0/3.0/3.1\n- **[Migration Guide](docs/guides/XPATH-MIGRATION-GUIDE.md)** - Upgrading from XPath 1.0 to 2.0\n- **[Incompatibilities Guide](docs/guides/XPATH-INCOMPATIBILITIES.md)** - Known version differences\n\n### Building Documentation\n\n```bash\n# Generate TypeDoc documentation\nyarn docs\n\n# Watch for changes and regenerate\nyarn docs:watch\n```\n\nDocumentation is automatically built and published to GitHub Pages on every push to the main branch.\n\n## Motivation\n\nWe maintain another open source package called [`xslt-processor`](https://github.com/DesignLiquido/xslt-processor). The XPath component the project had became impossible to maintain due to a variety of reasons. `xslt-processor` uses this project as a submodule since its version 4.\n\nThis repository is intended to solve a particular problem in our packages, but it can be used by any other NPM package.\n\n## Quick Start\n\n```typescript\nimport { XPath10Parser, XPathLexer, createContext } from '@designliquido/xpath';\n\n// Create parser and lexer for XPath 1.0\nconst parser = new XPath10Parser();\nconst lexer = new XPathLexer('1.0');\n\n// Parse an XPath expression\nconst tokens = lexer.scan('//book[price \u003e 30]/title');\nconst expression = parser.parse(tokens);\n\n// Evaluate against your DOM\nconst context = createContext(documentNode);\nconst result = expression.evaluate(context);\n```\n\n## Choosing XPath Version\n\nThis library supports multiple XPath versions. Choose the appropriate parser and lexer configuration based on your needs.\n\n### XPath 1.0 (Default)\n\nFor XPath 1.0 expressions (XSLT 1.0 compatibility):\n\n```typescript\nimport { XPath10Parser, XPathLexer, createContext } from '@designliquido/xpath';\n\n// Explicit version\nconst lexer = new XPathLexer('1.0');\nconst parser = new XPath10Parser();\n\n// Or use defaults (both default to 1.0)\nconst lexer = new XPathLexer();\nconst parser = new XPath10Parser();\n\nconst tokens = lexer.scan('//book[@price \u003e 30]');\nconst ast = parser.parse(tokens);\n```\n\n### XPath 2.0\n\nFor XPath 2.0 expressions with conditionals, for expressions, and quantified expressions:\n\n```typescript\nimport { XPath20Parser, XPathLexer, createContext } from '@designliquido/xpath';\n\n// IMPORTANT: Use matching versions for lexer and parser\nconst lexer = new XPathLexer('2.0'); // Recognizes 'if', 'then', 'else', 'for', etc.\nconst parser = new XPath20Parser();\n\n// if-then-else expressions\nconst tokens1 = lexer.scan(\"if ($price \u003e 100) then 'expensive' else 'affordable'\");\nconst ast1 = parser.parse(tokens1);\n\n// for expressions\nconst tokens2 = lexer.scan('for $x in (1, 2, 3) return $x * 2');\nconst ast2 = parser.parse(tokens2);\n\n// quantified expressions\nconst tokens3 = lexer.scan('some $x in //item satisfies $x/@stock \u003e 0');\nconst ast3 = parser.parse(tokens3);\n```\n\n### Using the Factory Function\n\nFor automatic parser selection based on version:\n\n```typescript\nimport { createXPathParser, XPathLexer } from '@designliquido/xpath';\n\n// Create parser for specific version\nconst parser10 = createXPathParser('1.0');\nconst parser20 = createXPathParser('2.0');\n\n// With options\nconst parser = createXPathParser('1.0', {\n    enableNamespaceAxis: true,\n});\n```\n\n### Lexer Version Differences\n\nThe lexer version determines how certain keywords are tokenized:\n\n| Keyword  | XPath 1.0                 | XPath 2.0     |\n| -------- | ------------------------- | ------------- |\n| `if`     | Identifier (element name) | Reserved word |\n| `then`   | Identifier (element name) | Reserved word |\n| `else`   | Identifier (element name) | Reserved word |\n| `for`    | Identifier (element name) | Reserved word |\n| `return` | Identifier (element name) | Reserved word |\n| `some`   | Identifier (element name) | Reserved word |\n| `every`  | Identifier (element name) | Reserved word |\n\n**Important:** Always match your lexer and parser versions. Using an XPath 1.0 lexer with an XPath 2.0 parser will cause parsing errors for 2.0-specific syntax.\n\n### XPath Version Reference\n\nFor detailed information about version-specific features and the implementation roadmap, see:\n\n- **[XPATH-VERSIONS.md](XPATH-VERSIONS.md)** - Version support infrastructure and feature flags\n- **[Migration Guide](docs/guides/XPATH-MIGRATION-GUIDE.md)** - Upgrading from XPath 1.0 to 2.0\n\n## Custom Selectors\n\nYou can implement custom selectors by wrapping the XPath parser and lexer. This is useful when you need to integrate XPath with your own DOM implementation.\n\n### Basic Implementation\n\nHere's how to create a custom selector class:\n\n```typescript\nimport { XPathLexer } from './lexer';\nimport { XPath10Parser } from './parser';\nimport { createContext } from './context';\nimport { XPathNode } from './node';\n\nexport class CustomXPathSelector {\n    private lexer: XPathLexer;\n    private parser: XPath10Parser;\n    private nodeCache: WeakMap\u003cYourNodeType, XPathNode\u003e = new WeakMap();\n\n    constructor() {\n        // Use XPath 1.0 for most DOM use cases\n        this.lexer = new XPathLexer('1.0');\n        this.parser = new XPath10Parser();\n    }\n\n    public select(expression: string, contextNode: YourNodeType): YourNodeType[] {\n        // 1. Tokenize the XPath expression\n        const tokens = this.lexer.scan(expression);\n\n        // 2. Parse tokens into an AST\n        const ast = this.parser.parse(tokens);\n\n        // 3. Clear cache for each selection\n        this.nodeCache = new WeakMap();\n\n        // 4. Convert your node to XPathNode\n        const xpathNode = this.convertToXPathNode(contextNode);\n\n        // 5. Create context and evaluate\n        const context = createContext(xpathNode);\n        const result = ast.evaluate(context);\n\n        // 6. Convert results back to your node type\n        return this.convertResult(result);\n    }\n}\n```\n\n### Node Conversion\n\nThe key to custom selectors is converting between your DOM nodes and XPathNode format:\n\n```typescript\nprivate convertToXPathNode(node: YourNodeType): XPathNode {\n    // Check cache to avoid infinite recursion\n    const cached = this.nodeCache.get(node);\n    if (cached) return cached;\n\n    // Filter out attribute nodes (nodeType = 2) from children\n    const childNodes = node.childNodes || [];\n    const attributes = childNodes.filter(n =\u003e n.nodeType === 2);\n    const elementChildren = childNodes.filter(n =\u003e n.nodeType !== 2);\n\n    // Create XPathNode BEFORE converting children to prevent infinite recursion\n    const xpathNode: XPathNode = {\n        nodeType: this.getNodeType(node),\n        nodeName: node.nodeName || '#document',\n        localName: node.localName || node.nodeName,\n        namespaceUri: node.namespaceUri || null,\n        textContent: node.nodeValue,\n        parentNode: null, // Avoid cycles\n        childNodes: [], // Will be populated\n        attributes: [], // Will be populated\n        nextSibling: null,\n        previousSibling: null,\n        ownerDocument: null\n    };\n\n    // Cache BEFORE converting children\n    this.nodeCache.set(node, xpathNode);\n\n    // NOW convert children and attributes\n    xpathNode.childNodes = elementChildren.map(child =\u003e\n        this.convertToXPathNode(child)\n    );\n    xpathNode.attributes = attributes.map(attr =\u003e\n        this.convertToXPathNode(attr)\n    );\n\n    return xpathNode;\n}\n```\n\n### Node Type Mapping\n\nMap your node types to standard DOM node types:\n\n```typescript\nprivate getNodeType(node: YourNodeType): number {\n    if (node.nodeType !== undefined) return node.nodeType;\n\n    // Map node names to standard node types\n    switch (node.nodeName?.toLowerCase()) {\n        case '#text':\n            return 3; // TEXT_NODE\n        case '#comment':\n            return 8; // COMMENT_NODE\n        case '#document':\n            return 9; // DOCUMENT_NODE\n        case '#document-fragment':\n            return 11; // DOCUMENT_FRAGMENT_NODE\n        default:\n            return 1; // ELEMENT_NODE\n    }\n}\n```\n\n### Result Conversion\n\nConvert XPath results back to your node type:\n\n```typescript\nprivate convertResult(result: any): YourNodeType[] {\n    if (Array.isArray(result)) {\n        return result.map(node =\u003e this.convertFromXPathNode(node));\n    }\n\n    if (result \u0026\u0026 typeof result === 'object' \u0026\u0026 'nodeType' in result) {\n        return [this.convertFromXPathNode(result)];\n    }\n\n    return [];\n}\n\nprivate convertFromXPathNode(xpathNode: XPathNode): YourNodeType {\n    return {\n        nodeType: xpathNode.nodeType,\n        nodeName: xpathNode.nodeName,\n        localName: xpathNode.localName,\n        namespaceUri: xpathNode.namespaceUri,\n        nodeValue: xpathNode.textContent,\n        parent: xpathNode.parentNode ?\n            this.convertFromXPathNode(xpathNode.parentNode) : undefined,\n        children: xpathNode.childNodes ?\n            Array.from(xpathNode.childNodes).map(child =\u003e\n                this.convertFromXPathNode(child)) : undefined,\n        attributes: xpathNode.attributes ?\n            Array.from(xpathNode.attributes).map(attr =\u003e\n                this.convertFromXPathNode(attr)) : undefined,\n        nextSibling: xpathNode.nextSibling ?\n            this.convertFromXPathNode(xpathNode.nextSibling) : undefined,\n        previousSibling: xpathNode.previousSibling ?\n            this.convertFromXPathNode(xpathNode.previousSibling) : undefined\n    } as YourNodeType;\n}\n```\n\n### Usage Example\n\n```typescript\nconst selector = new CustomXPathSelector();\n\n// Select all book elements\nconst books = selector.select('//book', documentNode);\n\n// Select books with price \u003e 30\nconst expensiveBooks = selector.select('//book[price \u003e 30]', documentNode);\n\n// Select first book title\nconst firstTitle = selector.select('//book[1]/title', documentNode);\n```\n\n### Key Considerations\n\n1. **Caching**: Use WeakMap to cache node conversions and prevent memory leaks\n2. **Recursion**: Cache nodes BEFORE converting children to avoid infinite loops\n3. **Attributes**: Filter attributes (nodeType = 2) separately from element children\n4. **Null Safety**: Handle null/undefined values when converting between node types\n5. **Performance**: Clear the cache between selections to avoid stale references\n\nFor a complete working example, see the [XPathSelector implementation in xslt-processor](https://github.com/DesignLiquido/xslt-processor/blob/main/src/xpath/selector.ts).\n\n## XSLT Extensions API\n\nThis library provides a pure **XPath 1.0** implementation. However, it also includes a clean integration API for XSLT-specific functions, allowing the `xslt-processor` package (or any other XSLT implementation) to extend XPath with XSLT 1.0 functions like `document()`, `key()`, `format-number()`, `generate-id()`, and others.\n\n### Architecture\n\nThe XSLT Extensions API follows a **separation of concerns** pattern:\n\n- **This package (`@designliquido/xpath`)**: Provides type definitions, interfaces, and integration hooks\n- **XSLT processor packages**: Implement the actual XSLT function logic\n\nThis approach keeps the XPath library pure while enabling XSLT functionality through a well-defined extension mechanism.\n\n### Key Features\n\n1. **Type Definitions**: `XSLTExtensions`, `XSLTExtensionFunction`, `XSLTFunctionMetadata` interfaces\n2. **Parser Integration**: `XPathBaseParser` accepts `options.extensions` parameter\n3. **Lexer Support**: `XPathLexer.registerFunctions()` for dynamic function registration\n4. **Context Integration**: Extension functions receive `XPathContext` as first parameter\n\n### Basic Usage\n\nHere's how to use XSLT extensions (typically done by the `xslt-processor` package):\n\n```typescript\nimport {\n    XPath10Parser,\n    XPathLexer,\n    XSLTExtensions,\n    XSLTFunctionMetadata,\n    getExtensionFunctionNames,\n    XPathContext,\n} from '@designliquido/xpath';\n\n// Define XSLT extension functions\nconst xsltFunctions: XSLTFunctionMetadata[] = [\n    {\n        name: 'generate-id',\n        minArgs: 0,\n        maxArgs: 1,\n        implementation: (context: XPathContext, nodeSet?: any[]) =\u003e {\n            const node = nodeSet?.[0] || context.node;\n            return `id-${generateUniqueId(node)}`;\n        },\n        description: 'Generate unique identifier for a node',\n    },\n    {\n        name: 'system-property',\n        minArgs: 1,\n        maxArgs: 1,\n        implementation: (context: XPathContext, propertyName: string) =\u003e {\n            const properties = {\n                'xsl:version': '1.0',\n                'xsl:vendor': 'Design Liquido XPath',\n                'xsl:vendor-url': 'https://github.com/designliquido/xpath',\n            };\n            return properties[String(propertyName)] || '';\n        },\n        description: 'Query XSLT processor properties',\n    },\n];\n\n// Create extensions bundle\nconst extensions: XSLTExtensions = {\n    functions: xsltFunctions,\n    version: '1.0',\n};\n\n// Create parser with extensions (XPath 1.0 for XSLT 1.0 compatibility)\nconst parser = new XPath10Parser({ extensions });\n\n// Create lexer and register extension functions\nconst lexer = new XPathLexer('1.0');\nlexer.registerFunctions(getExtensionFunctionNames(extensions));\n\n// Parse expression\nconst tokens = lexer.scan('generate-id()');\nconst expression = parser.parse(tokens);\n\n// Create context with extension functions\nconst context: XPathContext = {\n    node: rootNode,\n    functions: {\n        'generate-id': xsltFunctions[0].implementation,\n        'system-property': xsltFunctions[1].implementation,\n    },\n};\n\n// Evaluate\nconst result = expression.evaluate(context);\n```\n\n### Extension Function Signature\n\nXSLT extension functions receive the evaluation context as their first parameter:\n\n```typescript\ntype XSLTExtensionFunction = (context: XPathContext, ...args: any[]) =\u003e any;\n```\n\nThis allows extension functions to access:\n\n- `context.node` - current context node\n- `context.position` - position in node-set (1-based)\n- `context.size` - size of current node-set\n- `context.variables` - XPath variables\n- `context.functions` - other registered functions\n\n### Available Helper Functions\n\n```typescript\n// Validate extensions bundle for errors\nconst errors = validateExtensions(extensions);\nif (errors.length \u003e 0) {\n    console.error('Extension validation errors:', errors);\n}\n\n// Extract function names for lexer registration\nconst functionNames = getExtensionFunctionNames(extensions);\nlexer.registerFunctions(functionNames);\n\n// Create empty extensions bundle\nconst emptyExtensions = createEmptyExtensions('1.0');\n```\n\n### XSLT 1.0 Functions\n\nThe following XSLT 1.0 functions are designed to be implemented via this extension API:\n\n1. **`document()`** - Load external XML documents\n2. **`key()`** - Efficient node lookup using keys\n3. **`format-number()`** - Number formatting with patterns\n4. **`generate-id()`** - Generate unique node identifiers\n5. **`unparsed-entity-uri()`** - Get URI of unparsed entities\n6. **`system-property()`** - Query processor properties\n7. **`element-available()`** - Check XSLT element availability\n8. **`function-available()`** - Check function availability\n\nFor detailed implementation guidance, see [TODO.md](TODO.md).\n\n### Context Extensions\n\nXSLT functions may require additional context data beyond standard XPath context:\n\n```typescript\nconst context: XPathContext = {\n    node: rootNode,\n    functions: {\n        'generate-id': generateIdImpl,\n        key: keyImpl,\n        'format-number': formatNumberImpl,\n    },\n    // XSLT-specific context extensions\n    xsltVersion: '1.0',\n    // For key() function\n    keys: {\n        'employee-id': { match: 'employee', use: '@id' },\n    },\n    // For document() function\n    documentLoader: (uri: string) =\u003e loadXmlDocument(uri),\n    // For format-number() function\n    decimalFormats: {\n        euro: { decimalSeparator: ',', groupingSeparator: '.' },\n    },\n    // For system-property() function\n    systemProperties: {\n        'xsl:version': '1.0',\n        'xsl:vendor': 'Design Liquido',\n    },\n};\n```\n\n### Complete Example\n\nFor a complete implementation example, see the test suite at [https://github.com/DesignLiquido/xpath/blob/main/tests/xslt-extensions.test.ts](tests/xslt-extensions.test.ts), which demonstrates:\n\n- Creating and validating extension bundles\n- Registering extensions with parser and lexer\n- Implementing sample XSLT functions (`generate-id`, `system-property`)\n- End-to-end evaluation with extension functions\n\n## API Migration Guide\n\nThis section documents changes to the API and how to migrate from older versions.\n\n### Migrating to Versioned Parser/Lexer API\n\nPrior versions used abstract or unversioned parser/lexer classes. The new API uses explicit versioned classes for better clarity and type safety.\n\n#### Parser Migration\n\n```typescript\n// OLD (deprecated):\nimport { XPathBaseParser } from '@designliquido/xpath';\nconst parser = new XPathBaseParser(); // Error: XPathBaseParser is abstract\n\n// NEW (recommended):\nimport { XPath10Parser } from '@designliquido/xpath';\nconst parser = new XPath10Parser();\n\n// Or use the factory:\nimport { createXPathParser } from '@designliquido/xpath';\nconst parser = createXPathParser('1.0');\n```\n\n#### Lexer Migration\n\n```typescript\n// OLD (may have defaulted to 2.0):\nimport { XPathLexer } from '@designliquido/xpath';\nconst lexer = new XPathLexer(); // Was defaulting to '2.0'\n\n// NEW (explicit version, defaults to 1.0):\nimport { XPathLexer } from '@designliquido/xpath';\nconst lexer = new XPathLexer('1.0'); // Explicit XPath 1.0\n\n// Or with options object:\nconst lexer = new XPathLexer({ version: '1.0' });\n```\n\n#### Breaking Change: Lexer Default Version\n\n**Important:** The lexer default version has changed from `'2.0'` to `'1.0'` for backward compatibility with XPath 1.0/XSLT 1.0 use cases.\n\nIf your code relied on the old default and uses XPath 2.0 features, update your lexer instantiation:\n\n```typescript\n// If you were using XPath 2.0 features with the old default:\nconst lexer = new XPathLexer(); // OLD: defaulted to 2.0\n\n// Update to explicit 2.0:\nconst lexer = new XPathLexer('2.0');\n```\n\n#### Quick Reference\n\n| Old API                                   | New API                                             |\n| ----------------------------------------- | --------------------------------------------------- |\n| `new XPathBaseParser()`                   | `new XPath10Parser()` or `createXPathParser('1.0')` |\n| `new XPathBaseParser({ version: '2.0' })` | `new XPath20Parser()` or `createXPathParser('2.0')` |\n| `new XPathLexer()` (was 2.0)              | `new XPathLexer('1.0')` (now 1.0)                   |\n| `new XPathLexer('2.0')`                   | `new XPathLexer('2.0')` (unchanged)                 |\n\n#### Compatibility Alias\n\nFor gradual migration, `XPathParser` is available as an alias for `XPath10Parser`:\n\n```typescript\nimport { XPathParser } from '@designliquido/xpath';\nconst parser = new XPathParser(); // Same as new XPath10Parser()\n```\n\nThis alias is deprecated and will be removed in a future major version. Prefer using `XPath10Parser` directly.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdesignliquido%2Fxpath","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdesignliquido%2Fxpath","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdesignliquido%2Fxpath/lists"}