npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@innodatalabs/lxmlx-js

v2.0.2

Published

XML as a JSON event stream

Readme

lxmlx-js

Build Status npm version

XML representations as a JSON stream. Convenient for content-oriented XML tasks.

This is a JS port of Python package lxmlx.

Installation

npm i lxmlx-js --save

Building and testing:

npm i
make

Event stream

Event stream is XML representation which is equivalent to the in-memory tree.

It is similar to SAX parsing events, except:

  1. we use simplified set of events (ENTER, EXIT, TEXT, COMMENT and PI)
  2. events are represented natively as streams (generators)
  3. event objects are JSON-serializable

Each event in the stream is a dict containing at least type key

ENTER event

ENTER event is fired to indicate the opening of an XML tag. Payload:

  • type must be string "enter" (or constant import { ENTER } from 'lxmlx-js';)
  • tag element tag
  • attrib optional - a dictionary of attributes

Example:

{
  type  : 'enter',
  tag   : 'font',
  attrib: {
    name : 'Times',
    style: 'bold'
  }
}

EXIT event

EXIT event is fired to indicate closing of an XML tag. No payload is expected, because it implicitly corresponds to the opening tag from ENTER event.

  • type must be string "exit" (or constant import { EXIT } from 'lxmlx-js';)

Example:

{
  type: "exit"
}

TEXT event

TEXT event is fired to indicate XML CTEXT value. Payload is:

  • type must be string "text" (or constant import { TEXT } from 'lxmlx-js';)
  • text - required

Example:

{
  type: "text",
  text: "Hello!"
}

COMMENT

COMMENT - represents XML comment

Payload is:

  • type must be string "comment" (or constant import { COMMENT } from 'lxmlx-js';)
  • text - required

Example:

{
  type: "comment",
  text: "Hello!"
}

PI

PI - processing instruction. Payload:

  • type must be string "pi" (or constant lxmlx.event.PI)
  • target - required PI target (aka tag)
  • text - optional PI text content

Example:

{
  type  : "pi",
  target: "myPI",
  text  : "my cool text here"
}

Our definition of event stream is consistent with depth-first left-to-right traversal of XML tree.

Example

XML document below

<book>
   <chapter id="1">Introduction</chapter>
   <chapter id="2">Preface</chapter>
   <chapter id="3">Title</chapter>
</book>

can equivalently be represented by the following event stream:

[
  {"type": "enter", "tag": "book"},

  {"type": "enter", "tag": "chapter", "attrib": {"id": "1"}},
  {"type": "text", "text": "Introduction"},
  {"type": "exit"},

  {"type": "enter", "tag": "chapter", "attrib": {"id": "2"}},
  {"type": "text", "text": "Preface"},
  {"type": "exit"},

  {"type": "enter", "tag": "chapter", "attrib": {"id": "3"}},
  {"type": "text", "text": "Title"},
  {"type": "exit"},

  {"type": "exit"}
]

Why do we need event stream representation of XML?

Some tasks are easier done using tree representation, but other tasks are better done on event stream representation.

  1. Stripping some XML tags. Remove some tags from XML document, leaving text and other tags intact. In terms of XML tree this requires carefully taking care of the children and contained text, and is pretty difficult to get it right. Especially if you need to remove many tags from a single tree - mutating the tree for each one.

    Using event stream representation this is as easy as suppressing matching ENTER and EXIT events.

  2. Extracting text content from an XML fragment. Using traditional tree representation this is not a difficult task. But using event stream representation this becomes quite trivial: accept only TEXT events and join the resulting text pieces together:

    ''.join(evt['text'] for evt in events if evt['type']==TEXT)
  3. Wrapping XML elements. Daunting task using XML tree representation. Very easy using events stream - just inject wrappers each time you detect ENTER or EXIT of a wrapee.

  4. When implemented right, event stream uses limited memory, independent of the size of the XML document. Even huge XML documents can be transformed quickly using small amount of RAM.

Well-formed event stream

Not every sequence of events is a valid event stream. The requirement of well-formedness asserts that stream corresponds to left-to-right depth-first traversal of some tree.