</> XML Language Service v1.1.0
XML tools for JavaScript and TypeScript

XML Language Service

This tool helps you work with XML in JavaScript and TypeScript projects. It can understand XML even when it has errors, and it gives editor-like features without needing Java or native software.

$ npm install xml-language-service
Works anywhere Use it in editors, language servers, CLIs, web apps, and tests.
Handles broken XML Incomplete XML still produces a usable document tree.
No Java setup XSD validation runs through bundled Xerces-C++ WebAssembly.

Install

Install the package in an ESM-compatible Node.js project.

bash
npm install xml-language-service
Requires Node.js 18+. The package includes the WASM files needed for XSD validation.

Quick Start

Create a service, parse XML, then call the feature you need.

typescript
import { getLanguageService } from "xml-language-service";

const service = getLanguageService();

const xml = `<catalog>
  <book id="bk101">
    <title>XML Developer Guide</title>
  </book>
</catalog>`;

const document = service.parseXMLDocument("file:///catalog.xml", xml);

const completions = service.doComplete(document, { line: 1, character: 4 });
const hover = service.doHover(document, { line: 2, character: 6 });
const symbols = service.findDocumentSymbols(document);
const formatting = service.format(document, { tabSize: 2, insertSpaces: true });

console.log(completions.items);
console.log(hover);
console.log(symbols);
console.log(formatting);

await service.dispose();

Features

The service returns plain TypeScript objects, so you can connect these features to your own editor, CLI, web app, language server, or test tool.

Fault-tolerant parsing

Reads XML and builds a usable document tree, even when the file is incomplete or has syntax errors.

Auto complete

Suggests element names, attributes, and closing tags while the user is typing.

Hover info

Shows the attributes and children of the element under the cursor, or its schema documentation when a schema is associated.

Document symbols

Creates an outline of the XML structure so editors can show breadcrumbs, sidebars, and quick navigation.

Folding ranges

Finds multi-line elements and comments that can be collapsed.

Formatting

Returns text edits that re-indent the document and keep its line endings.

Rename

Renames matching opening and closing tags together so XML stays consistent.

Definition and references

Jumps between matching tags and finds other elements with the same tag name.

XSD validation

Reports syntax errors, including mismatched tags and undefined entities, and checks XML against XSD schemas with Apache Xerces-C++ compiled to WebAssembly.

How It Works

Every feature works from the parsed document. A schema is optional and only adds information.

1. Parse

The fault-tolerant parser turns XML text into an XMLDocument: an element tree plus any syntax errors.

2. Editor features

Completion, hover, symbols, folding, formatting, rename, definition and references all read that tree.

3. Find a schema

The file name and root xmlns are matched against your associations, then the built-in catalog. Completion and hover then use the schema's elements and attributes.

4. Validate

With a registered XSD, Xerces-C++ checks the raw text in one streaming pass. Without one, you get the parser's syntax errors.

Validation

Without a schema, validate() still checks that the document is well-formed, including mismatched tags and undefined entities.

typescript
const document = service.parseXMLDocument("file:///a.xml", "<a><b></a>");
const diagnostics = await service.validate("file:///a.xml", document);
// includes: expected end of tag 'b' but found 'a'

To validate against an XSD, register it once, then validate any number of documents against it.

typescript
await service.registerSchema({
  uri: "file:///catalog.xsd",
  xsdText: catalogXsd,
});

const document = service.parseXMLDocument("file:///catalog.xml", xmlText);
const diagnostics = await service.validate("file:///catalog.xsd", document);
// [{ range, message, severity: "error" | "warning" | "info", source: "xsd" | "syntax" }]

If the XSD uses xs:include or xs:import, pass the other files in imports. The keys must match the schemaLocation values used in the XSD.

typescript
await service.registerSchema({
  uri: "file:///root.xsd",
  xsdText: rootXsd,
  imports: { "types.xsd": typesXsd },
});

Schemas

Pass the document's file name to doComplete() or doHover() and the service looks up a schema for it. These files are recognised out of the box:

File Schema
pom.xmlMaven 4.0.0
web.xmlJava Servlet 3.1
persistence.xmlJPA 2.2
spring-*.xmlSpring Beans 4.3
typescript
const pom = service.parseXMLDocument("file:///project/pom.xml", text);
service.doComplete(pom, position, "pom.xml"); // modelVersion, parent, groupId, ...

Add your own associations. They take priority over the built-in ones, except for pom.xml.

typescript
service.addUserAssociation({
  pattern: "**/*.config.xml",
  xsdPath: "/absolute/path/to/config.xsd",
  isBuiltIn: false,
});
Remote schemas. resolveSchemaForDocumentAsync() downloads an XSD from an http:// or https:// systemId and caches it in .cache/xml-schemas/ under the current working directory. Files it pulls in with xs:include or xs:import are not downloaded.

Debugging

Use the printer helpers when you want to see what the parser produced.

typescript
console.log(service.printTreeAST(document));
// Document
// └── catalog
//     └── book

console.log(service.printAST(document));                     // elements and attributes
console.log(service.printAST(document, { format: "json" }));
console.log(service.printCST(document));                     // every grammar rule and token

Links

Resource URL
npm package npmjs.com/package/xml-language-service
Repository github.com/harshanacz/xml-language-service
Project using this github.com/harshanacz/xml-review-bot-demo
XML language server based on this github.com/harshanacz/xml-language-server
VS Code extension github.com/harshanacz/xml-language-client