Marcheur: XSLT-like Tree Processor Builder

0.9.0 · maintenance · verified Sun Apr 19

Marcheur is a JavaScript library designed for building simplistic tree-walking and pattern-matching processors, drawing inspiration from XSLT 1.0's core algorithm. It allows developers to define rules for transforming tree structures, offering functionality analogous to XSLT without aiming to be a full replacement. The current stable version is 0.9.0, indicating it is pre-1.0 and its API may still be subject to changes. Due to the incomplete documentation (marked with 'XXX TDB' in the provided README excerpt), the release cadence is likely irregular, and the project's current development activity might be low. Its key differentiator is providing a lightweight mechanism for common tree transformation needs in JavaScript where full XSLT support is cumbersome or unavailable.

Warnings

Install

Imports

Quickstart

This quickstart demonstrates how to define and apply transformation rules to a JavaScript object tree using Marcheur's `Matcher` and `qname` utilities. It illustrates a conceptual `createTreeWalker` for processing.

import { createTreeWalker } from 'marcheur'; // Hypothetical core processor builder
import { Matcher } from 'marcheur';
import { qname } from 'marcheur/qname';

// Example source data representing an XML-like JS object tree
const document = {
  element: 'root',
  attrs: { 'xmlns:foo': 'http://foo.com/ns', version: '1.0' },
  children: [
    { element: 'item', attrs: { id: 'a' }, children: ['Text A'] },
    { element: 'foo:data', attrs: { value: '123' }, children: ['Some Foo Data'] },
  ],
};

const nsMap = { foo: 'http://foo.com/ns' };

// Define transformation rules using Matcher and qname for pattern matching
const rules = [
  {
    // Match any 'item' element and transform it
    match: new Matcher().element('item'),
    apply: (node) => ({
      element: 'transformedItem',
      attrs: { ...node.attrs, processed: 'true' },
      children: node.children.map(c => typeof c === 'string' ? `MODIFIED: ${c}` : c),
    }),
  },
  {
    // Match 'foo:data' using qname for namespace-aware matching
    match: new Matcher().element(qname('foo:data', nsMap)),
    apply: (node) => ({
      element: 'foo:transformedData',
      attrs: { originalValue: node.attrs.value },
      children: ['Namespace handled!'],
    }),
  },
  {
    // Default rule: copy nodes and recurse for unmatched elements
    match: new Matcher().any(), // Assumes a generic 'any' matcher
    apply: (node, walk) => {
      if (typeof node === 'string') return node; // Handle text nodes
      return {
        ...node,
        children: node.children ? node.children.map(walk) : [],
      };
    },
  },
];

// Hypothetical function to create and execute a tree walker/processor
const walker = createTreeWalker(rules); // 'createTreeWalker' is an assumed API
const transformedDoc = walker.walk(document);

console.log('Original Document:', JSON.stringify(document, null, 2));
console.log('\nTransformed Document:', JSON.stringify(transformedDoc, null, 2));

// Direct usage of the qname utility
const qualifiedNameInfo = qname('foo:bar', nsMap);
console.log('\nqname("foo:bar", nsMap):', qualifiedNameInfo); 
// Expected output: { ns: 'http://foo.com/ns', ln: 'bar' }

const simpleNameInfo = qname('baz');
console.log('qname("baz"):', simpleNameInfo);
// Expected output: { qn: 'baz' }

view raw JSON →