jml-tools

0.1.3 • Public • Published

JML Tools

npm version Build Status

This library is aimed at providing a set of tools to work with XML-based markup JSON data similar to (but not the same as) JSON-ML in JavaScript. The "markup language" (JML) is defined by the non-compact JSON structure proposed by the xml-js library. It can be converted lossless to and from XML documents including mixed-content elements. The tools are fully namespace aware.

Usage

Installation

npm install jml-tools --save

or

yarn add jml-tools

Quick start

import {create} from 'jml-tools';
const name = 'person';
const data = {content: 'Freddie Mercury'};
const jmlObject = create(name, data);
console.log(jmlObject);
 
// Output:
// {
//     "elements": [
//         {
//             "elements": [
//                 {
//                     "text": "Freddie Mercury",
//                     "type": "text"
//                 }
//             ],
//             "name": "person",
//             "type": "element"
//         }
//     ]
// }

Running tests

npm test

API Reference

This library provides the following functionalities:

create

Manually creates a JML object that is fully compatible with xml-js.

Syntax

create(name[, data])

Parameters

name

A string, either prefixed or not that will be the name of the object to be created.

data

An optional data object that can have any or all of the following properties:

Property Description Examples
namespaces An object array describing the objects' namespaces with the namespace URI and an optional prefix both as string values. A namespace with only an URI is considered as the objects' default namespace similar to XML. [{prefix: 'ns', uri: 'http://example.com/ns'}]
[{uri: 'http://example.com/default'}, {prefix: 'ns', 'uri: 'http://example.org/ns'}]
content The content (if any). Can be a string for pure text content, a single JML object or an array of JML objects. 'Freddie Mercury'
attributes All attributes as an object of string key-value pairs. The values will be converted to strings if necessary. {date: '2017-12-31', time: '23:12'}

Usage example

import {create} from 'jml-tools';
const name = 'person';
const data = {content: 'Freddie Mercury'};
const jmlObject = create(name, data);
console.log(jmlObject);
 
// Output:
// {
//     "elements": [
//         {
//             "elements": [
//                 {
//                     "text": "Freddie Mercury",
//                     "type": "text"
//                 }
//             ],
//             "name": "person",
//             "type": "element"
//         }
//     ]
// }

evaluate

Evaluates a path expression similar to XPath on a JML object starting with the content of the root object. It doesn't support all of the functionalities of XPath, most importantly, while the descendant axis is available in the form of the double forward slash //, the other axes are not.

Syntax

evaluate(path, jmlObject[, options])

Parameters

path

A string that describes the individual steps that form the path to evaluate on a JML object. The steps are made up of (optionally qualified) object names, text() to select text content or @name to select an object attribute. Each step can have zero or more conditions that describe which specific objects it will match.

Examples
Path Result
/first/second All second objects that are direct children of a first object
//second/text() The direct text content of all second objects
//second//text() The text content of all second objects and their descendants
/first/@value The text content of the value attribute of all first objects
/first[@value="1"] All first objects that have a value attribute with the value 1. The value can be a string or a number
/first[.//third/text()="text"] All first objects that have third descendants that have text as direct text content. The path that specifies the condition value starts with descendants of the current (e.g. first) object and is governed by the same rules than the outer path
/first[2]/second All second objects that are a child of the second first object
/ns:first All first objects that are in the ns namespace. The ns namespace needs to be declared in the methods' options object
Notable differences to XPath
  • The value of an attribute can be accessed directly by /something/@attribute instead of data(/something/@attribute) or /something/@attribute/string()
  • When evaluating on an object that is equivalent to <persons><person><name><given>Freddy</given></name></person><person><name><given>Brian</given></name></person></persons>, //given[1] returns the first of all given objects, wherever they appear, instead of the first given object in each individual context like in XPath. A functionality similar to the default in XPath behaviour can be achieved by //name/given[1].
jmlObject

A valid JML object as created by the create method and xml-js. The path will be evaluated on its contents starting inside the root object.

options

An optional object that describes the options for the evaluation:

Property Description Examples
namespaces An object array describing the namespaces used in the path with their namespace URI and prefix, both as string values. Namespaces that appear as default values in the target JML object still need to be declared with a prefix in the options object. [{prefix: 'ns1', uri: 'http://example.com/ns1'}, {prefix: 'ns2', uri: 'http://example.com/ns2'}]

Usage example

import {evaluate} from 'jml-tools';
// original XML:
// <paragraph xmlns="http://example.com/ns">JSON is just as <emphasized>fun</emphasized> as XML.</paragraph>
const jmlObject = {
    elements: [{
        type: 'element',
        name: 'paragraph',
        attributes: {
            xmlns: 'http://example.com/ns'
        },
        elements: [
            {type: 'text', text: 'JSON is just as '},
            {
                type: 'element',
                name: 'emphasized',
                elements: [
                    {type: 'text', text: 'fun'}
                ]
            },
            {type: 'text', text: ' as XML.'}
        ]
    }]
};
const result = evaluate('/ns:emphasized/text()', jmlObject, {namespaces: [{prefix: 'ns', uri: 'http://example.com/ns'}]});
console.log(result);
 
// Output:
// ['fun']

serialize

Serializes a JML object to a string according to fully qualified mappings that target either the whole object or individual child objects. This can, for example, be used to transform arbitrary structures into HTML or a different JSON representation.

Syntax

serialize(jmlObject, mappings[, options])

Parameters

jmlObject

A valid JML object as created by the create method and xml-js. It will be serialized according to the provided mappings.

mappings

The rules to apply to the jmlObject. It describes how its contents will be serialized. It can any of the following:

  1. An object consisting of string key-value pairs describing the mapping into serialized XML. An asterisk (*) as key is interpreted as the default mapping to use if no other mapping matches.
  2. An object consisting of key-key value pairs similar to option 1 above with the difference that the value is not a string but a function that should return the transformed content as a string. The functions' signature is function({name, contents, attributes}).
  3. A function that will be applied to each child object (similar to the child elements in XML). The functions' signature is function({name, contents, attributes}).

Note 1: The options 1 and 2 can be mixed with each other. It is possible to map some keys to string values and some to functions.

Note 2: If the object to be match by options 1 and 2 above are qualified, the objects' namespace needs to be declared in the options object and the correct prefixes need to be added to the keys to match the specific objects.

Example Description
({content, name}) => `<span data-name="${name}">${content}</span>`) A single function is applied to the object and all its child objects. It maps the content into span elements with the objects' names as data-name attributes.
{'ns:paragraph': 'p', 'bold': 'b', '*': 'span'} This mapping object matches all paragraph objects in the namespace prefixed with ns and unqualified bold objects. All other, unmapped, objects are matched by the asterisk. All string values describe simple XML element names to wrap the objects' contents into (see the usage example).
{'ns:paragraph': 'p', 'bold': ({content}) => content} This mapping object is similar to the preceding one with the difference that the mapping for the bold key is described by a function that only returns the content for each object without wrapping it into something. The other difference is that the asterisk-default mapping is missing. This way, all objects not matched by paragraph and bold will be ignored.
options

An optional object that describes the options for the serialization:

Property Description Examples
namespaces An object array describing namespaces used in the mapping with their namespace URI and prefix, both as string values. Namespaces that appear as default values in the target JML object still need to be declared with a prefix in the options object. [{prefix: 'ns', uri: 'http://example.com/ns'}]
[{uri: 'http://example.com/default'}, {prefix: 'ns', 'uri: 'http://example.org/ns'}]
skipEmpty A boolean that sets whether or not to skip empty objects during the serialization. Defaults to false. true

Usage example

import {serialize} from 'jml-tools';
// original XML:
// <paragraph xmlns="http://example.com/ns">JSON is just as <emphasized>fun</emphasized> as XML.</paragraph>
const jmlObject = {
    elements: [{
        type: 'element',
        name: 'paragraph',
        attributes: {
            xmlns: 'http://example.com/ns'
        },
        elements: [
            {type: 'text', text: 'JSON is just as '},
            {
                type: 'element',
                name: 'emphasized',
                elements: [
                    {type: 'text', text: 'fun'}
                ]
            },
            {type: 'text', text: ' as XML.'}
        ]
    }]
};
const mappings = {
    'ns:paragraph': 'p',
    'ns:emphasized': 'i'
};
const options = {
    namespaces: [{
        prefix: 'ns',
        uri: 'http://example.com/ns'
    }]
};
const serialized = serialize(jmlObject, mappings, options);
console.log(serialized);
 
// Output:
// <p>JSON is just as <i>fun</i> as XML.</p>

Authors

  • Daniel Jeller

License

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgments

Thanks to @nashwaan for his excellent xml-js library.

Readme

Keywords

none

Package Sidebar

Install

npm i jml-tools

Weekly Downloads

2

Version

0.1.3

License

MIT

Last publish

Collaborators

  • yngwi