{"id":12691,"library":"xmldoc","title":"xmldoc: Lightweight XML Document Parser","description":"xmldoc is a lightweight JavaScript library designed for parsing and traversing XML documents. It provides a simple, object-oriented API for interacting with XML structures, backed by the robust `sax` parser. The current stable version is 2.0.3, with releases occurring as needed for bug fixes and feature enhancements, rather than on a strict cadence. A key differentiator is its minimal footprint and direct access to XML elements and attributes, avoiding more complex XPath implementations by default. Since version 2.0, it fully supports TypeScript, offering type definitions for a better developer experience, and is compatible with both CommonJS and ESM environments. It focuses on parsing and basic traversal, making it suitable for applications where full XML DOM manipulation or complex querying (like advanced XPath) is not required.","status":"active","version":"2.0.3","language":"javascript","source_language":"en","source_url":"git://github.com/nfarina/xmldoc","tags":["javascript","xml","sax","parser","xpath","document","typescript"],"install":[{"cmd":"npm install xmldoc","lang":"bash","label":"npm"},{"cmd":"yarn add xmldoc","lang":"bash","label":"yarn"},{"cmd":"pnpm add xmldoc","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Core XML parsing engine.","package":"sax"},{"reason":"Required for React Native environments due to Node.js core module polyfills.","package":"buffer","optional":true},{"reason":"Required for React Native environments due to Node.js core module polyfills.","package":"stream","optional":true}],"imports":[{"note":"ESM and TypeScript environments use named import since v2.0.","wrong":"import XmlDocument from 'xmldoc';","symbol":"XmlDocument","correct":"import { XmlDocument } from 'xmldoc';"},{"note":"CommonJS environments use named destructuring since v2.0.","wrong":"const XmlDocument = require('xmldoc');","symbol":"XmlDocument","correct":"const { XmlDocument } = require('xmldoc');"},{"note":"XmlElement is typically accessed via XmlDocument instances, but can be imported directly if needed for type hinting or specific use cases.","symbol":"XmlElement","correct":"import { XmlElement } from 'xmldoc';"}],"quickstart":{"code":"import { XmlDocument, XmlElement } from \"xmldoc\";\n\nconst xmlString = `\n<bookstore>\n  <book category=\"cooking\">\n    <title lang=\"en\">Everyday Italian</title>\n    <author>Giada De Laurentiis</author>\n    <year>2005</year>\n    <price>30.00</price>\n    <!-- A comment about Italian cuisine -->\n  </book>\n  <book category=\"children\">\n    <title lang=\"en\">Harry Potter</title>\n    <author>J.K. Rowling</author>\n    <year>2005</year>\n    <price>29.99</price>\n  </book>\n  <magazine>\n    <title>National Geographic</title>\n  </magazine>\n</bookstore>\n`;\n\n// Parse the XML string\nconst document = new XmlDocument(xmlString);\n\n// Find all books\nconst books = document.childrenNamed(\"book\");\nconsole.log(`Found ${books.length} books.`);\n\n// Access attributes and text content of the first book\nconst firstBook = books[0];\nif (firstBook) {\n  console.log(`First book title: ${firstBook.childNamed(\"title\")?.val} (Lang: ${firstBook.childNamed(\"title\")?.attr.lang})`);\n  console.log(`First book author: ${firstBook.childNamed(\"author\")?.val}`);\n  console.log(`First book category: ${firstBook.attr.category}`);\n}\n\n// Find a specific element by path\nconst harryPotterTitle = document.childNamed(\"bookstore\")\n                                  ?.childrenNamed(\"book\")\n                                  .find(book => book.childNamed(\"title\")?.val === \"Harry Potter\")\n                                  ?.childNamed(\"title\");\n\nif (harryPotterTitle) {\n  console.log(`Harry Potter title found: ${harryPotterTitle.val}`);\n}\n\n// Convert back to string (note: comments might be lost depending on version)\nconst serializedXml = document.toString({ compressed: true }); // compressed option for brevity\nconsole.log(\"Serialized XML (compressed):\", serializedXml.substring(0, 100) + \"...\"); // show first 100 chars","lang":"typescript","description":"This quickstart demonstrates parsing an XML string, traversing elements, accessing attributes and text content, and converting the document back to a string."},"warnings":[{"fix":"Update code to check for `undefined` instead of `null` or use loose equality `== null` to catch both `null` and `undefined`.","message":"Prior to v0.3.1, `xmldoc` methods returning optional values (e.g., `firstChild`, `childNamed`, `attr` for non-existent attributes) would return `null`. As of v0.3.1, these methods now consistently return `undefined`.","severity":"breaking","affected_versions":">=0.3.1"},{"fix":"For CommonJS, use `const { XmlDocument } = require('xmldoc');`. For ESM and TypeScript, use `import { XmlDocument } from 'xmldoc';`.","message":"Version 2.0 introduced full TypeScript support and updated CommonJS/ESM compatibility. This changed the primary export pattern from potentially a default export (or other patterns in older versions) to named exports for `XmlDocument`. Older `require('xmldoc')` or `import XmlDocument from 'xmldoc'` patterns may no longer work.","severity":"breaking","affected_versions":">=2.0.0"},{"fix":"If comment preservation is critical, `xmldoc` is not suitable for round-trip XML modification that must retain comments. Consider alternative XML libraries or pre-process/post-process comments if possible.","message":"When converting an `XmlDocument` or `XmlElement` back to an XML string using `toString()`, XML comments are not preserved in the output. This is a design decision of the library.","severity":"gotcha","affected_versions":">=0.1.0"},{"fix":"Do not rely strictly on the exact original order of sibling elements if your application is sensitive to it. Test thoroughly and consider alternative parsers if strict order preservation is paramount for all operations.","message":"While `xmldoc` generally attempts to maintain the order of child elements, there have been reports (e.g., GitHub Issue #41) where the order of elements might be unexpectedly altered, particularly in specific scenarios or during internal transformations.","severity":"gotcha","affected_versions":">=0.1.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"For CommonJS, use `const { XmlDocument } = require('xmldoc');`. For ESM, use `import { XmlDocument } from 'xmldoc';`.","cause":"Attempting to use `require('xmldoc')` directly without destructuring, or `import XmlDocument from 'xmldoc'` in v2.0+ (where `XmlDocument` is a named export).","error":"TypeError: XmlDocument is not a constructor"},{"fix":"Upgrade `xmldoc` to version `0.5.1` or higher to resolve the `GLOBAL` deprecation warning/error in newer Node.js environments. Alternatively, ensure your Node.js version is compatible with the `xmldoc` version in use.","cause":"Running an older version of `xmldoc` (specifically pre-0.5.1) in Node.js v6 or later, which deprecated/removed the global `GLOBAL` object.","error":"ReferenceError: GLOBAL is not defined"},{"fix":"Comments are not preserved by design. If you are experiencing incorrect character escaping, upgrade `xmldoc` to `v0.5.0` or newer, which fixed the incorrect escaping issue.","cause":"Comments are explicitly not preserved by `xmldoc`'s `toString()` method. Incorrect escaping (e.g., for `<` and `>`) was a bug in older versions (pre-0.5.0).","error":"Output XML is missing comments or has incorrect escaping for '<' or '>' characters when calling toString()."}],"ecosystem":"npm"}