{"_id":"path-expression-matcher","_rev":"13-faff887991d5bc62d6af8d73cd2f870e","name":"path-expression-matcher","dist-tags":{"latest":"1.6.2"},"versions":{"1.0.0":{"name":"path-expression-matcher","version":"1.0.0","keywords":["xml","json","yaml","path","matcher","pattern","xpath","selector","parser","fast-xml-parser","fast-xml-builder"],"author":{"url":"https://solothought.com","name":"Amit Gupta"},"license":"MIT","_id":"path-expression-matcher@1.0.0","maintainers":[{"name":"amitgupta","email":"amitgupta.gwl@gmail.com"}],"homepage":"https://github.com/NaturalIntelligence/path-expression-matcher#readme","bugs":{"url":"https://github.com/NaturalIntelligence/path-expression-matcher/issues"},"dist":{"shasum":"9f61d5411f33d46b063fd4ae53737121d0c0b940","tarball":"https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.0.0.tgz","fileCount":6,"integrity":"sha512-6SYE3bPfULK4jZ7veRtG1fmrsGV36+XcvZQxrjnp32Xv1gC1de5Jih9kvb6dZThRXEdfZgTEIXHRMQnO8E5xXg==","signatures":[{"sig":"MEUCIHAtNmoJYRIbBJVK8CfaWpMhwR0sR1rgBvoK+Lu54WBUAiEA2H0IXswTUIbbUn0FWgLpiODruXvhnI1pdLdCJN0Ida0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":30351},"main":"src/index.js","type":"module","engines":{"node":">=14.0.0"},"exports":{".":"./src/index.js","./Matcher":"./src/Matcher.js","./Expression":"./src/Expression.js"},"funding":[{"url":"https://github.com/sponsors/NaturalIntelligence","type":"github"}],"gitHead":"9d44b9ca749a44a142aca2ed18f0b2d85e299bbf","scripts":{"test":"node test/test.js"},"_npmUser":{"name":"amitgupta","email":"amitgupta.gwl@gmail.com"},"repository":{"url":"git+https://github.com/NaturalIntelligence/path-expression-matcher.git","type":"git"},"_npmVersion":"11.11.0","description":"Efficient path tracking and pattern matching for XML/JSON parsers","directories":{},"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/path-expression-matcher_1.0.0_1772803815285_0.5097220061166832","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"path-expression-matcher","version":"1.1.0","keywords":["xml","json","yaml","path","matcher","pattern","xpath","selector","parser","fast-xml-parser","fast-xml-builder"],"author":{"url":"https://solothought.com","name":"Amit Gupta"},"license":"MIT","_id":"path-expression-matcher@1.1.0","maintainers":[{"name":"amitgupta","email":"amitgupta.gwl@gmail.com"}],"homepage":"https://github.com/NaturalIntelligence/path-expression-matcher#readme","bugs":{"url":"https://github.com/NaturalIntelligence/path-expression-matcher/issues"},"dist":{"shasum":"9a85509a5a5224bedc7792dba3e6375954105979","tarball":"https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.1.0.tgz","fileCount":6,"integrity":"sha512-dQleLfQnm6qDIV4jYwJINXlWXIA++oi+ZlXDx5UyksP2AICml71s7yKKfpJ7wk51/70spXcnM6C9S1YfoPxYPA==","signatures":[{"sig":"MEUCIEtSOlAQe7T8OGVRMLLhKXs2UnuPHBjePIni/hKOKW3iAiEAkiIxAH0tfPAsWUE2wG/wwHAIBYmgwdk9XRZ1XKWDyjc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":37316},"main":"src/index.js","type":"module","engines":{"node":">=14.0.0"},"exports":{".":"./src/index.js","./Matcher":"./src/Matcher.js","./Expression":"./src/Expression.js"},"funding":[{"url":"https://github.com/sponsors/NaturalIntelligence","type":"github"}],"gitHead":"7a69dc95231939bd677485fb9c98b85a36bb6888","scripts":{"test":"node test/namespace_test.js && node test/test.js"},"_npmUser":{"name":"amitgupta","email":"amitgupta.gwl@gmail.com"},"repository":{"url":"git+https://github.com/NaturalIntelligence/path-expression-matcher.git","type":"git"},"_npmVersion":"11.11.0","description":"Efficient path tracking and pattern matching for XML/JSON parsers","directories":{},"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/path-expression-matcher_1.1.0_1773098062011_0.3291288493025948","host":"s3://npm-registry-packages-npm-production"}},"1.1.1":{"name":"path-expression-matcher","version":"1.1.1","keywords":["xml","json","yaml","path","matcher","pattern","xpath","selector","parser","fast-xml-parser","fast-xml-builder"],"author":{"url":"https://solothought.com","name":"Amit Gupta"},"license":"MIT","_id":"path-expression-matcher@1.1.1","maintainers":[{"name":"amitgupta","email":"amitgupta.gwl@gmail.com"}],"homepage":"https://github.com/NaturalIntelligence/path-expression-matcher#readme","bugs":{"url":"https://github.com/NaturalIntelligence/path-expression-matcher/issues"},"dist":{"shasum":"c1fd8583ecedb74694b886c5e1715be053c05541","tarball":"https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.1.1.tgz","fileCount":6,"integrity":"sha512-NC1UVEpK8euainhgyX0UTmM0mSkWsEctNd39cjOAa8Tx424ZUpoPKcSPssPrCVDlhyjIYw7j6v36bqHxct9Xzg==","signatures":[{"sig":"MEQCIFMGq1J/rLHQayaGJMAUzv4wu3IR/S/8etA5j4pYWgj7AiBv16XNyaALz4Wxcq2D79upJVwCymb6O7rIUacLQsEI0g==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":37891},"main":"src/index.js","type":"module","engines":{"node":">=14.0.0"},"exports":{".":"./src/index.js","./Matcher":"./src/Matcher.js","./Expression":"./src/Expression.js"},"funding":[{"url":"https://github.com/sponsors/NaturalIntelligence","type":"github"}],"gitHead":"2742694640f7831baa76fedac22262b480467fd8","scripts":{"test":"node test/namespace_test.js && node test/test.js"},"_npmUser":{"name":"amitgupta","email":"amitgupta.gwl@gmail.com"},"repository":{"url":"git+https://github.com/NaturalIntelligence/path-expression-matcher.git","type":"git"},"_npmVersion":"11.11.0","description":"Efficient path tracking and pattern matching for XML/JSON parsers","directories":{},"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/path-expression-matcher_1.1.1_1773099565101_0.5644758911509864","host":"s3://npm-registry-packages-npm-production"}},"1.1.2":{"name":"path-expression-matcher","version":"1.1.2","keywords":["xml","json","yaml","path","matcher","pattern","xpath","selector","parser","fast-xml-parser","fast-xml-builder"],"author":{"url":"https://solothought.com","name":"Amit Gupta"},"license":"MIT","_id":"path-expression-matcher@1.1.2","maintainers":[{"name":"amitgupta","email":"amitgupta.gwl@gmail.com"}],"homepage":"https://github.com/NaturalIntelligence/path-expression-matcher#readme","bugs":{"url":"https://github.com/NaturalIntelligence/path-expression-matcher/issues"},"dist":{"shasum":"0102f74415abf183857532acd78bb7ad6ff6fa00","tarball":"https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.1.2.tgz","fileCount":6,"integrity":"sha512-LXWqJmcpp2BKOEmgt4CyuESFmBfPuhJlAHKJsFzuJU6CxErWk75BrO+Ni77M9OxHN6dCYKM4vj+21Z6cOL96YQ==","signatures":[{"sig":"MEYCIQCsYYnMPUa72H60Ihdd+Am+0pFJ4eRkzgfqO7M6g1KWxgIhALk5LAd/vSK5EXjZ7lmTWwgnFVU1YWcYo5gs2LfH57VN","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":37747},"main":"src/index.js","type":"module","engines":{"node":">=14.0.0"},"exports":{".":"./src/index.js","./Matcher":"./src/Matcher.js","./Expression":"./src/Expression.js"},"funding":[{"url":"https://github.com/sponsors/NaturalIntelligence","type":"github"}],"gitHead":"c2ee2c56b603f3ad7c141c0e51501002c4bdfaaa","scripts":{"test":"node test/namespace_test.js && node test/test.js"},"_npmUser":{"name":"amitgupta","email":"amitgupta.gwl@gmail.com"},"repository":{"url":"git+https://github.com/NaturalIntelligence/path-expression-matcher.git","type":"git"},"_npmVersion":"11.11.0","description":"Efficient path tracking and pattern matching for XML/JSON parsers","directories":{},"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/path-expression-matcher_1.1.2_1773111051697_0.7567646605025329","host":"s3://npm-registry-packages-npm-production"}},"1.1.3":{"name":"path-expression-matcher","version":"1.1.3","keywords":["xml","json","yaml","path","matcher","pattern","xpath","selector","parser","fast-xml-parser","fast-xml-builder"],"author":{"url":"https://solothought.com","name":"Amit Gupta"},"license":"MIT","_id":"path-expression-matcher@1.1.3","maintainers":[{"name":"amitgupta","email":"amitgupta.gwl@gmail.com"}],"homepage":"https://github.com/NaturalIntelligence/path-expression-matcher#readme","bugs":{"url":"https://github.com/NaturalIntelligence/path-expression-matcher/issues"},"dist":{"shasum":"8bf7c629dc1b114e42b633c071f06d14625b4e0d","tarball":"https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.1.3.tgz","fileCount":11,"integrity":"sha512-qdVgY8KXmVdJZRSS1JdEPOKPdTiEK/pi0RkcT2sw1RhXxohdujUlJFPuS1TSkevZ9vzd3ZlL7ULl1MHGTApKzQ==","signatures":[{"sig":"MEUCIBqGd3SOWaIUW+y2cP8OHccawmUyuMl+9jkYCcIV3IJQAiEA6nJkT7Kep27vpigKrf50+/RqkOJ2ErrenAZsJ2O6TG4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":94470},"main":"./lib/pem.cjs","type":"module","types":"./src/index.d.ts","module":"./src/index.js","engines":{"node":">=14.0.0"},"exports":{".":{"import":{"types":"./src/index.d.ts","default":"./src/index.js"},"require":{"types":"./lib/pem.d.cts","default":"./lib/pem.cjs"}}},"funding":[{"url":"https://github.com/sponsors/NaturalIntelligence","type":"github"}],"gitHead":"bbf713e3a97d8137e1565259d5ada6dd67e6ea69","scripts":{"test":"c8 --reporter=lcov --reporter=text node test/namespace_test.js && c8 --reporter=lcov --reporter=text node test/test.js","bundle":"webpack --config webpack.cjs.config.js"},"_npmUser":{"name":"amitgupta","email":"amitgupta.gwl@gmail.com"},"repository":{"url":"git+https://github.com/NaturalIntelligence/path-expression-matcher.git","type":"git"},"_npmVersion":"11.11.0","description":"Efficient path tracking and pattern matching for XML/JSON parsers","directories":{},"sideEffects":false,"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"devDependencies":{"c8":"^10.1.3","eslint":"^8.3.0","webpack":"^5.64.4","prettier":"^3.5.1","typescript":"5","@babel/core":"^7.13.10","@types/node":"20","webpack-cli":"^4.9.1","babel-loader":"^8.2.2","@babel/register":"^7.13.8","@babel/preset-env":"^7.13.10","@babel/plugin-transform-runtime":"^7.13.10"},"_npmOperationalInternal":{"tmp":"tmp/path-expression-matcher_1.1.3_1773227651949_0.4204014454598046","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"path-expression-matcher","version":"1.2.0","keywords":["xml","json","yaml","path","matcher","pattern","xpath","selector","parser","fast-xml-parser","fast-xml-builder"],"author":{"url":"https://solothought.com","name":"Amit Gupta"},"license":"MIT","_id":"path-expression-matcher@1.2.0","maintainers":[{"name":"amitgupta","email":"amitgupta.gwl@gmail.com"}],"homepage":"https://github.com/NaturalIntelligence/path-expression-matcher#readme","bugs":{"url":"https://github.com/NaturalIntelligence/path-expression-matcher/issues"},"dist":{"shasum":"9bdae3787f43b0857b0269e9caaa586c12c8abee","tarball":"https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.2.0.tgz","fileCount":11,"integrity":"sha512-DwmPWeFn+tq7TiyJ2CxezCAirXjFxvaiD03npak3cRjlP9+OjTmSy1EpIrEbh+l6JgUundniloMLDQ/6VTdhLQ==","signatures":[{"sig":"MEUCIAxG3caw1B1u1LnKwoxNk1oovpQP3oh/d/plCmnwE6Y4AiEA695VrzJWTFM86REVyqCvOu9nrUlS+KiZjQduPqZ8l2M=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":115682},"main":"./lib/pem.cjs","type":"module","types":"./src/index.d.ts","module":"./src/index.js","engines":{"node":">=14.0.0"},"exports":{".":{"import":{"types":"./src/index.d.ts","default":"./src/index.js"},"require":{"types":"./lib/pem.d.cts","default":"./lib/pem.cjs"}}},"funding":[{"url":"https://github.com/sponsors/NaturalIntelligence","type":"github"}],"gitHead":"ee08b3bf81376b7fce9149ecf911b863341dfa9c","scripts":{"test":"c8 --reporter=lcov --reporter=text node test/*test.js","bundle":"webpack --config webpack.cjs.config.js"},"_npmUser":{"name":"amitgupta","email":"amitgupta.gwl@gmail.com"},"repository":{"url":"git+https://github.com/NaturalIntelligence/path-expression-matcher.git","type":"git"},"_npmVersion":"11.11.0","description":"Efficient path tracking and pattern matching for XML/JSON parsers","directories":{},"sideEffects":false,"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"devDependencies":{"c8":"^10.1.3","eslint":"^8.3.0","webpack":"^5.64.4","prettier":"^3.5.1","typescript":"5","@babel/core":"^7.13.10","@types/node":"20","webpack-cli":"^4.9.1","babel-loader":"^8.2.2","@babel/register":"^7.13.8","@babel/preset-env":"^7.13.10","@babel/plugin-transform-runtime":"^7.13.10"},"_npmOperationalInternal":{"tmp":"tmp/path-expression-matcher_1.2.0_1773973150184_0.048252377999925766","host":"s3://npm-registry-packages-npm-production"}},"1.2.1":{"name":"path-expression-matcher","version":"1.2.1","keywords":["xml","json","yaml","path","matcher","pattern","xpath","selector","parser","fast-xml-parser","fast-xml-builder"],"author":{"url":"https://solothought.com","name":"Amit Gupta"},"license":"MIT","_id":"path-expression-matcher@1.2.1","maintainers":[{"name":"amitgupta","email":"amitgupta.gwl@gmail.com"}],"homepage":"https://github.com/NaturalIntelligence/path-expression-matcher#readme","bugs":{"url":"https://github.com/NaturalIntelligence/path-expression-matcher/issues"},"dist":{"shasum":"04de63e98dcef3e07af8b12a41055466f200e291","tarball":"https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.2.1.tgz","fileCount":11,"integrity":"sha512-d7gQQmLvAKXKXE2GeP9apIGbMYKz88zWdsn/BN2HRWVQsDFdUY36WSLTY0Jvd4HWi7Fb30gQ62oAOzdgJA6fZw==","signatures":[{"sig":"MEYCIQC9qjmFRJqCFKpe7LvirCikNPqdELghqmlrO/XSeqxrqQIhAJaepBMMZay+t770Nk3zDNFRo4Sec6mqwKD77Uzxe2uZ","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":118103},"main":"./lib/pem.cjs","type":"module","types":"./src/index.d.ts","module":"./src/index.js","engines":{"node":">=14.0.0"},"exports":{".":{"import":{"types":"./src/index.d.ts","default":"./src/index.js"},"require":{"types":"./lib/pem.d.cts","default":"./lib/pem.cjs"}}},"funding":[{"url":"https://github.com/sponsors/NaturalIntelligence","type":"github"}],"gitHead":"83cb5afa0c2135ca189f560e6e5ab81e67365b4e","scripts":{"test":"c8 --reporter=lcov --reporter=text node test/*test.js","bundle":"webpack --config webpack.cjs.config.js"},"_npmUser":{"name":"amitgupta","email":"amitgupta.gwl@gmail.com"},"repository":{"url":"git+https://github.com/NaturalIntelligence/path-expression-matcher.git","type":"git"},"_npmVersion":"11.11.0","description":"Efficient path tracking and pattern matching for XML/JSON parsers","directories":{},"sideEffects":false,"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"devDependencies":{"c8":"^10.1.3","eslint":"^8.3.0","webpack":"^5.64.4","prettier":"^3.5.1","typescript":"5","@babel/core":"^7.13.10","@types/node":"20","webpack-cli":"^4.9.1","babel-loader":"^8.2.2","@babel/register":"^7.13.8","@babel/preset-env":"^7.13.10","@babel/plugin-transform-runtime":"^7.13.10"},"_npmOperationalInternal":{"tmp":"tmp/path-expression-matcher_1.2.1_1775187591102_0.0762754085351025","host":"s3://npm-registry-packages-npm-production"}},"1.3.0":{"name":"path-expression-matcher","version":"1.3.0","keywords":["xml","json","yaml","path","matcher","pattern","xpath","selector","parser","fast-xml-parser","fast-xml-builder"],"author":{"url":"https://solothought.com","name":"Amit Gupta"},"license":"MIT","_id":"path-expression-matcher@1.3.0","maintainers":[{"name":"amitgupta","email":"amitgupta.gwl@gmail.com"}],"homepage":"https://github.com/NaturalIntelligence/path-expression-matcher#readme","bugs":{"url":"https://github.com/NaturalIntelligence/path-expression-matcher/issues"},"dist":{"shasum":"dc39fd6d745df5485356ce81ff7e8efeabef4846","tarball":"https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.3.0.tgz","fileCount":12,"integrity":"sha512-tkolHg8cWjEFA8+TqYGk0w6aNEZVcb7pVxW8KXZpU+ebaBr3s1ogbLssjK1cL74TtEuKl/qy6cb90RnwTFt3kw==","signatures":[{"sig":"MEYCIQCha7+pXgLyJJZMcwPTQKpjMqY7FWjZFRgVzS6XccAPPwIhAKB3+3UOXCI5eb8HiqJFwcCWvPe6pRukeW8/D95m0TpT","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":150470},"main":"./lib/pem.cjs","type":"module","types":"./src/index.d.ts","module":"./src/index.js","engines":{"node":">=14.0.0"},"exports":{".":{"import":{"types":"./src/index.d.ts","default":"./src/index.js"},"require":{"types":"./lib/pem.d.cts","default":"./lib/pem.cjs"}}},"funding":[{"url":"https://github.com/sponsors/NaturalIntelligence","type":"github"}],"gitHead":"8b6eb81c2cc2c7d3dda87ce0218d80c947757984","scripts":{"test":"c8 --reporter=lcov --reporter=text node test/*test.js","bundle":"webpack --config webpack.cjs.config.js"},"_npmUser":{"name":"amitgupta","email":"amitgupta.gwl@gmail.com"},"repository":{"url":"git+https://github.com/NaturalIntelligence/path-expression-matcher.git","type":"git"},"_npmVersion":"11.11.0","description":"Efficient path tracking and pattern matching for XML/JSON parsers","directories":{},"sideEffects":false,"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"devDependencies":{"c8":"^10.1.3","eslint":"^8.3.0","webpack":"^5.64.4","prettier":"^3.5.1","typescript":"5","@babel/core":"^7.13.10","@types/node":"20","webpack-cli":"^4.9.1","babel-loader":"^8.2.2","@babel/register":"^7.13.8","@babel/preset-env":"^7.13.10","@babel/plugin-transform-runtime":"^7.13.10"},"_npmOperationalInternal":{"tmp":"tmp/path-expression-matcher_1.3.0_1775535679777_0.7432145293698484","host":"s3://npm-registry-packages-npm-production"}},"1.4.0":{"name":"path-expression-matcher","version":"1.4.0","keywords":["xml","json","yaml","path","matcher","pattern","xpath","selector","parser","fast-xml-parser","fast-xml-builder"],"author":{"url":"https://solothought.com","name":"Amit Gupta"},"license":"MIT","_id":"path-expression-matcher@1.4.0","maintainers":[{"name":"amitgupta","email":"amitgupta.gwl@gmail.com"}],"homepage":"https://github.com/NaturalIntelligence/path-expression-matcher#readme","bugs":{"url":"https://github.com/NaturalIntelligence/path-expression-matcher/issues"},"dist":{"shasum":"275730c9c21bbf2e124eba6d4c6453f02f3d331d","tarball":"https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.4.0.tgz","fileCount":12,"integrity":"sha512-s4DQMxIdhj3jLFWd9LxHOplj4p9yQ4ffMGowFf3cpEgrrJjEhN0V5nxw4Ye1EViAGDoL4/1AeO6qHpqYPOzE4Q==","signatures":[{"sig":"MEUCIQC/YLhYM3CXUIHlb/9zA+41whsRP72x9GvveQatzlGMQAIgGzaofWYmH2URY/Uoi7YViSv8mS0fvLMnxkwWwJNcbOM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":153837},"main":"./lib/pem.cjs","type":"module","types":"./src/index.d.ts","module":"./src/index.js","engines":{"node":">=14.0.0"},"exports":{".":{"import":{"types":"./src/index.d.ts","default":"./src/index.js"},"require":{"types":"./lib/pem.d.cts","default":"./lib/pem.cjs"}}},"funding":[{"url":"https://github.com/sponsors/NaturalIntelligence","type":"github"}],"gitHead":"999843e65c04be206a4debf78e1f327c7b86ce11","scripts":{"test":"c8 --reporter=lcov --reporter=text node test/*test.js","bundle":"webpack --config webpack.cjs.config.js"},"_npmUser":{"name":"amitgupta","email":"amitgupta.gwl@gmail.com"},"repository":{"url":"git+https://github.com/NaturalIntelligence/path-expression-matcher.git","type":"git"},"_npmVersion":"11.11.0","description":"Efficient path tracking and pattern matching for XML/JSON parsers","directories":{},"sideEffects":false,"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"devDependencies":{"c8":"^10.1.3","eslint":"^8.3.0","webpack":"^5.64.4","prettier":"^3.5.1","typescript":"5","@babel/core":"^7.13.10","@types/node":"20","webpack-cli":"^4.9.1","babel-loader":"^8.2.2","@babel/register":"^7.13.8","@babel/preset-env":"^7.13.10","@babel/plugin-transform-runtime":"^7.13.10"},"_npmOperationalInternal":{"tmp":"tmp/path-expression-matcher_1.4.0_1775547723640_0.8318611681397561","host":"s3://npm-registry-packages-npm-production"}},"1.5.0":{"name":"path-expression-matcher","version":"1.5.0","keywords":["xml","json","yaml","path","matcher","pattern","xpath","selector","parser","fast-xml-parser","fast-xml-builder"],"author":{"url":"https://solothought.com","name":"Amit Gupta"},"license":"MIT","_id":"path-expression-matcher@1.5.0","maintainers":[{"name":"amitgupta","email":"amitgupta.gwl@gmail.com"}],"homepage":"https://github.com/NaturalIntelligence/path-expression-matcher#readme","bugs":{"url":"https://github.com/NaturalIntelligence/path-expression-matcher/issues"},"dist":{"shasum":"3b98545dc88ffebb593e2d8458d0929da9275f4a","tarball":"https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.5.0.tgz","fileCount":12,"integrity":"sha512-cbrerZV+6rvdQrrD+iGMcZFEiiSrbv9Tfdkvnusy6y0x0GKBXREFg/Y65GhIfm0tnLntThhzCnfKwp1WRjeCyQ==","signatures":[{"sig":"MEUCIQCZa1TiiSi4KawcNsQfkQhlSQYswzCAs1f9GycASoy2wwIgFcRQYnnf50Jg4Q48jsG9b5oiFoBuf0BI3BPr/8MJwqw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":145152},"main":"./lib/pem.cjs","type":"module","types":"./src/index.d.ts","module":"./src/index.js","engines":{"node":">=14.0.0"},"exports":{".":{"import":{"types":"./src/index.d.ts","default":"./src/index.js"},"require":{"types":"./lib/pem.d.cts","default":"./lib/pem.cjs"}}},"funding":[{"url":"https://github.com/sponsors/NaturalIntelligence","type":"github"}],"gitHead":"543e5b3718897aa7da9dfc9ea6f433d1b551720d","scripts":{"test":"c8 --reporter=lcov --reporter=text node test/*test.js","bundle":"webpack --config webpack.cjs.config.js"},"_npmUser":{"name":"amitgupta","email":"amitgupta.gwl@gmail.com"},"repository":{"url":"git+https://github.com/NaturalIntelligence/path-expression-matcher.git","type":"git"},"_npmVersion":"11.11.0","description":"Efficient path tracking and pattern matching for XML/JSON parsers","directories":{},"sideEffects":false,"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"devDependencies":{"c8":"^10.1.3","eslint":"^8.3.0","webpack":"^5.64.4","prettier":"^3.5.1","typescript":"5","@babel/core":"^7.13.10","@types/node":"20","webpack-cli":"^4.9.1","babel-loader":"^8.2.2","@babel/register":"^7.13.8","@babel/preset-env":"^7.13.10","@babel/plugin-transform-runtime":"^7.13.10"},"_npmOperationalInternal":{"tmp":"tmp/path-expression-matcher_1.5.0_1775791900484_0.03414041489071806","host":"s3://npm-registry-packages-npm-production"}},"1.6.0":{"name":"path-expression-matcher","version":"1.6.0","keywords":["xml","html","json","yaml","path","matcher","pattern","xpath","selector","parser","fast-xml-parser","fast-xml-builder"],"author":{"url":"https://solothought.com","name":"Amit Gupta"},"license":"MIT","_id":"path-expression-matcher@1.6.0","maintainers":[{"name":"amitgupta","email":"amitgupta.gwl@gmail.com"}],"homepage":"https://github.com/NaturalIntelligence/path-expression-matcher#readme","bugs":{"url":"https://github.com/NaturalIntelligence/path-expression-matcher/issues"},"dist":{"shasum":"a94b623c5a24b1087eb348b02fa5dae8cb363212","tarball":"https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.6.0.tgz","fileCount":12,"integrity":"sha512-e5y7RCLHKjemsgQ4eqGJtPyr10ILz25HO7flzxhTV8bgvd5yHx98DGtCAtbVW9f2TqnYI/gEVZd+vz7snrdPTw==","signatures":[{"sig":"MEYCIQCnwde7qssynFAMkKUQqf9T9zLzfTA2strgy7Soa1ETRgIhAIe0NwjNzwlqeY2UOTei/bzgYCcQg30RXPyV0TN79YmK","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":168800},"main":"./lib/pem.cjs","type":"module","types":"./src/index.d.ts","module":"./src/index.js","engines":{"node":">=14.0.0"},"exports":{".":{"import":{"types":"./src/index.d.ts","default":"./src/index.js"},"require":{"types":"./lib/pem.d.cts","default":"./lib/pem.cjs"}}},"funding":[{"url":"https://github.com/sponsors/NaturalIntelligence","type":"github"}],"gitHead":"19ff92d900f68ccb00e4c98aae27dea70d2f9b27","scripts":{"test":"c8 --reporter=lcov --reporter=text node test/*test.js","bundle":"webpack --config webpack.cjs.config.js"},"_npmUser":{"name":"amitgupta","email":"amitgupta.gwl@gmail.com"},"repository":{"url":"git+https://github.com/NaturalIntelligence/path-expression-matcher.git","type":"git"},"_npmVersion":"11.11.0","description":"Efficient path tracking and pattern matching for XML/JSON parsers","directories":{},"sideEffects":false,"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"devDependencies":{"c8":"^10.1.3","eslint":"^8.3.0","webpack":"^5.64.4","prettier":"^3.5.1","typescript":"5","@babel/core":"^7.13.10","@types/node":"20","webpack-cli":"^4.9.1","babel-loader":"^8.2.2","@babel/register":"^7.13.8","@babel/preset-env":"^7.13.10","@babel/plugin-transform-runtime":"^7.13.10"},"_npmOperationalInternal":{"tmp":"tmp/path-expression-matcher_1.6.0_1781958819955_0.5136866630608745","host":"s3://npm-registry-packages-npm-production"}},"1.6.1":{"name":"path-expression-matcher","version":"1.6.1","keywords":["xml","html","json","yaml","path","matcher","pattern","xpath","selector","parser","fast-xml-parser","fast-xml-builder"],"author":{"url":"https://solothought.com","name":"Amit Gupta"},"license":"MIT","_id":"path-expression-matcher@1.6.1","maintainers":[{"name":"amitgupta","email":"amitgupta.gwl@gmail.com"}],"homepage":"https://github.com/NaturalIntelligence/path-expression-matcher#readme","bugs":{"url":"https://github.com/NaturalIntelligence/path-expression-matcher/issues"},"dist":{"shasum":"fb190513954875d7e1b05c8caabe7fdd0a4cd75b","tarball":"https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.6.1.tgz","fileCount":12,"integrity":"sha512-h7bxdzhHk8Knyc4Tj+jMaa7fEEoUJy7p1qtbVgkYg1Uhpe5Np5VuGXCRZnkZvU+Q42M1vStt0ifa3ueykRJPmQ==","signatures":[{"sig":"MEYCIQDqe89LsoHLA7Q4KfwMxu+dMDFwVj1s2wKYaQZkYEX+2AIhAKDSAITp06vxGRB6h9f/WFVELihq9PvzGYtxc3zLUujF","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":169364},"main":"./lib/pem.cjs","type":"module","types":"./src/index.d.ts","module":"./src/index.js","engines":{"node":">=14.0.0"},"exports":{".":{"import":{"types":"./src/index.d.ts","default":"./src/index.js"},"require":{"types":"./lib/pem.d.cts","default":"./lib/pem.cjs"}}},"funding":[{"url":"https://github.com/sponsors/NaturalIntelligence","type":"github"}],"gitHead":"5e372235acb79ffa602bcc5ba63264237f1a74ed","scripts":{"test":"c8 --reporter=lcov --reporter=text node test/*test.js","bundle":"webpack --config webpack.cjs.config.js"},"_npmUser":{"name":"amitgupta","email":"amitgupta.gwl@gmail.com"},"repository":{"url":"git+https://github.com/NaturalIntelligence/path-expression-matcher.git","type":"git"},"_npmVersion":"11.11.0","description":"Efficient path tracking and pattern matching for XML/JSON parsers","directories":{},"sideEffects":false,"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"devDependencies":{"c8":"^10.1.3","eslint":"^8.3.0","webpack":"^5.64.4","prettier":"^3.5.1","typescript":"5","@babel/core":"^7.13.10","@types/node":"20","webpack-cli":"^4.9.1","babel-loader":"^8.2.2","@babel/register":"^7.13.8","@babel/preset-env":"^7.13.10","@babel/plugin-transform-runtime":"^7.13.10"},"_npmOperationalInternal":{"tmp":"tmp/path-expression-matcher_1.6.1_1782198129787_0.8462521956401179","host":"s3://npm-registry-packages-npm-production"}},"1.6.2":{"name":"path-expression-matcher","version":"1.6.2","description":"Efficient path tracking and pattern matching for XML/JSON parsers","main":"./lib/pem.cjs","type":"module","sideEffects":false,"module":"./src/index.js","types":"./src/index.d.ts","exports":{".":{"import":{"types":"./src/index.d.ts","default":"./src/index.js"},"require":{"types":"./lib/pem.d.cts","default":"./lib/pem.cjs"}}},"scripts":{"test":"c8 --reporter=lcov --reporter=text node test/*test.js","bundle":"webpack --config webpack.cjs.config.js"},"keywords":["xml","html","json","yaml","path","matcher","pattern","xpath","selector","parser","fast-xml-parser","fast-xml-builder"],"author":{"name":"Amit Gupta","url":"https://solothought.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/NaturalIntelligence/path-expression-matcher.git"},"bugs":{"url":"https://github.com/NaturalIntelligence/path-expression-matcher/issues"},"homepage":"https://github.com/NaturalIntelligence/path-expression-matcher#readme","engines":{"node":">=14.0.0"},"devDependencies":{"@babel/core":"^7.13.10","@babel/plugin-transform-runtime":"^7.13.10","@babel/preset-env":"^7.13.10","@babel/register":"^7.13.8","@types/node":"20","babel-loader":"^8.2.2","c8":"^10.1.3","eslint":"^8.3.0","prettier":"^3.5.1","typescript":"5","webpack":"^5.64.4","webpack-cli":"^4.9.1"},"funding":[{"type":"github","url":"https://github.com/sponsors/NaturalIntelligence"}],"gitHead":"0326c2e78b7dc9b5e3e04a580ce2de7f428f1672","_id":"path-expression-matcher@1.6.2","_nodeVersion":"22.14.0","_npmVersion":"11.18.0","dist":{"integrity":"sha512-enSlaiat05iasnzmgNxRj8reFdj3puY2QpNgP1aPIaVfT6nn9ICuPoFlKHk8EN22HcwewshO+mN2DGbkCEOtqQ==","shasum":"567c73c07197e9dcef24e90edcdc571056599168","tarball":"https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.6.2.tgz","fileCount":12,"unpackedSize":170626,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQD/FVwLwC93/8ur7TZTFPo4Li9301SRIRCHpzuRYfEKkQIgaY1NjuX2lx+8kDiDjsAjk/5ZMIA2EXFmgmnulAUKZKg="}]},"_npmUser":{"name":"amitgupta","email":"amitgupta.gwl@gmail.com"},"directories":{},"maintainers":[{"name":"amitgupta","email":"amitgupta.gwl@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/path-expression-matcher_1.6.2_1783503972343_0.012717061002815555"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-06T13:30:15.285Z","modified":"2026-07-08T09:46:12.629Z","1.0.0":"2026-03-06T13:30:15.454Z","1.1.0":"2026-03-09T23:14:22.159Z","1.1.1":"2026-03-09T23:39:25.280Z","1.1.2":"2026-03-10T02:50:51.859Z","1.1.3":"2026-03-11T11:14:12.123Z","1.2.0":"2026-03-20T02:19:10.325Z","1.2.1":"2026-04-03T03:39:51.251Z","1.3.0":"2026-04-07T04:21:19.931Z","1.4.0":"2026-04-07T07:42:03.782Z","1.5.0":"2026-04-10T03:31:40.667Z","1.6.0":"2026-06-20T12:33:40.106Z","1.6.1":"2026-06-23T07:02:10.186Z","1.6.2":"2026-07-08T09:46:12.523Z"},"bugs":{"url":"https://github.com/NaturalIntelligence/path-expression-matcher/issues"},"author":{"name":"Amit Gupta","url":"https://solothought.com"},"license":"MIT","homepage":"https://github.com/NaturalIntelligence/path-expression-matcher#readme","keywords":["xml","html","json","yaml","path","matcher","pattern","xpath","selector","parser","fast-xml-parser","fast-xml-builder"],"repository":{"type":"git","url":"git+https://github.com/NaturalIntelligence/path-expression-matcher.git"},"description":"Efficient path tracking and pattern matching for XML/JSON parsers","maintainers":[{"name":"amitgupta","email":"amitgupta.gwl@gmail.com"}],"readme":"# path-expression-matcher\n\n[![path-expression-matcher downloads](https://img.shields.io/npm/dw/path-expression-matcher.svg)](https://npm-compare.com/path-expression-matcher) \n[![path-expression-matcher version](https://img.shields.io/npm/v/path-expression-matcher.svg)](https://www.npmjs.com/package/path-expression-matcher)\n[![path-expression-matcher license](https://img.shields.io/npm/l/path-expression-matcher.svg)](https://github.com/NaturalIntelligence/path-expression-matcher)\n\nEfficient path tracking and pattern matching for XML, JSON, YAML or any other parsers.\n\n## 🎯 Purpose\n\n`path-expression-matcher` provides three core classes for tracking and matching paths:\n\n- **`Expression`**: Parses and stores pattern expressions (e.g., `\"root.users.user[id]\"`)\n- **`Matcher`**: Tracks current path during parsing and matches against expressions\n- **`MatcherView`**: A lightweight read-only view of a `Matcher`, safe to pass to callbacks\n\nCompatible with [fast-xml-parser](https://github.com/NaturalIntelligence/fast-xml-parser) and similar tools.\n\n## 📦 Installation\n\n```bash\nnpm install path-expression-matcher\n```\n\n## 🚀 Quick Start\n\n```javascript\nimport { Expression, Matcher } from 'path-expression-matcher';\n\n// Create expression (parse once, reuse many times)\nconst expr = new Expression(\"root.users.user\");\n\n// Create matcher (tracks current path)\nconst matcher = new Matcher();\n\nmatcher.push(\"root\");\nmatcher.push(\"users\");\nmatcher.push(\"user\", { id: \"123\" });\n\n// Match current path against expression\nif (matcher.matches(expr)) {\n  console.log(\"Match found!\");\n  console.log(\"Current path:\", matcher.toString()); // \"root.users.user\"\n}\n\n// Namespace support\nconst nsExpr = new Expression(\"soap::Envelope.soap::Body..ns::UserId\");\nmatcher.push(\"Envelope\", null, \"soap\");\nmatcher.push(\"Body\", null, \"soap\");\nmatcher.push(\"UserId\", null, \"ns\");\nconsole.log(matcher.toString()); // \"soap:Envelope.soap:Body.ns:UserId\"\n```\n\n## 📖 Pattern Syntax\n\n### Basic Paths\n\n```javascript\n\"root.users.user\"           // Exact path match\n\"*.users.user\"              // Wildcard: any parent\n\"root.*.user\"               // Wildcard: any middle\n\"root.users.*\"              // Wildcard: any child\n```\n\n### Deep Wildcard\n\n```javascript\n\"..user\"                    // user anywhere in tree\n\"root..user\"                // user anywhere under root\n\"..users..user\"             // users somewhere, then user below it\n```\n\n### Attribute Matching\n\n```javascript\n\"user[id]\"                  // user with \"id\" attribute\n\"user[type=admin]\"          // user with type=\"admin\" (current node only)\n```\n\n> **Note:** Attribute conditions in expressions only ever look at the **current** (last) node in the path — `..user` matches `user` at any depth, but bracket conditions like `[lang]` still apply to `user` itself, never to an ancestor tag. To check an *ancestor's* attribute (e.g. \"is there a `lang` attribute somewhere above this node?\"), use `push(..., { keep: [...] })` with `getAnyParentAttr()` / `hasAnyParentAttr()` — see [Ancestor Attributes (`keep`)](#ancestor-attributes-keep) below.\n\n### Position Selectors\n\n```javascript\n\"user:first\"                // First user (counter=0)\n\"user:nth(2)\"               // Third user (counter=2, zero-based)\n\"user:odd\"                  // Odd-numbered users (counter=1,3,5...)\n\"user:even\"                 // Even-numbered users (counter=0,2,4...)\n\"root.users.user:first\"     // First user under users\n```\n\n**Note:** Position selectors use the **counter** (occurrence count of the tag name), not the position (child index). For example, in `<root><a/><b/><a/></root>`, the second `<a/>` has position=2 but counter=1.\n\n### Namespaces\n\n```javascript\n\"ns::user\"                  // user with namespace \"ns\"\n\"soap::Envelope\"            // Envelope with namespace \"soap\"\n\"ns::user[id]\"              // user with namespace \"ns\" and \"id\" attribute\n\"ns::user:first\"            // First user with namespace \"ns\"\n\"*::user\"                   // user with any namespace\n\"..ns::item\"                // item with namespace \"ns\" anywhere in tree\n\"soap::Envelope.soap::Body\" // Nested namespaced elements\n\"ns::first\"                 // Tag named \"first\" with namespace \"ns\" (NO ambiguity!)\n```\n\n**Namespace syntax:**\n- Use **double colon (::)** for namespace: `ns::tag`\n- Use **single colon (:)** for position: `tag:first`\n- Combined: `ns::tag:first` (namespace + tag + position)\n\n**Namespace matching rules:**\n- Pattern `ns::user` matches only nodes with namespace \"ns\" and tag \"user\"\n- Pattern `user` (no namespace) matches nodes with tag \"user\" regardless of namespace\n- Pattern `*::user` matches tag \"user\" with any namespace (wildcard namespace)\n- Namespaces are tracked separately for counter/position (e.g., `ns1::item` and `ns2::item` have independent counters)\n\n### Wildcard Differences\n\n**Single wildcard (`*`)** - Matches exactly ONE level:\n- `\"*.fix1\"` matches `root.fix1` (2 levels) ✅\n- `\"*.fix1\"` does NOT match `root.another.fix1` (3 levels) ❌\n- Path depth MUST equal pattern depth\n\n**Deep wildcard (`..`)** - Matches ZERO or MORE levels:\n- `\"..fix1\"` matches `root.fix1` ✅\n- `\"..fix1\"` matches `root.another.fix1` ✅\n- `\"..fix1\"` matches `a.b.c.d.fix1` ✅\n- Works at any depth\n\n### Combined Patterns\n\n```javascript\n\"..user[id]:first\"              // First user with id, anywhere\n\"root..user[type=admin]\"        // Admin user under root\n\"ns::user[id]:first\"            // First namespaced user with id\n\"soap::Envelope..ns::UserId\"    // UserId with namespace ns under SOAP envelope\n```\n\n## 🔧 API Reference\n\n### Expression\n\n#### Constructor\n\n```javascript\nnew Expression(pattern, options = {}, data)\n```\n\n**Parameters:**\n- `pattern` (string): Pattern to parse\n- `options.separator` (string): Path separator (default: `'.'`)\n\n**Example:**\n```javascript\nconst expr1 = new Expression(\"root.users.user\");\nconst expr2 = new Expression(\"root/users/user\", { separator: '/' });\nconst expr3 = new Expression(\"root/users/user\", { separator: '/' }, { extra: \"data\"});\nconsole.log(expr3.data) // { extra: \"data\" }\n```\n\n#### Methods\n\n- `hasDeepWildcard()` → boolean\n- `hasAttributeCondition()` → boolean\n- `hasPositionSelector()` → boolean\n- `toString()` → string\n\n### Matcher\n\n#### Constructor\n\n```javascript\nnew Matcher(options)\n```\n\n**Parameters:**\n- `options.separator` (string): Default path separator (default: `'.'`)\n\n#### Path Tracking Methods\n\n##### `push(tagName, attrValues, namespace, options)`\n\nAdd a tag to the current path. Position and counter are automatically calculated.\n\n**Parameters:**\n- `tagName` (string): Tag name\n- `attrValues` (object, optional): Attribute key-value pairs (current node only)\n- `namespace` (string, optional): Namespace for the tag\n- `options` (object, optional):\n  - `keep` (string[], optional): Names of attributes (from `attrValues`) to retain for ancestor lookup via `getAnyParentAttr()` / `hasAnyParentAttr()`, even after this node is no longer the current node. See [Ancestor Attributes (`keep`)](#ancestor-attributes-keep).\n\n**Example:**\n```javascript\nmatcher.push(\"user\", { id: \"123\", type: \"admin\" });\nmatcher.push(\"item\");  // No attributes\nmatcher.push(\"Envelope\", null, \"soap\");  // With namespace\nmatcher.push(\"Body\", { version: \"1.1\" }, \"soap\");  // With both\nmatcher.push(\"Body\", { version: \"1.1\" }, \"soap\", { keep: [\"version\"] });  // Retain \"version\" for descendants\n```\n\n**Position vs Counter:**\n- **Position**: The child index in the parent (0, 1, 2, 3...)\n- **Counter**: How many times this tag name appeared at this level (0, 1, 2...)\n\nExample:\n```xml\n<root>\n  <a/>      <!-- position=0, counter=0 -->\n  <b/>      <!-- position=1, counter=0 -->\n  <a/>      <!-- position=2, counter=1 -->\n</root>\n```\n\n##### `pop()`\n\nRemove the last tag from the path.\n\n```javascript\nmatcher.pop();\n```\n\n##### `updateCurrent(attrValues)`\n\nUpdate current node's attributes (useful when attributes are parsed after push).\n\n```javascript\nmatcher.push(\"user\");  // Don't know values yet\n// ... parse attributes ...\nmatcher.updateCurrent({ id: \"123\" });\n```\n\n##### `reset()`\n\nClear the entire path.\n\n```javascript\nmatcher.reset();\n```\n\n#### Query Methods\n\n##### `matches(expression)`\n\nCheck if current path matches an Expression.\n\n```javascript\nconst expr = new Expression(\"root.users.user\");\nif (matcher.matches(expr)) {\n  // Current path matches\n}\n```\n\n#### `matchesAny(exprSet)` → `boolean`\n\nPlease check `ExpressionSet` class for more details.  \n\n```javascript\nconst matcher = new Matcher();\nconst exprSet = new ExpressionSet();\nexprSet.add(new Expression(\"root.users.user\"));\nexprSet.add(new Expression(\"root.config.*\"));\nexprSet.seal();\n\nif (matcher.matchesAny(exprSet)) {\n  // Current path matches any expression in the set\n}\n```\n\n##### `getCurrentTag()`\n\nGet current tag name.\n\n```javascript\nconst tag = matcher.getCurrentTag(); // \"user\"\n```\n\n##### `getCurrentNamespace()`\n\nGet current namespace.\n\n```javascript\nconst ns = matcher.getCurrentNamespace(); // \"soap\" or undefined\n```\n\n##### `getAttrValue(attrName)`\n\nGet attribute value of current node.\n\n```javascript\nconst id = matcher.getAttrValue(\"id\"); // \"123\"\n```\n\n##### `hasAttr(attrName)`\n\nCheck if current node has an attribute.\n\n```javascript\nif (matcher.hasAttr(\"id\")) {\n  // Current node has \"id\" attribute\n}\n```\n\n##### `getAnyParentAttr(attrName)`\n\nGet the value of an attribute that was explicitly **kept** (via `push(..., { keep: [...] })`) by the current node or any ancestor. Unlike `getAttrValue()`, this works regardless of how far the path has descended since the attribute was pushed — but only for names that were marked with `keep` at push time. If the same name was kept at multiple depths, the **nearest** (most recent) one wins.\n\n```javascript\nmatcher.push(\"Body\", { version: \"1.1\" }, \"soap\", { keep: [\"version\"] });\nmatcher.push(\"GetUserRequest\");\nmatcher.push(\"UserId\");\n\nmatcher.getAttrValue(\"version\");     // undefined — Body is no longer current\nmatcher.getAnyParentAttr(\"version\"); // \"1.1\" — still reachable, because it was kept\n```\n\n##### `hasAnyParentAttr(attrName)`\n\nCheck whether the current node or any ancestor kept the given attribute via `push(..., { keep: [...] })`.\n\n```javascript\nif (matcher.hasAnyParentAttr(\"version\")) {\n  // Some node on the path (current or ancestor) kept \"version\"\n}\n```\n\n##### `getPosition()`\n\nGet sibling position of current node (child index in parent).\n\n```javascript\nconst position = matcher.getPosition(); // 0, 1, 2, ...\n```\n\n##### `getCounter()`\n\nGet repeat counter of current node (occurrence count of this tag name).\n\n```javascript\nconst counter = matcher.getCounter(); // 0, 1, 2, ...\n```\n\n##### `getIndex()` (deprecated)\n\nAlias for `getPosition()`. Use `getPosition()` or `getCounter()` instead for clarity.\n\n```javascript\nconst index = matcher.getIndex(); // Same as getPosition()\n```\n\n##### `getDepth()`\n\nGet current path depth.\n\n```javascript\nconst depth = matcher.getDepth(); // 3 for \"root.users.user\"\n```\n\n##### `toString(separator?, includeNamespace?)`\n\nGet path as string.\n\n**Parameters:**\n- `separator` (string, optional): Path separator (uses default if not provided)\n- `includeNamespace` (boolean, optional): Whether to include namespaces (default: true)\n\n```javascript\nconst path = matcher.toString();           // \"root.ns:user.item\"\nconst path2 = matcher.toString('/');       // \"root/ns:user/item\"\nconst path3 = matcher.toString('.', false); // \"root.user.item\" (no namespaces)\n```\n\n##### `toArray()`\n\nGet path as array.\n\n```javascript\nconst arr = matcher.toArray(); // [\"root\", \"users\", \"user\"]\n```\n\n#### State Management\n\n##### `snapshot()`\n\nCreate a snapshot of current state.\n\n```javascript\nconst snapshot = matcher.snapshot();\n```\n\n##### `restore(snapshot)`\n\nRestore from a snapshot.\n\n```javascript\nmatcher.restore(snapshot);\n```\n\n#### Read-Only Access\n\n##### `readOnly()`\n\nReturns a **`MatcherView`** — a lightweight, live read-only view of the matcher. All query and inspection methods work normally and always reflect the current state of the underlying matcher. Mutation methods (`push`, `pop`, `reset`, `updateCurrent`, `restore`) simply don't exist on `MatcherView`, so misuse is caught at **compile time** by TypeScript rather than at runtime.\n\nThe **same instance** is returned on every call — no allocation occurs per invocation. This is the recommended way to share the matcher with callbacks, plugins, or any external code that only needs to inspect the current path.\n\n```javascript\nconst view = matcher.readOnly();\n// Same reference every time — safe to cache\nview === matcher.readOnly(); // true\n```\n\n**What works on the view:**\n\n```javascript\nview.matches(expr)          // ✓ pattern matching\nview.getCurrentTag()        // ✓ current tag name\nview.getCurrentNamespace()  // ✓ current namespace\nview.getAttrValue(\"id\")     // ✓ attribute value\nview.hasAttr(\"id\")          // ✓ attribute presence check\nview.getPosition()          // ✓ sibling position\nview.getCounter()           // ✓ occurrence counter\nview.getDepth()             // ✓ path depth\nview.toString()             // ✓ path as string\nview.toArray()              // ✓ path as array\n```\n\n**What doesn't exist (compile-time error in TypeScript):**\n\n```javascript\nview.push(\"child\", {})      // ✗ Property 'push' does not exist on type 'MatcherView'\nview.pop()                  // ✗ Property 'pop' does not exist on type 'MatcherView'\nview.reset()                // ✗ Property 'reset' does not exist on type 'MatcherView'\nview.updateCurrent({})      // ✗ Property 'updateCurrent' does not exist on type 'MatcherView'\nview.restore(snapshot)      // ✗ Property 'restore' does not exist on type 'MatcherView'\n```\n\n**The view is live** — it always reflects the current state of the underlying matcher.\n\n```javascript\nconst matcher = new Matcher();\nconst view = matcher.readOnly();\n\nmatcher.push(\"root\");\nview.getDepth();    // 1 — immediately reflects the push\nmatcher.push(\"users\");\nview.getDepth();    // 2 — still live\n```\n\n## 💡 Usage Examples\n\n### Example 1: XML Parser with stopNodes\n\n```javascript\nimport { XMLParser } from 'fast-xml-parser';\nimport { Expression, Matcher } from 'path-expression-matcher';\n\nclass MyParser {\n  constructor() {\n    this.matcher = new Matcher();\n    \n    // Pre-compile stop node patterns\n    this.stopNodeExpressions = [\n      new Expression(\"html.body.script\"),\n      new Expression(\"html.body.style\"),\n      new Expression(\"..svg\"),\n    ];\n  }\n  \n  parseTag(tagName, attrs) {\n    this.matcher.push(tagName, attrs);\n    \n    // Check if this is a stop node\n    for (const expr of this.stopNodeExpressions) {\n      if (this.matcher.matches(expr)) {\n        // Don't parse children, read as raw text\n        return this.readRawContent();\n      }\n    }\n    \n    // Continue normal parsing\n    this.parseChildren();\n    \n    this.matcher.pop();\n  }\n}\n```\n\n### Example 2: Conditional Processing\n\n```javascript\nconst matcher = new Matcher();\nconst userExpr = new Expression(\"..user[type=admin]\");\nconst firstItemExpr = new Expression(\"..item:first\");\n\nfunction processTag(tagName, value, attrs) {\n  matcher.push(tagName, attrs);\n  \n  if (matcher.matches(userExpr)) {\n    value = enhanceAdminUser(value);\n  }\n  \n  if (matcher.matches(firstItemExpr)) {\n    value = markAsFirst(value);\n  }\n  \n  matcher.pop();\n  return value;\n}\n```\n\n### Example 3: Path-based Filtering\n\n```javascript\nconst patterns = [\n  new Expression(\"data.users.user\"),\n  new Expression(\"data.posts.post\"),\n  new Expression(\"..comment[approved=true]\"),\n];\n\nfunction shouldInclude(matcher) {\n  return patterns.some(expr => matcher.matches(expr));\n}\n```\n\n### Example 4: Custom Separator\n\n```javascript\nconst matcher = new Matcher({ separator: '/' });\nconst expr = new Expression(\"root/config/database\", { separator: '/' });\n\nmatcher.push(\"root\");\nmatcher.push(\"config\");\nmatcher.push(\"database\");\n\nconsole.log(matcher.toString()); // \"root/config/database\"\nconsole.log(matcher.matches(expr)); // true\n```\n\n### Example 5: Attribute Checking\n\n```javascript\nconst matcher = new Matcher();\nmatcher.push(\"root\");\nmatcher.push(\"user\", { id: \"123\", type: \"admin\", status: \"active\" });\n\n// Check attribute existence (current node only)\nconsole.log(matcher.hasAttr(\"id\"));        // true\nconsole.log(matcher.hasAttr(\"email\"));     // false\n\n// Get attribute value (current node only)\nconsole.log(matcher.getAttrValue(\"type\")); // \"admin\"\n\n// Match by attribute\nconst expr1 = new Expression(\"user[id]\");\nconsole.log(matcher.matches(expr1));       // true\n\nconst expr2 = new Expression(\"user[type=admin]\");\nconsole.log(matcher.matches(expr2));       // true\n```\n\n> Need to check an attribute from an *ancestor* node, not just the current one? See [Example 5b](#example-5b-ancestor-attributes-keep) and [Ancestor Attributes (`keep`)](#ancestor-attributes-keep).\n\n### Example 5b: Ancestor Attributes (`keep`)\n\n`getAttrValue()` / `hasAttr()` only ever see the **current** node — by design, ancestor attribute values are discarded as soon as you push past them, to keep memory usage low. If you know in advance that a specific attribute (e.g. a SOAP envelope's `version`, or `xml:space`) will matter much deeper in the tree, mark it to be **kept**:\n\n```javascript\nconst matcher = new Matcher();\nmatcher.push(\"Envelope\", null, \"soap\");\nmatcher.push(\"Body\", { version: \"1.1\" }, \"soap\", { keep: [\"version\"] });\nmatcher.push(\"GetUserRequest\", { id: \"42\" });\nmatcher.push(\"UserId\");\n\n// Ordinary attribute access only sees the current node:\nconsole.log(matcher.getAttrValue(\"version\"));     // undefined\n\n// getAnyParentAttr/hasAnyParentAttr still see it, however deep we've gone:\nconsole.log(matcher.hasAnyParentAttr(\"version\")); // true\nconsole.log(matcher.getAnyParentAttr(\"version\")); // \"1.1\"\n\nmatcher.pop(); matcher.pop(); matcher.pop(); // back to Envelope\nconsole.log(matcher.hasAnyParentAttr(\"version\")); // false — Body (and its kept attrs) was popped\n```\n\n**When to use this:** only for the small number of attributes you specifically know you'll need many levels deeper — not as a general substitute for `getAttrValue()`. Each name passed to `keep` adds a tiny, constant amount of bookkeeping at `push()` time; lookups scan only the kept-attributes list (typically 0-3 entries), never the full path, so cost does not grow with document depth.\n\n### Example 6: Position vs Counter\n\n```javascript\nconst matcher = new Matcher();\nmatcher.push(\"root\");\n\n// Mixed tags at same level\nmatcher.push(\"item\");  // position=0, counter=0 (first item)\nmatcher.pop();\n\nmatcher.push(\"div\");   // position=1, counter=0 (first div)\nmatcher.pop();\n\nmatcher.push(\"item\");  // position=2, counter=1 (second item)\n\nconsole.log(matcher.getPosition()); // 2 (third child overall)\nconsole.log(matcher.getCounter());  // 1 (second \"item\" specifically)\n\n// :first uses counter, not position\nconst expr = new Expression(\"root.item:first\");\nconsole.log(matcher.matches(expr)); // false (counter=1, not 0)\n```\n\n### Example 8: Passing a Read-Only View to External Consumers\n\nWhen passing the matcher into callbacks, plugins, or other code you don't control, use `readOnly()` to get a `MatcherView` — it can inspect but never mutate parser state.\n\n```javascript\nimport { Expression, Matcher } from 'path-expression-matcher';\n\nconst matcher = new Matcher();\n\nconst adminExpr = new Expression(\"..user[type=admin]\");\n\nfunction parseTag(tagName, attrs, onTag) {\n  matcher.push(tagName, attrs);\n\n  // Pass MatcherView — consumer can inspect but not mutate\n  onTag(matcher.readOnly());\n\n  matcher.pop();\n}\n\n// Safe consumer — can only read\nfunction myPlugin(view) {\n  if (view.matches(adminExpr)) {\n    console.log(\"Admin at path:\", view.toString());\n    console.log(\"Depth:\", view.getDepth());\n    console.log(\"ID:\", view.getAttrValue(\"id\"));\n  }\n}\n\n// view.push(...) or view.reset() don't exist on MatcherView —\n// TypeScript catches misuse at compile time.\nparseTag(\"user\", { id: \"1\", type: \"admin\" }, myPlugin);\n```\n\n```javascript\nconst matcher = new Matcher();\nconst soapExpr = new Expression(\"soap::Envelope.soap::Body..ns::UserId\");\n\n// Parse SOAP document\nmatcher.push(\"Envelope\", { xmlns: \"...\" }, \"soap\");\nmatcher.push(\"Body\", null, \"soap\");\nmatcher.push(\"GetUserRequest\", null, \"ns\");\nmatcher.push(\"UserId\", null, \"ns\");\n\n// Match namespaced pattern\nif (matcher.matches(soapExpr)) {\n  console.log(\"Found UserId in SOAP body\");\n  console.log(matcher.toString()); // \"soap:Envelope.soap:Body.ns:GetUserRequest.ns:UserId\"\n}\n\n// Namespace-specific counters\nmatcher.reset();\nmatcher.push(\"root\");\nmatcher.push(\"item\", null, \"ns1\");  // ns1::item counter=0\nmatcher.pop();\nmatcher.push(\"item\", null, \"ns2\");  // ns2::item counter=0 (different namespace)\nmatcher.pop();\nmatcher.push(\"item\", null, \"ns1\");  // ns1::item counter=1\n\nconst firstNs1Item = new Expression(\"root.ns1::item:first\");\nconsole.log(matcher.matches(firstNs1Item)); // false (counter=1)\n\nconst secondNs1Item = new Expression(\"root.ns1::item:nth(1)\");\nconsole.log(matcher.matches(secondNs1Item)); // true\n\n// NO AMBIGUITY: Tags named after position keywords\nmatcher.reset();\nmatcher.push(\"root\");\nmatcher.push(\"first\", null, \"ns\");  // Tag named \"first\" with namespace\n\nconst expr = new Expression(\"root.ns::first\");\nconsole.log(matcher.matches(expr)); // true - matches namespace \"ns\", tag \"first\"\n```\n\n## 🏗️ Architecture\n\n### Data Storage Strategy\n\n**Ancestor nodes:** Store only tag name, position, and counter (minimal memory)\n**Current node:** Store tag name, position, counter, and attribute values\n\nThis design minimizes memory usage:\n- No attribute names stored (derived from values object when needed)\n- Attribute values only for current node, not ancestors, **by default**\n- For 1M nodes with 3 attributes each, saves ~50MB vs storing attribute names\n\n### Ancestor Attributes (`keep`)\n\nThe trade-off above is the right default, but XML/SOAP documents occasionally have a handful of attributes — `xml:space`, a SOAP envelope's `version`, a feature-flag at the document root — that genuinely need to be visible many levels deeper. Rather than retaining *all* attribute values for *every* node (defeating the memory savings above), `push()` accepts an explicit opt-in:\n\n```javascript\nmatcher.push(\"Body\", { version: \"1.1\" }, \"soap\", { keep: [\"version\"] });\n```\n\nOnly the named attribute(s) are copied into a small side-stack (`_keptAttrs`), independent of the normal per-node `values`. Reachable later via `getAnyParentAttr(name)` / `hasAnyParentAttr(name)` regardless of depth — see [Example 5b](#example-5b-ancestor-attributes-keep).\n\n**Why this stays cheap:**\n- Pushing without `options` costs two extra property reads — no allocation, no measurable overhead (benchmarked: within run-to-run noise vs. plain `push()`).\n- Lookups scan only the kept-attributes stack, not the full path — cost is proportional to *how many distinct attributes are currently kept* (typically 0-3 in real usage), not to document depth.\n- `pop()` truncates kept entries belonging to the popped subtree in the same backward-scan style, so the stack never grows unbounded.\n- The core `matches()` / `_matchSegment` pattern-matching path is completely unaffected — `keep` is a separate, opt-in mechanism with no new expression syntax.\n\nThis is intentionally a narrow escape hatch, not a general \"remember everything\" toggle — overusing `keep` (e.g. keeping every attribute on every node) reintroduces the same memory cost this library avoids by default.\n\n### Matching Strategy\n\nMatching is performed **bottom-to-top** (from current node toward root):\n1. Start at current node\n2. Match segments from pattern end to start\n3. Attribute *expression* conditions (`[attr=value]`) only apply to the current node — ancestors have no attribute data in the path itself. For genuinely ancestor-scoped checks outside of expression matching, use `keep` (above).\n4. Position selectors use **counter** (occurrence count), not position (child index)\n\n### Performance\n\n- **Expression parsing:** One-time cost when Expression is created\n- **Expression analysis:** Cached (hasDeepWildcard, hasAttributeCondition, hasPositionSelector)\n- **Path tracking:** O(1) for push/pop operations (O(k) additionally when `options.keep` is used, where k = number of kept attribute names — typically 0-3)\n- **Pattern matching:** O(n*m) where n = path depth, m = pattern segments\n- **Ancestor attribute lookup:** O(k) where k = number of currently-kept attributes, independent of path depth\n- **Memory per ancestor node:** ~40-60 bytes (tag, position, counter only)\n- **Memory per current node:** ~80-120 bytes (adds attribute values)\n\n## 🎓 Design Patterns\n\n### Pre-compile Patterns (Recommended)\n\n```javascript\n// ✅ GOOD: Parse once, reuse many times\nconst expr = new Expression(\"..user[id]\");\n\nfor (let i = 0; i < 1000; i++) {\n  if (matcher.matches(expr)) {\n    // ...\n  }\n}\n```\n\n```javascript\n// ❌ BAD: Parse on every iteration\nfor (let i = 0; i < 1000; i++) {\n  if (matcher.matches(new Expression(\"..user[id]\"))) {\n    // ...\n  }\n}\n```\n\n### Batch Pattern Checking with ExpressionSet (Recommended)\n\nFor checking multiple patterns on every tag, use `ExpressionSet` instead of a manual loop.\nIt pre-indexes expressions at build time so each call to `matchesAny()` does an O(1) bucket\nlookup rather than a full O(N) scan:\n\n```javascript\nimport { Expression, ExpressionSet, Matcher } from 'path-expression-matcher';\n\n// Build once at config/startup time\nconst stopNodes = new ExpressionSet();\nstopNodes\n  .add(new Expression('root.users.user'))\n  .add(new Expression('root.config.*'))\n  .add(new Expression('..script'))\n  .seal(); // prevent accidental mutation during parsing\n\n// Per-tag — hot path\nif (stopNodes.matchesAny(matcher)) {\n  // handle stop node\n}\n```\n\nThis replaces the manual loop pattern:\n\n```javascript\n// ❌ Before — O(N) per tag\nfunction isStopNode(expressions, matcher) {\n  for (let i = 0; i < expressions.length; i++) {\n    if (matcher.matches(expressions[i])) return true;\n  }\n  return false;\n}\n\n// ✅ After — O(1) lookup per tag\nconst stopNodes = new ExpressionSet();\nstopNodes.addAll(expressions);\nstopNodes.matchesAny(matcher);\n//or matcher.matchesAny(stopNodes)\n```\n\n---\n\n## 📦 ExpressionSet API\n\n`ExpressionSet` is an indexed collection of `Expression` objects designed for efficient\nbulk matching. Build it once from your config, then call `matchesAny()` on every tag.\n\n### Constructor\n\n```javascript\nconst set = new ExpressionSet();\n```\n\n### `add(expression)` → `this`\n\nAdd a single `Expression`. Duplicate patterns (same pattern string) are silently ignored.\nReturns `this` for chaining. Throws `TypeError` if the set is sealed.\n\n```javascript\nset.add(new Expression('root.users.user'));\nset.add(new Expression('..script'));\n```\n\n### `addAll(expressions)` → `this`\n\nAdd an array of `Expression` objects at once. Returns `this` for chaining.\n\n```javascript\nset.addAll(config.stopNodes.map(p => new Expression(p)));\n```\n\n### `has(expression)` → `boolean`\n\nCheck whether an expression with the same pattern is already present.\n\n```javascript\nset.has(new Expression('root.users.user')); // true / false\n```\n\n### `seal()` → `this`\n\nPrevent further additions. Any subsequent call to `add()` or `addAll()` throws a `TypeError`.\nUseful to guard against accidental mutation once parsing has started.\n\n```javascript\nconst stopNodes = new ExpressionSet();\nstopNodes.addAll(patterns).seal();\n\nstopNodes.add(new Expression('root.extra')); // ❌ TypeError: ExpressionSet is sealed\n```\n\n### `size` → `number`\n\nNumber of distinct expressions in the set.\n\n```javascript\nset.size; // 3\n```\n\n### `isSealed` → `boolean`\n\nWhether `seal()` has been called.\n\n### `matchesAny(matcher)` → `boolean`\n\nReturns `true` if the matcher's current path matches **any** expression in the set.\nAccepts both a `Matcher` instance and a `MatcherView`.\n\n```javascript\nif (stopNodes.matchesAny(matcher)) { /* ... */ }\nif (stopNodes.matchesAny(matcher.readOnly())) { /* ... */ } // also works\n```\n\n**How indexing works:** expressions are bucketed at `add()` time, not at match time.\n\n| Expression type | Bucket | Lookup cost |\n|---|---|---|\n| Fixed path, concrete tag (`root.users.user`) | `depth:tag` map | O(1) |\n| Fixed path, wildcard tag (`root.config.*`) | `depth` map | O(1) |\n| Deep wildcard (`..script`) | flat list | O(D) — always scanned |\n\nIn practice, deep-wildcard expressions are rare in configs, so the list stays small.\n\n### `findMatch(matcher)` → `Expression`\n\nReturns the Expression instance that matched the current path. Accepts both a `Matcher` instance and a `MatcherView`.\n\n```javascript\nconst node = stopNodes.findMatch(matcher);\n```\n\n\n### Example 7: ExpressionSet in a real parser loop\n\n```javascript\nimport { XMLParser } from 'fast-xml-parser';\nimport { Expression, ExpressionSet, Matcher } from 'path-expression-matcher';\n\n// Config-time setup\nconst stopNodes = new ExpressionSet();\nstopNodes\n  .addAll(['script', 'style'].map(t => new Expression(`..${t}`)))\n  .seal();\n\nconst matcher = new Matcher();\n\nconst parser = new XMLParser({\n  onOpenTag(tagName, attrs) {\n    matcher.push(tagName, attrs);\n    if (stopNodes.matchesAny(matcher)) {\n      // treat as stop node\n    }\n  },\n  onCloseTag() {\n    matcher.pop();\n  },\n});\n```\n\n\n\n## 🔗 Integration with fast-xml-parser\n\n**Basic integration:**\n\n```javascript\nimport { XMLParser } from 'fast-xml-parser';\nimport { Expression, Matcher } from 'path-expression-matcher';\n\nconst parser = new XMLParser({\n  // Custom options using path-expression-matcher\n  stopNodes: [\"script\", \"style\"].map(tag => new Expression(`..${tag}`)),\n  \n  tagValueProcessor: (tagName, value, jPath, hasAttrs, isLeaf, matcher) => {\n    // matcher is available in callbacks\n    if (matcher.matches(new Expression(\"..user[type=admin]\"))) {\n      return enhanceValue(value);\n    }\n    return value;\n  }\n});\n```\n\n## 📄 License\n\nMIT\n\n## 🤝 Contributing\n\nIssues and PRs welcome! This package is designed to be used by XML/JSON parsers like fast-xml-parser. But can be used with any formar parser.\n","readmeFilename":"README.md"}