{"id":27261548,"url":"https://github.com/yngwi/jml-tools","last_synced_at":"2025-04-11T05:34:57.630Z","repository":{"id":57281180,"uuid":"103024880","full_name":"yngwi/jml-tools","owner":"yngwi","description":"A set of tools to simplify the usage of XML-based JSON markup (JML) in JavaScript","archived":false,"fork":false,"pushed_at":"2017-09-27T16:23:45.000Z","size":132,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-01T15:04:58.605Z","etag":null,"topics":["javascript","json-ml","markup","xml-js"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yngwi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-09-10T11:42:45.000Z","updated_at":"2017-09-13T17:27:02.000Z","dependencies_parsed_at":"2022-09-20T06:51:15.140Z","dependency_job_id":null,"html_url":"https://github.com/yngwi/jml-tools","commit_stats":null,"previous_names":["yngwi/json-ml-tools"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yngwi%2Fjml-tools","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yngwi%2Fjml-tools/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yngwi%2Fjml-tools/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yngwi%2Fjml-tools/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yngwi","download_url":"https://codeload.github.com/yngwi/jml-tools/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247276159,"owners_count":20912288,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["javascript","json-ml","markup","xml-js"],"created_at":"2025-04-11T05:34:52.926Z","updated_at":"2025-04-11T05:34:57.617Z","avatar_url":"https://github.com/yngwi.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# JML Tools\n\n[![npm version](https://badge.fury.io/js/jml-tools.svg)](https://badge.fury.io/js/jml-tools) [![Build Status](https://travis-ci.org/yngwi/jml-tools.svg?branch=master)](https://travis-ci.org/yngwi/jml-tools)\n\nThis 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](https://github.com/nashwaan/xml-js). It can be converted lossless to and from XML documents including _mixed-content elements_. The tools are fully _namespace aware_.\n\n## Usage\n\n### Installation\n\n`npm install jml-tools --save`\n\nor\n\n`yarn add jml-tools`\n\n### Quick start\n\n```js\nimport {create} from 'jml-tools';\nconst name = 'person';\nconst data = {content: 'Freddie Mercury'};\nconst jmlObject = create(name, data);\nconsole.log(jmlObject);\n\n// Output:\n// {\n//     \"elements\": [\n//         {\n//             \"elements\": [\n//                 {\n//                     \"text\": \"Freddie Mercury\",\n//                     \"type\": \"text\"\n//                 }\n//             ],\n//             \"name\": \"person\",\n//             \"type\": \"element\"\n//         }\n//     ]\n// }\n```\n\n### Running tests\n\n`npm test`\n\n## API Reference\n\nThis library provides the following functionalities:\n\n### \u003ca name=\"create\"\u003e\u003c/a\u003ecreate\n\nManually creates a JML object that is fully compatible with [xml-js](https://github.com/nashwaan/xml-js).\n\n#### Syntax\n\n```\ncreate(name[, data])\n```\n\n#### Parameters\n\n##### name\n\nA _string_, either prefixed or not that will be the name of the object to be created.\n\n##### data\n\nAn optional data object that can have any or all of the following properties:\n\n| Property | Description    | Examples           |\n|----------|----------------|-------------------|\n| 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'}]`\u003cbr/\u003e`[{uri: 'http://example.com/default'}, {prefix: 'ns', 'uri: 'http://example.org/ns'}]` |\n| 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'` |\n| 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'}` |\n\n#### Usage example\n\n```js\nimport {create} from 'jml-tools';\nconst name = 'person';\nconst data = {content: 'Freddie Mercury'};\nconst jmlObject = create(name, data);\nconsole.log(jmlObject);\n\n// Output:\n// {\n//     \"elements\": [\n//         {\n//             \"elements\": [\n//                 {\n//                     \"text\": \"Freddie Mercury\",\n//                     \"type\": \"text\"\n//                 }\n//             ],\n//             \"name\": \"person\",\n//             \"type\": \"element\"\n//         }\n//     ]\n// }\n```\n\n### evaluate\n\nEvaluates 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.\n\n#### Syntax\n\n```\nevaluate(path, jmlObject[, options])\n```\n\n#### Parameters\n\n##### path\n\nA _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.\n\n###### Examples\n\n| Path | Result |\n|------|-------------|\n| `/first/second` | All `second` objects that are direct children of a `first` object |\n| `//second/text()` | The direct text content of all `second` objects |\n| `//second//text()` | The text content of all `second` objects and their descendants |\n| `/first/@value` | The text content of the `value` attribute of all `first` objects |\n| `/first[@value=\"1\"]` | All `first` objects that have a `value` attribute with the value `1`. The value can be a _string_ or a _number_ |\n| `/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 |\n| `/first[2]/second` | All `second` objects that are a child of the second `first` object |\n| `/ns:first` | All `first` objects that are in the `ns` namespace. The `ns` namespace needs to be declared in the methods' [options](#evaluate_options) object |\n\n###### Notable differences to XPath\n\n* The value of an attribute can be accessed directly by `/something/@attribute` instead of `data(/something/@attribute)` or `/something/@attribute/string()`\n* When evaluating on an object that is equivalent to `\u003cpersons\u003e\u003cperson\u003e\u003cname\u003e\u003cgiven\u003eFreddy\u003c/given\u003e\u003c/name\u003e\u003c/person\u003e\u003cperson\u003e\u003cname\u003e\u003cgiven\u003eBrian\u003c/given\u003e\u003c/name\u003e\u003c/person\u003e\u003c/persons\u003e`, `//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]`.\n\n##### jmlObject\n\nA valid JML _object_ as created by the [create](#create) method and [xml-js](https://github.com/nashwaan/xml-js). The path will be evaluated on its contents starting inside the root object.\n\n##### \u003ca name=\"evaluate_options\"\u003e\u003c/a\u003eoptions\n\nAn optional object that describes the options for the evaluation:\n\n| Property | Description    | Examples           |\n|----------|----------------|-------------------|\n| 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'}]` |\n\n#### Usage example\n\n```js\nimport {evaluate} from 'jml-tools';\n// original XML:\n// \u003cparagraph xmlns=\"http://example.com/ns\"\u003eJSON is just as \u003cemphasized\u003efun\u003c/emphasized\u003e as XML.\u003c/paragraph\u003e\nconst jmlObject = {\n    elements: [{\n        type: 'element',\n        name: 'paragraph',\n        attributes: {\n            xmlns: 'http://example.com/ns'\n        },\n        elements: [\n            {type: 'text', text: 'JSON is just as '},\n            {\n                type: 'element',\n                name: 'emphasized',\n                elements: [\n                    {type: 'text', text: 'fun'}\n                ]\n            },\n            {type: 'text', text: ' as XML.'}\n        ]\n    }]\n};\nconst result = evaluate('/ns:emphasized/text()', jmlObject, {namespaces: [{prefix: 'ns', uri: 'http://example.com/ns'}]});\nconsole.log(result);\n\n// Output:\n// ['fun']\n```\n\n### serialize\n\nSerializes 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.\n\n#### Syntax\n\n```\nserialize(jmlObject, mappings[, options])\n```\n\n#### Parameters\n\n##### jmlObject\n\nA valid JML _object_ as created by the [create](#create) method and [xml-js](https://github.com/nashwaan/xml-js). It will be serialized according to the provided mappings.\n\n##### mappings\n\nThe rules to apply to the _jmlObject_. It describes how its contents will be serialized. It can any of the following:\n\n1. 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.\n2. 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})`.\n3. 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})`.\n\n_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._\n\n_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](#serialize_options) object and the correct prefixes need to be added to the keys to match the specific objects._\n\n| Example | Description |\n|---------|-------------|\n| ``({content, name}) =\u003e `\u003cspan data-name=\"${name}\"\u003e${content}\u003c/span\u003e`)`` | 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.|\n|`{'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](#serialize_usage_example)).  |\n|`{'ns:paragraph': 'p', 'bold': ({content}) =\u003e 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.|\n\n##### \u003ca name=\"serialize_options\"\u003e\u003c/a\u003eoptions\n\nAn optional object that describes the options for the serialization:\n\n| Property | Description    | Examples           |\n|----------|----------------|-------------------|\n| 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'}]`\u003cbr/\u003e`[{uri: 'http://example.com/default'}, {prefix: 'ns', 'uri: 'http://example.org/ns'}]` |\n| skipEmpty | A _boolean_ that sets whether or not to skip empty objects during the serialization. Defaults to _false_. | `true` |\n\n#### \u003ca name=\"serialize_usage_example\"\u003e\u003c/a\u003eUsage example\n\n```js\nimport {serialize} from 'jml-tools';\n// original XML:\n// \u003cparagraph xmlns=\"http://example.com/ns\"\u003eJSON is just as \u003cemphasized\u003efun\u003c/emphasized\u003e as XML.\u003c/paragraph\u003e\nconst jmlObject = {\n    elements: [{\n        type: 'element',\n        name: 'paragraph',\n        attributes: {\n            xmlns: 'http://example.com/ns'\n        },\n        elements: [\n            {type: 'text', text: 'JSON is just as '},\n            {\n                type: 'element',\n                name: 'emphasized',\n                elements: [\n                    {type: 'text', text: 'fun'}\n                ]\n            },\n            {type: 'text', text: ' as XML.'}\n        ]\n    }]\n};\nconst mappings = {\n    'ns:paragraph': 'p',\n    'ns:emphasized': 'i'\n};\nconst options = {\n    namespaces: [{\n        prefix: 'ns',\n        uri: 'http://example.com/ns'\n    }]\n};\nconst serialized = serialize(jmlObject, mappings, options);\nconsole.log(serialized);\n\n// Output:\n// \u003cp\u003eJSON is just as \u003ci\u003efun\u003c/i\u003e as XML.\u003c/p\u003e\n```\n\n## Authors\n\n* **Daniel Jeller**\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\n## Acknowledgments\n\nThanks to [@nashwaan](https://github.com/nashwaan) for his excellent xml-js library.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyngwi%2Fjml-tools","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyngwi%2Fjml-tools","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyngwi%2Fjml-tools/lists"}