### Well-formed XML Example
Source: https://github.com/lddubeau/saxes/blob/master/CONTRIBUTING.md
This is an example of well-formed XML. Optimize your code for this format rather than more complex, whitespace-heavy variations.
```xml
something
```
--------------------------------
### Basic Saxes XML Parsing Example
Source: https://github.com/lddubeau/saxes/blob/master/README.md
Demonstrates the basic usage of the Saxes parser, including setting up event handlers for errors, text, open tags, and the end of the document. This snippet shows how to write XML data to the parser and close the stream.
```javascript
var saxes = require("./lib/saxes"),
parser = new saxes.SaxesParser();
parser.on("error", function (e) {
// an error happened.
});
parser.on("text", function (t) {
// got some text. t is the string of text.
});
parser.on("opentag", function (node) {
// opened a tag. node has "name" and "attributes"
});
parser.on("end", function () {
// parser stream is done, and ready to have more stuff written to it.
});
parser.write('Hello, world!').close();
```
--------------------------------
### Whitespace-Tolerant Well-formed XML Example
Source: https://github.com/lddubeau/saxes/blob/master/CONTRIBUTING.md
This is also well-formed XML, demonstrating that Saxes can handle significant whitespace. However, optimize for cleaner XML as shown in the other example.
```xml
something
```
--------------------------------
### Custom Entity Handling in Saxes
Source: https://context7.com/lddubeau/saxes/llms.txt
Customize entity expansions by modifying the `parser.ENTITIES` map. Entities can be pre-registered or added dynamically, for example, after receiving a `doctype` event.
```typescript
import { SaxesParser } from "saxes";
const parser = new SaxesParser();
const texts: string[] = [];
// Pre-register custom entities before parsing
parser.ENTITIES["copy"] = "©";
parser.ENTITIES["trade"] = "™";
parser.ENTITIES["company"] = "Acme Corp.";
parser.on("text", (t) => texts.push(t));
parser.on("error", (err) => console.error(err.message));
// Listen to doctype and add entities dynamically
parser.on("doctype", (_doctypeStr) => {
parser.ENTITIES["logo"] = "[LOGO]";
});
parser.write(
']>' +
"© ™ by &company; &logo;
"
);
parser.close();
console.log(texts.join(""));
// => "© ™ by Acme Corp. [LOGO]"
```
--------------------------------
### Position Tracking in Saxes
Source: https://context7.com/lddubeau/saxes/llms.txt
Enable position tracking to get `line`, `column`, `columnIndex`, and `position` for parser events. Disable it with `position: false` for maximum throughput.
```typescript
import { SaxesParser } from "saxes";
const parser = new SaxesParser({ position: true, fileName: "source.xml" });
parser.on("opentag", (tag) => {
console.log(
`<${tag.name}> at line=${parser.line} col=${parser.column} ` +
`colIdx=${parser.columnIndex} pos=${parser.position}`
);
});
parser.on("error", (err) => {
// Error messages automatically include file:line:col prefix
console.error(err.message);
// => "source.xml:3:5: unmatched closing tag: foo."
});
parser.write(`\n\n \n`);
parser.close();
// => at line=2 col=6 colIdx=6 pos=27
// => at line=3 col=17 colIdx=17 pos=...
// Disable position tracking for maximum throughput
const fastParser = new SaxesParser({ position: false });
fastParser.on("opentag", () => { /* parser.line etc. still exist but are not updated */ });
```
--------------------------------
### Run Performance Test
Source: https://github.com/lddubeau/saxes/blob/master/CONTRIBUTING.md
Execute this command to benchmark the performance of the null-parser with a given XML document. Run this before and after your changes to assess performance impact.
```terminal
$ node examples/null-parser.js examples/data/docbook.rng
```
--------------------------------
### Constructor Arguments
Source: https://github.com/lddubeau/saxes/blob/master/README.md
Options available when creating a new SAXES parser instance.
```APIDOC
## Constructor Arguments
Settings supported:
* `xmlns` - Boolean. If `true`, then namespaces are supported. Default is `false`.
* `position` - Boolean. If `false`, then don't track line/col/position. Unset is treated as `true`. Default is unset. Currently, setting this to `false` only results in a cosmetic change: the errors reported do not contain position information. sax-js would literally turn off the position-computing logic if this flag was set to false. The notion was that it would optimize execution. In saxes at least it turns out that continually testing this flag causes a cost that offsets the benefits of turning off this logic.
* `fileName` - String. Set a file name for error reporting. This is useful only when tracking positions. You may leave it unset.
* `fragment` - Boolean. If `true`, parse the XML as an XML fragment. Default is `false`.
* `additionalNamespaces` - A plain object whose key, value pairs define namespaces known before parsing the XML file. It is not legal to pass bindings for the namespaces `"xml"` or `"xmlns"`.
* `defaultXMLVersion` - The default version of the XML specification to use if the document contains no XML declaration. If the document does contain an XML declaration, then this setting is ignored. Must be `"1.0"` or `"1.1"`. The default is `"1.0"`.
* `forceXMLVersion` - Boolean. A flag indicating whether to force the XML version used for parsing to the value of `defaultXMLVersion`. When this flag is `true`, `defaultXMLVersion` must be specified. If unspecified, the default value of this flag is `false`.
Example: suppose you are parsing a document that has an XML declaration specifying XML version 1.1.
If you set `defaultXMLVersion` to `"1.0"` without setting `forceXMLVersion` then the XML declaration will override the value of `defaultXMLVersion` and the document will be parsed according to XML 1.1.
If you set `defaultXMLVersion` to `"1.0"` and set `forceXMLVersion` to `true`, then the XML declaration will be ignored and the document will be parsed according to XML 1.0.
```
--------------------------------
### Methods
Source: https://github.com/lddubeau/saxes/blob/master/README.md
Core methods for interacting with the SAXES parser.
```APIDOC
## Methods
`write` - Write bytes onto the stream. You don't have to pass the whole document in one `write` call. You can read your source chunk by chunk and call `write` with each chunk.
`close` - Close the stream. Once closed, no more data may be written until it is done processing the buffer, which is signaled by the `end` event.
```
--------------------------------
### Events
Source: https://github.com/lddubeau/saxes/blob/master/README.md
Information on how to listen to and handle parser events.
```APIDOC
## Events
To listen to an event, override `on`. The list of supported events are also in the exported `EVENTS` array.
See the JSDOC comments in the source code for a description of each supported event.
```
--------------------------------
### SaxesParser Constructor
Source: https://context7.com/lddubeau/saxes/llms.txt
Constructs a new SaxesParser instance with optional configuration. Options can control namespace processing, position tracking, XML version, fragment mode, and error reporting.
```APIDOC
## `new SaxesParser(opt?)` — Create a parser instance
Constructs a new parser with the given options. Options control namespace processing, position tracking, XML version handling, fragment mode, and error reporting file name. Every call to `close()` resets the parser so it can be reused for a new document.
```typescript
import { SaxesParser, EVENTS } from "saxes";
// Basic parser (no namespace tracking)
const parser = new SaxesParser();
// Namespace-aware parser with position tracking and a file name for errors
const nsParser = new SaxesParser({
xmlns: true,
position: true,
fileName: "document.xml",
});
// Force XML 1.0 regardless of the document's own XML declaration
const v10Parser = new SaxesParser({
defaultXMLVersion: "1.0",
forceXMLVersion: true,
});
// Fragment parser: accepts content without a single root element
const fragParser = new SaxesParser({
xmlns: true,
fragment: true,
additionalNamespaces: { dc: "http://purl.org/dc/elements/1.1/" },
});
```
```
--------------------------------
### Create SaxesParser Instance
Source: https://context7.com/lddubeau/saxes/llms.txt
Instantiate SaxesParser with options for namespace processing, position tracking, XML version, fragment mode, and additional namespaces. Each parser instance can be reused after calling close().
```typescript
import { SaxesParser, EVENTS } from "saxes";
// Basic parser (no namespace tracking)
const parser = new SaxesParser();
// Namespace-aware parser with position tracking and a file name for errors
const nsParser = new SaxesParser({
xmlns: true,
position: true,
fileName: "document.xml",
});
// Force XML 1.0 regardless of the document's own XML declaration
const v10Parser = new SaxesParser({
defaultXMLVersion: "1.0",
forceXMLVersion: true,
});
// Fragment parser: accepts content without a single root element
const fragParser = new SaxesParser({
xmlns: true,
fragment: true,
additionalNamespaces: { dc: "http://purl.org/dc/elements/1.1/" },
});
```
--------------------------------
### Create and report errors with parser.makeError() / parser.fail()
Source: https://context7.com/lddubeau/saxes/llms.txt
Use `makeError()` to create an `Error` object with the current parser position. Use `fail()` to report application-level well-formedness issues, which either calls the `error` handler or throws an error.
```typescript
import { SaxesParser } from "saxes";
const parser = new SaxesParser({ fileName: "data.xml", position: true });
const parseErrors: string[] = [];
parser.on("error", (err) => parseErrors.push(err.message));
parser.on("opentag", (tag) => {
// Manually validate application constraints during parsing
if (tag.name === "price" && !tag.attributes["currency"]) {
parser.fail("price element must have a currency attribute");
// => parseErrors will contain: "data.xml:2:7: price element must have a currency attribute"
}
});
parser.write("9.99");
parser.close();
console.log(parseErrors);
// => ["data.xml:1:14: price element must have a currency attribute"]
// makeError without throwing:
const err = parser.makeError("custom diagnostic");
console.log(err.message); // => "data.xml:1:1: custom diagnostic"
```
--------------------------------
### Define Additional Namespaces in Saxes
Source: https://github.com/lddubeau/saxes/blob/master/README.md
Use the `additionalNamespaces` option during parser initialization to pre-define namespace prefix-to-URI bindings. This is useful when a set of namespaces is known beforehand.
```javascript
const saxes = require('saxes');
const parser = new saxes.SaxesParser({
additionalNamespaces: {
"svg": "http://www.w3.org/2000/svg"
}
});
```
--------------------------------
### Properties
Source: https://github.com/lddubeau/saxes/blob/master/README.md
Properties providing information about the parser's current state.
```APIDOC
## Properties
The parser has the following properties:
`line`, `column`, `columnIndex`, `position` - Indications of the position in the XML document where the parser currently is looking. The `columnIndex` property counts columns as if indexing into a JavaScript string, whereas the `column` property counts Unicode characters.
`closed` - Boolean indicating whether or not the parser can be written to. If it's `true`, then wait for the `ready` event to write again.
`opt` - Any options passed into the constructor.
`xmlDecl` - The XML declaration for this document. It contains the fields `version`, `encoding` and `standalone`. They are all `undefined` before encountering the XML declaration. If they are undefined after the XML declaration, the corresponding value was not set by the declaration. There is no event associated with the XML declaration. In a well-formed document, the XML declaration may be preceded only by an optional BOM. So by the time any event generated by the parser happens, the declaration has been processed if present at all. Otherwise, you have a malformed document, and as stated above, you cannot rely on the parser data!
```
--------------------------------
### parser.write(chunk) and parser.close()
Source: https://context7.com/lddubeau/saxes/llms.txt
Feed XML data to the parser incrementally using `write(chunk)` and signal the end of input with `write(null)` or `close()`. This method returns `this` for chaining and triggers final checks and events upon completion.
```APIDOC
## `parser.write(chunk)` — Feed XML data to the parser
Writes a string chunk to the parser. May be called multiple times to stream data incrementally. Pass `null` (or call `close()`) to signal end-of-input, which triggers final well-formedness checks and fires the `end` event. Returns `this` for chaining.
## `parser.close()` — Close the stream and finalize parsing
Alias for `write(null)`. Signals the end of the XML document, performs final well-formedness checks (e.g., unclosed tags, missing root element), fires `end`, then resets the parser so it is ready for a new document.
```
--------------------------------
### Resolve namespace prefix to URI with parser.resolve()
Source: https://context7.com/lddubeau/saxes/llms.txt
When `xmlns` is enabled, `resolve()` returns the URI for a given namespace prefix based on the current in-scope bindings. It returns `undefined` if the prefix is not bound.
```typescript
import { SaxesParser } from "saxes";
const parser = new SaxesParser({
xmlns: true,
additionalNamespaces: {
dc: "http://purl.org/dc/elements/1.1/",
},
});
parser.on("opentag", (tag) => {
// Manually resolve any prefix mid-parse
const dcUri = parser.resolve("dc");
console.log(dcUri); // => "http://purl.org/dc/elements/1.1/"
const xmlUri = parser.resolve("xml");
console.log(xmlUri); // => "http://www.w3.org/XML/1998/namespace"
const unknown = parser.resolve("unknown");
console.log(unknown); // => undefined
});
parser.write('');
parser.close();
// Inside opentag for , resolve("eg") => "http://example.com/"
```
--------------------------------
### Combine Additional Namespaces and Resolve Prefix in Saxes
Source: https://github.com/lddubeau/saxes/blob/master/README.md
Both `additionalNamespaces` and `resolvePrefix` can be used together. `additionalNamespaces` are applied first, followed by `resolvePrefix` for any remaining unresolved prefixes.
```javascript
const saxes = require('saxes');
const parser = new saxes.SaxesParser({
additionalNamespaces: {
"svg": "http://www.w3.org/2000/svg"
},
resolvePrefix: function(prefix) {
if (prefix === 'custom') {
return 'http://example.com/custom';
}
return null;
}
});
```
--------------------------------
### parser.makeError(message) and parser.fail(message)
Source: https://context7.com/lddubeau/saxes/llms.txt
Create and report errors with current parser position information. `makeError` constructs an `Error` object, while `fail` calls `makeError` and handles the error via the registered handler or by throwing.
```APIDOC
## `parser.makeError(message)` / `parser.fail(message)` — Error creation and reporting
`makeError` builds an `Error` with the current parser position (file name, line, column) prepended to the message. `fail` calls `makeError` and either passes the error to the registered `error` handler or throws it if no handler is set. Client code can call `fail` to report application-level well-formedness issues.
```
--------------------------------
### Resolve Prefixes with a Custom Function in Saxes
Source: https://github.com/lddubeau/saxes/blob/master/README.md
Provide a `resolvePrefix` function to the SaxesParser constructor to handle namespace prefix resolution when the parser cannot resolve them automatically. This is an alternative to `additionalNamespaces` for dynamic resolution.
```javascript
const saxes = require('saxes');
const parser = new saxes.SaxesParser({
resolvePrefix: function(prefix) {
if (prefix === 'custom') {
return 'http://example.com/custom';
}
return null;
}
});
```
--------------------------------
### Accessing XML Declaration with SaxesParser
Source: https://context7.com/lddubeau/saxes/llms.txt
Demonstrates how to access the XML declaration fields (version, encoding, standalone) using the `xmlDecl` property and the `xmldecl` event. Fields are undefined if no declaration is present.
```typescript
import { SaxesParser } from "saxes";
const parser = new SaxesParser();
parser.on("xmldecl", (decl) => {
console.log("From event:", decl);
// From event: { version: '1.1', encoding: 'utf-8', standalone: 'yes' }
});
parser.on("opentagstart", () => {
// parser.xmlDecl is already populated by the time the first tag fires
console.log("From property:", parser.xmlDecl);
// From property: { version: '1.1', encoding: 'utf-8', standalone: 'yes' }
});
parser.write('');
parser.close();
// Document with no XML declaration — fields remain undefined
const p2 = new SaxesParser();
p2.on("opentag", () => {
console.log(p2.xmlDecl);
// => { version: undefined, encoding: undefined, standalone: undefined }
});
p2.write("").close();
```
--------------------------------
### Fragment Parsing with Saxes
Source: https://context7.com/lddubeau/saxes/llms.txt
Enable fragment mode to parse XML with multiple top-level elements or text nodes. Use `additionalNamespaces` for pre-defined namespaces or `resolvePrefix` for lazy namespace lookups.
```typescript
import { SaxesParser } from "saxes";
// Parse a fragment with pre-defined namespaces
const parser = new SaxesParser({
xmlns: true,
fragment: true,
additionalNamespaces: { foo: "http://example.com/foo" },
});
const events: [string, unknown][] = [];
parser.on("text", (t) => events.push(["text", t]));
parser.on("opentag", (tag) => events.push(["opentag", tag.name]));
parser.on("closetag", (tag) => events.push(["closetag", tag.name]));
parser.on("error", (err) => events.push(["error", err.message]));
parser.write("Hello world and more");
parser.close();
console.log(events);
// => [
// ["text", "Hello "],
// ["opentag", "foo:bar"],
// ["text", "world"],
// ["closetag", "foo:bar"],
// ["text", " and "],
// ["opentag", "baz"],
// ["closetag", "baz"],
// ["text", " more"],
// ]
// resolvePrefix variant — lazy namespace lookup
const lazyParser = new SaxesParser({
xmlns: true,
fragment: true,
resolvePrefix: (prefix) => {
const map: Record = {
dc: "http://purl.org/dc/elements/1.1/",
rdf: "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
};
return map[prefix];
},
});
lazyParser.on("opentag", (tag) => console.log(tag.name, "->", tag.uri));
lazyParser.write("My Title");
lazyParser.close();
// => "dc:title -> http://purl.org/dc/elements/1.1/"
```
--------------------------------
### parser.resolve(prefix)
Source: https://context7.com/lddubeau/saxes/llms.txt
Resolve a namespace prefix to its corresponding URI. This method is available when `xmlns` is enabled and uses the current in-scope namespace bindings to find the URI.
```APIDOC
## `parser.resolve(prefix)` — Resolve a namespace prefix to its URI
Available when `xmlns: true`. Resolves a namespace prefix using the current in-scope namespace bindings. Returns the URI string, or `undefined` if the prefix is not bound.
```
--------------------------------
### Namespace-Aware Parsing with Saxes
Source: https://context7.com/lddubeau/saxes/llms.txt
Enables namespace-aware parsing by setting `xmlns: true`. The `opentag` event provides `SaxesTagNS` objects with prefix, local name, URI, and new namespace bindings. Attributes are delivered as `SaxesAttributeNSIncomplete`.
```typescript
import { SaxesParser, SaxesTagNS, SaxesAttributeNS } from "saxes";
const parser = new SaxesParser({ xmlns: true });
parser.on("opentag", (tag: SaxesTagNS) => {
console.log("name :", tag.name);
console.log("prefix :", tag.prefix);
console.log("local :", tag.local);
console.log("uri :", tag.uri);
console.log("ns :", tag.ns); // new bindings on *this* element
console.log("selfClose:", tag.isSelfClosing);
for (const [attrName, attr] of Object.entries(tag.attributes)) {
const a = attr as SaxesAttributeNS;
console.log(` attr ${attrName}: local=${a.local} prefix=${a.prefix} uri=${a.uri} value=${a.value}`);
}
});
parser.write(
'' +
' ' +
''
);
parser.close();
// opentag for :
// name: root, prefix: "", local: root, uri: http://example.com/default
// ns: { a: "http://example.com/a", "": "http://example.com/default" }
//
// opentag for :
// name: a:child, prefix: a, local: child, uri: http://example.com/a
// ns: {}
// attr a:id: local=id prefix=a uri=http://example.com/a value=42
// attr label: local=label prefix="" uri="" value=hello
```
--------------------------------
### Parse XML Fragments with Saxes
Source: https://github.com/lddubeau/saxes/blob/master/README.md
Initialize the saxes parser with the `fragment: true` option to parse XML fragments. This option adjusts the parsing state and disables well-formedness checks appropriate for fragments.
```javascript
const saxes = require('saxes');
const parser = new saxes.SaxesParser({
fragment: true
});
```
--------------------------------
### Event Handler Registration and Removal
Source: https://context7.com/lddubeau/saxes/llms.txt
Register and remove handlers for various parser events. The parser supports one handler per event type, and all supported event names are exported in the `EVENTS` array.
```APIDOC
## `parser.on(event, handler)` / `parser.off(event)` — Register and remove event handlers
Sets or removes a handler for one of the named parser events. The parser supports exactly one handler per event type; setting a new handler silently replaces any existing one. All supported event names are exported in the `EVENTS` array.
```typescript
import { SaxesParser, EVENTS, SaxesTagNS } from "saxes";
const parser = new SaxesParser({ xmlns: true, fileName: "feed.xml" });
// Register handlers for every event
parser.on("xmldecl", (decl) => {
// decl: { version?: string; encoding?: string; standalone?: string }
console.log("XML declaration:", decl);
// => { version: '1.0', encoding: 'utf-8', standalone: undefined }
});
parser.on("opentagstart", (tag) => {
// Fired as soon as the tag name is known, before attributes are processed
console.log("Tag start:", tag.name);
});
parser.on("attribute", (attr) => {
// { name, prefix, local, value } when xmlns:true; { name, value } otherwise
console.log("Attribute:", attr.name, "=", attr.value);
});
parser.on("opentag", (tag: SaxesTagNS) => {
// Full tag object with resolved namespace info
console.log(`<${tag.name}> uri=${tag.uri} self-closing=${tag.isSelfClosing}`);
console.log(" attributes:", tag.attributes);
console.log(" ns bindings:", tag.ns);
});
parser.on("closetag", (tag: SaxesTagNS) => {
console.log(`${tag.name}>`);
});
parser.on("text", (text) => {
console.log("Text:", JSON.stringify(text));
});
parser.on("cdata", (data) => {
console.log("CDATA:", data);
});
parser.on("comment", (comment) => {
console.log("Comment:", comment);
});
parser.on("processinginstruction", ({ target, body }) => {
console.log(`PI: target=${target} body=${body}`);
});
parser.on("doctype", (doctype) => {
console.log("DOCTYPE:", doctype);
});
parser.on("error", (err) => {
// Custom error handler; default throws. Receives an Error with
// fileName:line:column prefix when position tracking is active.
console.error("Parse error:", err.message);
// => "feed.xml:3:14: unbound namespace prefix: \"foo\"."
});
parser.on("end", () => {
console.log("Parsing complete.");
});
parser.on("ready", () => {
console.log("Parser reset and ready for new document.");
});
// Remove a handler
parser.off("comment");
// Iterate all supported event names
console.log(EVENTS);
// => ["xmldecl","text","processinginstruction","doctype","comment",
// "opentagstart","attribute","opentag","closetag","cdata","error","end","ready"]
```
```
--------------------------------
### Feed XML data to the parser with parser.write()
Source: https://context7.com/lddubeau/saxes/llms.txt
Use `write()` to feed XML data to the parser incrementally. Call `write(null)` or `close()` to signal the end of input and trigger final checks. Returns `this` for chaining.
```typescript
import { SaxesParser } from "saxes";
import * as fs from "fs";
// --- Single write ---
const parser = new SaxesParser({ xmlns: true });
const results: string[] = [];
parser.on("opentag", (tag) => results.push(tag.name));
parser.on("error", (err) => console.error(err.message));
parser.write('helloworld');
parser.close();
console.log(results); // => ["root", "child", "child"]
// --- Chunked / streaming write ---
const streamParser = new SaxesParser({ xmlns: true });
streamParser.on("text", (t) => process.stdout.write(t));
streamParser.on("error", (err) => console.error(err.message));
const stream = fs.createReadStream("large.xml", { encoding: "utf8" });
stream.on("data", (chunk: string) => streamParser.write(chunk));
stream.on("end", () => streamParser.close());
// --- write(null) is equivalent to close() ---
const p2 = new SaxesParser();
p2.on("opentag", (tag) => console.log(tag.name));
p2.write("").write(null); // close via null
```
--------------------------------
### Error Handling
Source: https://github.com/lddubeau/saxes/blob/master/README.md
Guidelines for handling errors reported by the SAXES parser.
```APIDOC
## Error Handling
The parser continues to parse even upon encountering errors, and does its best to continue reporting errors. You should heed all errors reported. After an error, however, saxes may interpret your document incorrectly. For instance ```` is invalid XML. Did you mean to have ```` or ```` or some other variation? For the sake of continuing to provide errors, saxes will continue parsing the document, but the structure it reports may be incorrect. It is only after the errors are fixed in the document that saxes can provide a reliable interpretation of the document.
That leaves you with two rules of thumb when using saxes:
* Pay attention to the errors that saxes report. The default `onerror` handler throws, so by default, you cannot miss errors.
* **ONCE AN ERROR HAS BEEN ENCOUNTERED, STOP RELYING ON THE EVENT HANDLERS OTHER THAN `onerror`.** As explained above, when saxes runs into a well-formedness problem, it makes a guess in order to continue reporting more errors. The guess may be wrong.
```
--------------------------------
### Close the stream and finalize parsing with parser.close()
Source: https://context7.com/lddubeau/saxes/llms.txt
Use `close()` to signal the end of the XML document, perform final well-formedness checks, fire the `end` event, and reset the parser for reuse. It is an alias for `write(null)`.
```typescript
import { SaxesParser } from "saxes";
const parser = new SaxesParser({ fileName: "doc.xml" });
const errors: string[] = [];
const tags: string[] = [];
parser.on("opentag", (tag) => tags.push(tag.name));
parser.on("error", (err) => errors.push(err.message));
parser.on("end", () => {
console.log("tags:", tags); // => ["root", "item"]
console.log("errors:", errors); // => []
});
parser.write(" ");
parser.close();
// After close, the parser auto-resets — reuse it immediately:
parser.write("").close();
```
--------------------------------
### Register and Remove Event Handlers
Source: https://context7.com/lddubeau/saxes/llms.txt
Register handlers for various parser events like 'xmldecl', 'opentag', 'text', 'error', and 'end'. Use 'off()' to remove handlers. All supported event names are exported in the EVENTS array.
```typescript
import { SaxesParser, EVENTS, SaxesTagNS } from "saxes";
const parser = new SaxesParser({ xmlns: true, fileName: "feed.xml" });
// Register handlers for every event
parser.on("xmldecl", (decl) => {
// decl: { version?: string; encoding?: string; standalone?: string }
console.log("XML declaration:", decl);
// => { version: '1.0', encoding: 'utf-8', standalone: undefined }
});
parser.on("opentagstart", (tag) => {
// Fired as soon as the tag name is known, before attributes are processed
console.log("Tag start:", tag.name);
});
parser.on("attribute", (attr) => {
// { name, prefix, local, value } when xmlns:true; { name, value } otherwise
console.log("Attribute:", attr.name, "=", attr.value);
});
parser.on("opentag", (tag: SaxesTagNS) => {
// Full tag object with resolved namespace info
console.log(`<${tag.name}> uri=${tag.uri} self-closing=${tag.isSelfClosing}`);
console.log(" attributes:", tag.attributes);
console.log(" ns bindings:", tag.ns);
});
parser.on("closetag", (tag: SaxesTagNS) => {
console.log(`${tag.name}>`);
});
parser.on("text", (text) => {
console.log("Text:", JSON.stringify(text));
});
parser.on("cdata", (data) => {
console.log("CDATA:", data);
});
parser.on("comment", (comment) => {
console.log("Comment:", comment);
});
parser.on("processinginstruction", ({ target, body }) => {
console.log(`PI: target=${target} body=${body}`);
});
parser.on("doctype", (doctype) => {
console.log("DOCTYPE:", doctype);
});
parser.on("error", (err) => {
// Custom error handler; default throws. Receives an Error with
// fileName:line:column prefix when position tracking is active.
console.error("Parse error:", err.message);
// => "feed.xml:3:14: unbound namespace prefix: \"foo\"."
});
parser.on("end", () => {
console.log("Parsing complete.");
});
parser.on("ready", () => {
console.log("Parser reset and ready for new document.");
});
// Remove a handler
parser.off("comment");
// Iterate all supported event names
console.log(EVENTS);
// => ["xmldecl","text","processinginstruction","doctype","comment",
// "opentagstart","attribute","opentag","closetag","cdata","error","end","ready"]
```
--------------------------------
### Handle Unicode Surrogates in Saxes
Source: https://github.com/lddubeau/saxes/blob/master/README.md
Saxes versions 4 and above can handle Unicode characters split across surrogates when feeding data in chunks. For optimal performance, avoid splitting Unicode strings across surrogates by feeding all data at once if possible.
```javascript
const a = "\u{1F4A9}"[0];
const b = "\u{1F4A9}"[1];
// Avoid feeding 'a' and 'b' separately if they form a split surrogate.
```
=== COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.