Fix App.jsx two-page workflow JSX render and update study app layout
This commit is contained in:
commit
f47a41ce6f
4459 files changed
+1059845
No files matched your search
+21
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016-2017 Yousuf Almarzooqi
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
+390
@@ -0,0 +1,390 @@
|
||||

|
||||
|
||||
Convert XML text to Javascript object / JSON text (and vice versa).
|
||||
|
||||
[](https://ci.appveyor.com/project/nashwaan/xml-js)
|
||||
[](https://travis-ci.org/nashwaan/xml-js)
|
||||
[](https://circleci.com/gh/nashwaan/xml-js)
|
||||
<!-- [](https://gitlab.com/nashwaan/xml-js/commits/master) -->
|
||||
|
||||
[](https://coveralls.io/github/nashwaan/xml-js?branch=master)
|
||||
[](https://codecov.io/gh/nashwaan/xml-js)
|
||||
[](https://www.codacy.com/app/ysf953/xml-js?utm_source=github.com&utm_medium=referral&utm_content=nashwaan/xml-js&utm_campaign=Badge_Grade)
|
||||
[](https://codeclimate.com/github/nashwaan/xml-js)
|
||||
|
||||
[](https://www.npmjs.com/package/xml-js)
|
||||
[](LICENSE)
|
||||
[](http://www.npmtrends.com/xml-js)
|
||||
[](https://david-dm.org/nashwaan/xml-js)
|
||||
[](http://packagequality.com/#?package=xml-js)
|
||||
|
||||
# Synopsis
|
||||
|
||||

|
||||
<!----->
|
||||
|
||||
# Features
|
||||
|
||||
* **Maintain Order of Elements**:
|
||||
Most libraries will convert `<a/><b/><a/>` to `{a:[{},{}],b:{}}` which merges any node of same name into an array. This library can create the following to preserve the order of elements:
|
||||
`{"elements":[{"type":"element","name":"a"},{"type":"element","name":"b"},{"type":"element","name":"a"}]}`.
|
||||
|
||||
This is very important and it is the main reason why this library was created. Read also [Compact vs Non-Compact](#compact-vs-non-compact) for more info.
|
||||
|
||||
* **Fully XML Compliant**:
|
||||
Can parse: elements, attributes, texts, comments, CData, DOCTYPE, XML declarations, and Processing Instructions.
|
||||
|
||||
* **Reversible**:
|
||||
Whether converting xml→json or json→xml, the result can be converted back to its original form.
|
||||
|
||||
* **Minimal Dependencies**:
|
||||
This library depends only on one external npm module.
|
||||
|
||||
* **Change Property Key Name**:
|
||||
Usually output of XML attributes are stored in `@attr`, `_atrr`, `$attr` or `$` in order to avoid conflicting with name of sub-elements.
|
||||
This library store them in `attributes`, but most importantly, you can change this to whatever you like.
|
||||
|
||||
* **Support Upwards Traversal**:
|
||||
By setting `{addParent: true}` option, an extra property named `parent` will be generated along each element so that its parent can be referenced.
|
||||
Therefore, anywhere during the traversal of an element, its children **and** its parent can be easily accessed.
|
||||
|
||||
* **Support Command Line**:
|
||||
To quickly convert xml or json files, this module can be installed globally or locally (i.e. use it as [script](https://docs.npmjs.com/misc/scripts) in package.json).
|
||||
|
||||
* **Customize Processing using Callback Hooks**:
|
||||
[Custom functions](#options-for-custom-processing-functions) can be supplied to do additional processing for different parts of xml or json (like cdata, comments, elements, attributes ...etc).
|
||||
|
||||
* **Portable Code**:
|
||||
Written purely in JavaScript which means it can be used in Node environment and **browser** environment (via bundlers like browserify/JSPM/Webpack).
|
||||
|
||||
* **Typings Info Included**:
|
||||
Support type checking and code suggestion via intellisense.
|
||||
Thanks to the wonderful efforts by [DenisCarriere](https://github.com/DenisCarriere).
|
||||
|
||||
## Compact vs Non-Compact
|
||||
|
||||
Most XML to JSON converters (including online converters) convert `<a/>` to some compact output like `{"a":{}}`
|
||||
instead of non-compact output like `{"elements":[{"type":"element","name":"a"}]}`.
|
||||
|
||||
While compact output might work in most situations, there are cases when elements of different names are mixed inside a parent element. Lets use `<a x="1"/><b x="2"/><a x="3"/>` as an example.
|
||||
Most converters will produce compact output like this `{a:[{_:{x:"1"}},{_:{x:"3"}}], b:{_:{x:"2"}}}`,
|
||||
which has merged both `<a>` elements into an array. If you try to convert this back to xml, you will get `<a x="1"/><a x="3"/><b x="2"/>`
|
||||
which has not preserved the order of elements!
|
||||
|
||||
The reason behind this behavior is due to the inherent limitation in the compact representation.
|
||||
Because output like `{a:{_:{x:"1"}}, b:{_:{x:"2"}}, a:{_:{x:"3"}}}` is illegal (same property name `a` should not appear twice in an object). This leaves no option but to use array `{a:[{_:{x:"1"}},{_:{x:"3"}}]`.
|
||||
|
||||
The non-compact output, which is supported by this library, will produce more information and always guarantees the order of the elements as they appeared in the XML file.
|
||||
|
||||
Another drawback of compact output is the resultant element can be an object or an array and therefore makes the client code a little awkward in terms of the extra check needed on object type before processing.
|
||||
|
||||
NOTE: Although non-compact output is more accurate representation of original XML than compact version, the non-compact version is verbose and consumes more space.
|
||||
This library provides both options. Use `{compact: false}` if you are not sure because it preserves everything;
|
||||
otherwise use `{compact: true}` if you want to save space and you don't care about mixing elements of same name and losing their order.
|
||||
|
||||
Tip: You can reduce the output size by using shorter [key names](#options-for-changing-key-names).
|
||||
|
||||
# Usage
|
||||
|
||||
## Installation
|
||||
|
||||
```
|
||||
npm install --save xml-js
|
||||
```
|
||||
|
||||
You can also install it globally to use it as a command line convertor (see [Command Line](#command-line)).
|
||||
|
||||
```
|
||||
npm install --global xml-js
|
||||
```
|
||||
|
||||
## Quick start
|
||||
|
||||
```js
|
||||
var convert = require('xml-js');
|
||||
var xml =
|
||||
'<?xml version="1.0" encoding="utf-8"?>' +
|
||||
'<note importance="high" logged="true">' +
|
||||
' <title>Happy</title>' +
|
||||
' <todo>Work</todo>' +
|
||||
' <todo>Play</todo>' +
|
||||
'</note>';
|
||||
var result1 = convert.xml2json(xml, {compact: true, spaces: 4});
|
||||
var result2 = convert.xml2json(xml, {compact: false, spaces: 4});
|
||||
console.log(result1, '\n', result2);
|
||||
```
|
||||
|
||||
To see the result of this code, see the output above in [Synopsis](#synopsis) section.
|
||||
|
||||
Or [run and edit](https://runkit.com/587874e079a2f60013c1f5ac/587874e079a2f60013c1f5ad) this code live in the browser.
|
||||
|
||||
## Sample Conversions
|
||||
|
||||
| XML | JS/JSON compact | JS/JSON non-compact |
|
||||
|:----|:----------------|:--------------------|
|
||||
| `<a/>` | `{"a":{}}` | `{"elements":[{"type":"element","name":"a"}]}` |
|
||||
| `<a/><b/>` | `{"a":{},"b":{}}` | `{"elements":[{"type":"element","name":"a"},{"type":"element","name":"b"}]}` |
|
||||
| `<a><b/></a>` | `{"a":{"b":{}}}` | `{"elements":[{"type":"element","name":"a","elements":[{"type":"element","name":"b"}]}]}` |
|
||||
| `<a> Hi </a>` | `{"a":{"_text":" Hi "}}` | `{"elements":[{"type":"element","name":"a","elements":[{"type":"text","text":" Hi "}]}]}` |
|
||||
| `<a x="1.234" y="It's"/>` | `{"a":{"_attributes":{"x":"1.234","y":"It's"}}}` | `{"elements":[{"type":"element","name":"a","attributes":{"x":"1.234","y":"It's"}}]}` |
|
||||
| `<?xml?>` | `{"_declaration":{}}` | `{"declaration":{}}` |
|
||||
| `<?go there?>` | `{"_instruction":{"go":"there"}}` | `{"elements":[{"type":"instruction","name":"go","instruction":"there"}]}` |
|
||||
| `<?xml version="1.0" encoding="utf-8"?>` | `{"_declaration":{"_attributes":{"version":"1.0","encoding":"utf-8"}}}` | `{"declaration":{"attributes":{"version":"1.0","encoding":"utf-8"}}}` |
|
||||
| `<!--Hello, World!-->` | `{"_comment":"Hello, World!"}` | `{"elements":[{"type":"comment","comment":"Hello, World!"}]}` |
|
||||
| `<![CDATA[<foo></bar>]]>` | `{"_cdata":"<foo></bar>"}` | `{"elements":[{"type":"cdata","cdata":"<foo></bar>"}]}` |
|
||||
|
||||
# API Reference
|
||||
|
||||
This library provides 4 functions: `js2xml()`, `json2xml()`, `xml2js()`, and `xml2json()`. Here are the usages for each one (see more details in the following sections):
|
||||
```js
|
||||
var convert = require('xml-js');
|
||||
result = convert.js2xml(js, options); // to convert javascript object to xml text
|
||||
result = convert.json2xml(json, options); // to convert json text to xml text
|
||||
result = convert.xml2js(xml, options); // to convert xml text to javascript object
|
||||
result = convert.xml2json(xml, options); // to convert xml text to json text
|
||||
```
|
||||
|
||||
## Convert JS object / JSON → XML
|
||||
|
||||
To convert JavaScript object to XML text, use `js2xml()`. To convert JSON text to XML text, use `json2xml()`.
|
||||
|
||||
```js
|
||||
var convert = require('xml-js');
|
||||
var json = require('fs').readFileSync('test.json', 'utf8');
|
||||
var options = {compact: true, ignoreComment: true, spaces: 4};
|
||||
var result = convert.json2xml(json, options);
|
||||
console.log(result);
|
||||
```
|
||||
|
||||
### Options for Converting JS object / JSON → XML
|
||||
|
||||
The below options are applicable for both `js2xml()` and `json2xml()` functions.
|
||||
|
||||
|
||||
| Option | Default | Description |
|
||||
|:----------------------|:--------|:------------|
|
||||
| `spaces` | `0` | Number of spaces to be used for indenting XML output. Passing characters like `' '` or `'\t'` are also accepted. |
|
||||
| `compact` | `false` | Whether the *input* object is in compact form or not. By default, input is expected to be in non-compact form. |
|
||||
| | | IMPORTANT: Remeber to set this option `compact: true` if you are supplying normal json (which is likely equivalent to compact form). Otherwise, the function assumes your json input is non-compact form and you will not get a result if it is not in that form. See [Synopsis](#synopsis) to know the difference between the two json forms |
|
||||
| `fullTagEmptyElement` | `false` | Whether to produce element without sub-elements as full tag pairs `<a></a>` rather than self closing tag `<a/>`. |
|
||||
| `indentCdata` | `false` | Whether to write CData in a new line and indent it. Will generate `<a>\n <![CDATA[foo]]></a>` instead of `<a><![CDATA[foo]]></a>`. See [discussion](https://github.com/nashwaan/xml-js/issues/14) |
|
||||
| `indentAttributes` | `false` | Whether to print attributes across multiple lines and indent them (when `spaces` is not `0`). See [example](https://github.com/nashwaan/xml-js/issues/31). |
|
||||
| `ignoreDeclaration` | `false` | Whether to ignore writing declaration directives of xml. For example, `<?xml?>` will be ignored. |
|
||||
| `ignoreInstruction` | `false` | Whether to ignore writing processing instruction of xml. For example, `<?go there?>` will be ignored. |
|
||||
| `ignoreAttributes` | `false` | Whether to ignore writing attributes of the elements. For example, `x="1"` in `<a x="1"></a>` will be ignored |
|
||||
| `ignoreComment` | `false` | Whether to ignore writing comments of the elements. That is, no `<!-- -->` will be generated. |
|
||||
| `ignoreCdata` | `false` | Whether to ignore writing CData of the elements. That is, no `<![CDATA[ ]]>` will be generated. |
|
||||
| `ignoreDoctype` | `false` | Whether to ignore writing Doctype of the elements. That is, no `<!DOCTYPE >` will be generated. |
|
||||
| `ignoreText` | `false` | Whether to ignore writing texts of the elements. For example, `hi` text in `<a>hi</a>` will be ignored. |
|
||||
|
||||
## Convert XML → JS object / JSON
|
||||
|
||||
To convert XML text to JavaScript object, use `xml2js()`. To convert XML text to JSON text, use `xml2json()`.
|
||||
|
||||
```js
|
||||
var convert = require('xml-js');
|
||||
var xml = require('fs').readFileSync('test.xml', 'utf8');
|
||||
var options = {ignoreComment: true, alwaysChildren: true};
|
||||
var result = convert.xml2js(xml, options); // or convert.xml2json(xml, options)
|
||||
console.log(result);
|
||||
```
|
||||
|
||||
### Options for Converting XML → JS object / JSON
|
||||
|
||||
The below options are applicable for both `xml2js()` and `xml2json()` functions.
|
||||
|
||||
| Option | Default | Description |
|
||||
|:--------------------|:--------|:------------|
|
||||
| `compact` | `false` | Whether to produce detailed object or compact object. |
|
||||
| `trim` | `false` | Whether to trim whitespace characters that may exist before and after the text. |
|
||||
| `sanitize` ([Deprecated](https://github.com/nashwaan/xml-js/issues/26)) | `false` | Whether to replace `&` `<` `>` with `&` `<` `>` respectively, in the resultant text. |
|
||||
| `nativeType` | `false` | Whether to attempt converting text of numerals or of boolean values to native type. For example, `"123"` will be `123` and `"true"` will be `true` |
|
||||
| `nativeTypeAttributes` | `false` | Whether to attempt converting attributes of numerals or of boolean values to native type. See also `nativeType` above. |
|
||||
| `addParent` | `false` | Whether to add `parent` property in each element object that points to parent object. |
|
||||
| `alwaysArray` | `false` | Whether to always put sub element, even if it is one only, as an item inside an array. `<a><b/></a>` will be `a:[{b:[{}]}]` rather than `a:{b:{}}` (applicable for compact output only). If the passed value is an array, only elements with names in the passed array are always made arrays. |
|
||||
| `alwaysChildren` | `false` | Whether to always generate `elements` property even when there are no actual sub elements. `<a></a>` will be `{"elements":[{"type":"element","name":"a","elements":[]}]}` rather than `{"elements":[{"type":"element","name":"a"}]}` (applicable for non-compact output). |
|
||||
| `instructionHasAttributes` | `false` | Whether to parse contents of Processing Instruction as attributes or not. `<?go to="there"?>` will be `{"_instruction":{"go":{"_attributes":{"to":"there"}}}}` rather than `{"_instruction":{"go":"to=\"there\""}}`. See [discussion](https://github.com/nashwaan/xml-js/issues/17). |
|
||||
| `ignoreDeclaration` | `false` | Whether to ignore parsing declaration property. That is, no `declaration` property will be generated. |
|
||||
| `ignoreInstruction` | `false` | Whether to ignore parsing processing instruction property. That is, no `instruction` property will be generated. |
|
||||
| `ignoreAttributes` | `false` | Whether to ignore parsing attributes of elements.That is, no `attributes` property will be generated. |
|
||||
| `ignoreComment` | `false` | Whether to ignore parsing comments of the elements. That is, no `comment` will be generated. |
|
||||
| `ignoreCdata` | `false` | Whether to ignore parsing CData of the elements. That is, no `cdata` will be generated. |
|
||||
| `ignoreDoctype` | `false` | Whether to ignore parsing Doctype of the elements. That is, no `doctype` will be generated. |
|
||||
| `ignoreText` | `false` | Whether to ignore parsing texts of the elements. That is, no `text` will be generated. |
|
||||
|
||||
The below option is applicable only for `xml2json()` function.
|
||||
|
||||
| Option | Default | Description |
|
||||
|:--------------------|:--------|:------------|
|
||||
| `spaces` | `0` | Number of spaces to be used for indenting JSON output. Passing characters like `' '` or `'\t'` are also accepted. |
|
||||
|
||||
## Options for Changing Key Names
|
||||
|
||||
To change default key names in the output object or the default key names assumed in the input JavaScript object / JSON, use the following options:
|
||||
|
||||
| Option | Default | Description |
|
||||
|:--------------------|:--------|:------------|
|
||||
| `declarationKey` | `"declaration"` or `"_declaration"` | Name of the property key which will be used for the declaration. For example, if `declarationKey: '$declaration'` then output of `<?xml?>` will be `{"$declaration":{}}` *(in compact form)* |
|
||||
| `instructionKey` | `"instruction"` or `"_instruction"` | Name of the property key which will be used for the processing instruction. For example, if `instructionKey: '$instruction'` then output of `<?go there?>` will be `{"$instruction":{"go":"there"}}` *(in compact form)* |
|
||||
| `attributesKey` | `"attributes"` or `"_attributes"` | Name of the property key which will be used for the attributes. For example, if `attributesKey: '$attributes'` then output of `<a x="hello"/>` will be `{"a":{$attributes:{"x":"hello"}}}` *(in compact form)* |
|
||||
| `textKey` | `"text"` or `"_text"` | Name of the property key which will be used for the text. For example, if `textKey: '$text'` then output of `<a>hi</a>` will be `{"a":{"$text":"Hi"}}` *(in compact form)* |
|
||||
| `cdataKey` | `"cdata"` or `"_cdata"` | Name of the property key which will be used for the cdata. For example, if `cdataKey: '$cdata'` then output of `<![CDATA[1 is < 2]]>` will be `{"$cdata":"1 is < 2"}` *(in compact form)* |
|
||||
| `doctypeKey` | `"doctype"` or `"_doctype"` | Name of the property key which will be used for the doctype. For example, if `doctypeKey: '$doctype'` then output of `<!DOCTYPE foo>` will be `{"$doctype":" foo}` *(in compact form)* |
|
||||
| `commentKey` | `"comment"` or `"_comment"` | Name of the property key which will be used for the comment. For example, if `commentKey: '$comment'` then output of `<!--note-->` will be `{"$comment":"note"}` *(in compact form)* |
|
||||
| `parentKey` | `"parent"` or `"_parent"` | Name of the property key which will be used for the parent. For example, if `parentKey: '$parent'` then output of `<a></b></a>` will be `{"a":{"b":{$parent:_points_to_a}}}` *(in compact form)* |
|
||||
| `typeKey` | `"type"` | Name of the property key which will be used for the type. For example, if `typeKey: '$type'` then output of `<a></a>` will be `{"elements":[{"$type":"element","name":"a"}]}` *(in non-compact form)* |
|
||||
| `nameKey` | `"name"` | Name of the property key which will be used for the name. For example, if `nameKey: '$name'` then output of `<a></a>` will be `{"elements":[{"type":"element","$name":"a"}]}` *(in non-compact form)* |
|
||||
| `elementsKey` | `"elements"` | Name of the property key which will be used for the elements. For example, if `elementsKey: '$elements'` then output of `<a></a>` will be `{"$elements":[{"type":"element","name":"a"}]}` *(in non-compact form)* |
|
||||
|
||||
Two default values mean the first is used for *non-compact* output and the second is for *compact* output.
|
||||
|
||||
> **TIP**: In compact mode, you can further reduce output result by using fewer characters for key names `{textKey: '_', attributesKey: '$', commentKey: 'value'}`. This is also applicable to non-compact mode.
|
||||
|
||||
> **TIP**: In non-compact mode, you probably want to set `{textKey: 'value', cdataKey: 'value', commentKey: 'value'}`
|
||||
> to make it more consistent and easier for your client code to go through the contents of text, cdata, and comment.
|
||||
|
||||
## Options for Custom Processing Functions
|
||||
|
||||
For XML → JS object / JSON, following custom callback functions can be supplied:
|
||||
|
||||
```js
|
||||
var convert = require('xml-js');
|
||||
var xml = '<foo:Name>Ali</Name> <bar:Age>30</bar:Age>';
|
||||
var options = {compact: true, elementNameFn: function(val) {return val.replace('foo:','').toUpperCase();}};
|
||||
var result = convert.xml2json(xml, options);
|
||||
console.log(result); // {"NAME":{"_text":"Ali"},"BAR:AGE":{"_text":"30"}}
|
||||
```
|
||||
|
||||
| Option | Signature | Description |
|
||||
|:--------------------|:----------|:------------|
|
||||
| `doctypeFn` | `(value, parentElement)` | To perform additional processing for DOCTYPE. For example, `{doctypeFn: function(val) {return val.toUpperCase();}}` |
|
||||
| `instructionFn` | `(instructionValue, instructionName, parentElement)` | To perform additional processing for content of Processing Instruction value. For example, `{instructionFn: function(val) {return val.toUpperCase();}}`. Note: `instructionValue` will be an object if `instructionHasAttributes` is enabled. |
|
||||
| `cdataFn` | `(value, parentElement)` | To perform additional processing for CData. For example, `{cdataFn: function(val) {return val.toUpperCase();}}`. |
|
||||
| `commentFn` | `(value, parentElement)` | To perform additional processing for comments. For example, `{commentFn: function(val) {return val.toUpperCase();}}`. |
|
||||
| `textFn` | `(value, parentElement)` | To perform additional processing for texts inside elements. For example, `{textFn: function(val) {return val.toUpperCase();}}`. |
|
||||
| `instructionNameFn` | `(instructionName, instructionValue, parentElement)` | To perform additional processing for Processing Instruction name. For example, `{instructionNameFn: function(val) {return val.toUpperCase();}}`. Note: `instructionValue` will be an object if `instructionHasAttributes` is enabled. |
|
||||
| `elementNameFn` | `(value, parentElement)` | To perform additional processing for element name. For example, `{elementNameFn: function(val) {return val.toUpperCase();}}`. |
|
||||
| `attributeNameFn` | `(attributeName, attributeValue, parentElement)` | To perform additional processing for attribute name. For example, `{attributeNameFn: function(val) {return val.toUpperCase();}}`. |
|
||||
| `attributeValueFn` | `(attributeValue, attributeName, parentElement)` | To perform additional processing for attributeValue. For example, `{attributeValueFn: function(val) {return val.toUpperCase();}}`. |
|
||||
| `attributesFn` | `(value, parentElement)` | To perform additional processing for attributes object. For example, `{attributesFn: function(val) {return val.toUpperCase();}}`. |
|
||||
|
||||
For JS object / JSON → XML, following custom callback functions can be supplied:
|
||||
|
||||
```js
|
||||
var convert = require('xml-js');
|
||||
var json = '{"name":{"_text":"Ali"},"age":{"_text":"30"}}';
|
||||
var options = {compact: true, textFn: function(val, elementName) {return elementName === 'age'? val + '';}};
|
||||
var result = convert.json2xml(json, options);
|
||||
console.log(result); // <foo:Name>Ali</Name> <bar:Age>30</bar:Age>
|
||||
```
|
||||
|
||||
| Option | Signature | Description |
|
||||
|:--------------------|:----------|:------------|
|
||||
| `doctypeFn` | `(value, currentElementName, currentElementObj)` | To perform additional processing for DOCTYPE. For example, `{doctypeFn: function(val) {return val.toUpperCase();}`. |
|
||||
| `instructionFn` | `(instructionValue, instructionName, currentElementName, currentElementObj)` | To perform additional processing for content of Processing Instruction value. For example, `{instructionFn: function(val) {return val.toUpperCase();}}`. Note: `instructionValue` will be an object if `instructionHasAttributes` is enabled. |
|
||||
| `cdataFn` | `(value, currentElementName, currentElementObj)` | To perform additional processing for CData. For example, `{cdataFn: function(val) {return val.toUpperCase();}}`. |
|
||||
| `commentFn` | `(value, currentElementName, currentElementObj)` | To perform additional processing for comments. For example, `{commentFn: function(val) {return val.toUpperCase();}}`. |
|
||||
| `textFn` | `(value, currentElementName, currentElementObj)` | To perform additional processing for texts inside elements. For example, `{textFn: function(val) {return val.toUpperCase();}}`. |
|
||||
| `instructionNameFn` | `(instructionName, instructionValue, currentElementName, currentElementObj)` | To perform additional processing for Processing Instruction name. For example, `{instructionNameFn: function(val) {return val.toUpperCase();}}`. Note: `instructionValue` will be an object if `instructionHasAttributes` is enabled. |
|
||||
| `elementNameFn` | `(value, currentElementName, currentElementObj)` | To perform additional processing for element name. For example, `{elementNameFn: function(val) {return val.toUpperCase();}}`. |
|
||||
| `attributeNameFn` | `(attributeName, attributeValue, currentElementName, currentElementObj)` | To perform additional processing for attribute name. For example, `{attributeNameFn: function(val) {return val.toUpperCase();}}`. |
|
||||
| `attributeValueFn` | `(attributeValue, attributeName, currentElementName, currentElementObj)` | To perform additional processing for attributeValue. For example, `{attributeValueFn: function(val) {return val.toUpperCase();}}`. |
|
||||
| `attributesFn` | `(value, currentElementName, currentElementObj)` | To perform additional processing for attributes object. For example, `{attributesFn: function(val) {return val.toUpperCase();}}`. |
|
||||
| `fullTagEmptyElementFn` | `(currentElementName, currentElementObj)` | Whether to generate full tag or just self closing tag for elements that has no sub elements. For example, `{fullTagEmptyElementFn: function(val) {return val === 'foo'}}`. |
|
||||
|
||||
# Command Line
|
||||
|
||||
Because any good library should support command line usage, this library is no different.
|
||||
|
||||
## As Globally Accessible Command
|
||||
|
||||
```
|
||||
npm install -g xml-js // install this library globally
|
||||
xml-js test.json --spaces 4 // xml result will be printed on screen
|
||||
xml-js test.json --spaces 4 --out test.xml // xml result will be saved to test.xml
|
||||
xml-js test.xml --spaces 4 // json result will be printed on screen
|
||||
xml-js test.xml --spaces 4 --out test.json // json result will be saved to test.json
|
||||
```
|
||||
|
||||
## As Locally Accessible Command
|
||||
|
||||
If you want to use it as script in package.json (can also be helpful in [task automation via npm scripts](http://blog.keithcirkel.co.uk/how-to-use-npm-as-a-build-tool/))
|
||||
|
||||
```
|
||||
npm install --save xml-js // no need to install this library globally
|
||||
```
|
||||
|
||||
In package.json, write a script:
|
||||
```json
|
||||
...
|
||||
"dependencies": {
|
||||
"xml-js": "latest"
|
||||
},
|
||||
"scripts": {
|
||||
"convert": "xml-js test.json --spaces 4"
|
||||
}
|
||||
```
|
||||
|
||||
Now in the command line, you can run this script by typing:
|
||||
```
|
||||
npm run convert // task 'scripts.convert' will be executed
|
||||
```
|
||||
|
||||
## CLI Arguments
|
||||
|
||||
```
|
||||
Usage: xml-js src [options]
|
||||
|
||||
src Input file that need to be converted.
|
||||
Conversion type xml->json or json->xml will be inferred from file extension.
|
||||
|
||||
Options:
|
||||
--help, -h Display this help content.
|
||||
--version, -v Display version number of this module.
|
||||
--out Output file where result should be written.
|
||||
--spaces Specifies amount of space indentation in the output.
|
||||
--full-tag XML elements will always be in <a></a> form.
|
||||
--no-decl Declaration directive <?xml?> will be ignored.
|
||||
--no-inst Processing instruction <?...?> will be ignored.
|
||||
--no-attr Attributes of elements will be ignored.
|
||||
--no-text Texts of elements will be ignored.
|
||||
--no-cdata CData of elements will be ignored.
|
||||
--no-doctype DOCTYPE of elements will be ignored.
|
||||
--no-comment Comments of elements will be ignored.
|
||||
--trim Any whitespaces surrounding texts will be trimmed.
|
||||
--compact JSON is in compact form.
|
||||
--native-type Numbers and boolean will be converted (coerced) to native type instead of text.
|
||||
--always-array Every element will always be an array type (applicable if --compact is set).
|
||||
--always-children Every element will always contain sub-elements (applicable if --compact is not set).
|
||||
--text-key To change the default 'text' key.
|
||||
--cdata-key To change the default 'cdata' key.
|
||||
--doctype-key To change the default 'doctype' key.
|
||||
--comment-key To change the default 'comment' key.
|
||||
--attributes-key To change the default 'attributes' key.
|
||||
--declaration-key To change the default 'declaration' key.
|
||||
--instruction-key To change the default 'processing instruction' key.
|
||||
--type-key To change the default 'type' key (applicable if --compact is not set).
|
||||
--name-key To change the default 'name' key (applicable if --compact is not set).
|
||||
--elements-key To change the default 'elements' key (applicable if --compact is not set).
|
||||
```
|
||||
|
||||
# Contribution
|
||||
|
||||
## Testing
|
||||
|
||||
To perform tests on this project, download the full repository from GitHub (not from npm) and then do the following:
|
||||
|
||||
```
|
||||
cd xml-js
|
||||
npm install
|
||||
npm test
|
||||
```
|
||||
For live testing, use `npm start` instead of `npm test`.
|
||||
|
||||
## Reporting
|
||||
|
||||
Use [this link](https://github.com/nashwaan/xml-js/issues) to report an issue or bug. Please include a sample code where the code is failing.
|
||||
|
||||
# License
|
||||
|
||||
[MIT](https://github.com/nashwaan/xml-js/blob/master/LICENSE)
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
module.exports = {
|
||||
|
||||
getCommandLineHelp: function (command, requiredArgs, optionalArgs) {
|
||||
var reqArgs = requiredArgs.reduce(function (res, arg) {return res + ' <' + arg.arg + '>';}, '');
|
||||
var output = 'Usage: ' + command + reqArgs + ' [options]\n';
|
||||
requiredArgs.forEach(function (argument) {
|
||||
output += ' <' + argument.arg + '>' + Array(20 - argument.arg.length).join(' ') + argument.desc + '\n';
|
||||
});
|
||||
output += '\nOptions:\n';
|
||||
optionalArgs.forEach(function (argument) {
|
||||
output += ' --' + argument.arg + Array(20 - argument.arg.length).join(' ') + argument.desc + '\n';
|
||||
});
|
||||
return output;
|
||||
},
|
||||
|
||||
mapCommandLineArgs: function (requiredArgs, optionalArgs) {
|
||||
var options = {}, r, o, a = 2;
|
||||
for (r = 0; r < requiredArgs.length; r += 1) {
|
||||
if (a < process.argv.length && process.argv[a].substr(0, 1) !== '-' && process.argv[a] !== 'JASMINE_CONFIG_PATH=./jasmine.json') {
|
||||
options[requiredArgs[r].option] = process.argv[a++];
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (; a < process.argv.length; a += 1) {
|
||||
for (o = 0; o < optionalArgs.length; o += 1) {
|
||||
if (optionalArgs[o].alias === process.argv[a].slice(1) || optionalArgs[o].arg === process.argv[a].slice(2)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (o < optionalArgs.length) {
|
||||
switch (optionalArgs[o].type) {
|
||||
case 'file': case 'string': case 'number':
|
||||
if (a + 1 < process.argv.length) {
|
||||
a += 1;
|
||||
options[optionalArgs[o].option] = (optionalArgs[o].type === 'number' ? Number(process.argv[a]) : process.argv[a]);
|
||||
}
|
||||
break;
|
||||
case 'flag':
|
||||
options[optionalArgs[o].option] = true; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
};
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
var fs = require('fs');
|
||||
var helper = require('./cli-helper');
|
||||
var project = require('../package.json');
|
||||
var xml2json = require('../lib/xml2json');
|
||||
var json2xml = require('../lib/json2xml');
|
||||
|
||||
var output = '';
|
||||
var stream = '';
|
||||
var options = {};
|
||||
var requiredArgs = [
|
||||
{ arg: 'src', type: 'file', option: 'src', desc: 'Input file that need to be converted.'}
|
||||
];
|
||||
var optionalArgs = [
|
||||
{ arg: 'help', alias: 'h', type: 'flag', option: 'help', desc: 'Display this help content.' },
|
||||
{ arg: 'version', alias: 'v', type: 'flag', option: 'version', desc: 'Display version number of this module.' },
|
||||
{ arg: 'out', type: 'file', option: 'out', desc: 'Output file where the converted result should be written.' },
|
||||
{ arg: 'to-json', type: 'flag', option:'toJason', desc: 'Convert.' },
|
||||
{ arg: 'compact', type: 'flag', option:'compact', desc: 'Compact JSON form (see explanation in www.npmjs.com/package/xml-js).' },
|
||||
{ arg: 'spaces', type: 'number', option:'spaces', desc: 'Specifies amount of space indentation in the output.' },
|
||||
{ arg: 'trim', type: 'flag', option:'trim', desc: 'Any whitespaces surrounding texts will be trimmed.' },
|
||||
// { arg: 'sanitize', type: 'flag', option:'sanitize', desc: 'Special xml characters will be replaced with entity codes.' },
|
||||
{ arg: 'native-type', type: 'flag', option:'nativeType', desc: 'Numbers and boolean will be converted (coerced) to native type instead of text.' },
|
||||
{ arg: 'always-array', type: 'flag', option:'alwaysArray', desc: 'Every element will always be an array type (applicable if --compact is set). If the passed value is an array, only elements with names in the passed array are always made arrays.' },
|
||||
{ arg: 'always-children', type: 'flag', option:'alwaysChildren', desc: 'Every element will always contain sub-elements (applicable if --compact is not set).' },
|
||||
{ arg: 'instruction-attr', type: 'flag', option:'instructionHasAttributes', desc: 'Whether to parse contents of processing instruction as attributes.' },
|
||||
{ arg: 'full-tag', type: 'flag', option:'fullTagEmptyElement', desc: 'XML elements will always be in <a></a> form.' },
|
||||
{ arg: 'no-decl', type: 'flag', option:'ignoreDeclaration', desc: 'Declaration instruction <?xml?> will be ignored.' },
|
||||
{ arg: 'no-decl', type: 'flag', option:'ignoreInstruction', desc: 'Processing instruction <?...?> will be ignored.' },
|
||||
{ arg: 'no-attr', type: 'flag', option:'ignoreAttributes', desc: 'Attributes of elements will be ignored.' },
|
||||
{ arg: 'no-text', type: 'flag', option:'ignoreText', desc: 'Texts of elements will be ignored.' },
|
||||
{ arg: 'no-cdata', type: 'flag', option:'ignoreCdata', desc: 'CData of elements will be ignored.' },
|
||||
{ arg: 'no-doctype', type: 'flag', option:'ignoreDoctype', desc: 'DOCTYPE of elements will be ignored.' },
|
||||
{ arg: 'no-comment', type: 'flag', option:'ignoreComment', desc: 'Comments of elements will be ignored.' },
|
||||
{ arg: 'text-key', type: 'string', option:'textKey', desc: 'To change the default \'text\' key.' },
|
||||
{ arg: 'cdata-key', type: 'string', option:'cdataKey', desc: 'To change the default \'cdata\' key.' },
|
||||
{ arg: 'doctype-key', type: 'string', option:'doctypeKey', desc: 'To change the default \'doctype\' key.' },
|
||||
{ arg: 'comment-key', type: 'string', option:'commentKey', desc: 'To change the default \'comment\' key.' },
|
||||
{ arg: 'attributes-key', type: 'string', option:'attributesKey', desc: 'To change the default \'attributes\' key.' },
|
||||
{ arg: 'declaration-key', type: 'string', option:'declarationKey', desc: 'To change the default \'declaration\' key <?xml?>.' },
|
||||
{ arg: 'instruction-key', type: 'string', option:'instructionKey', desc: 'To change the default \'processing instruction\' key <?...?>.' },
|
||||
{ arg: 'type-key', type: 'string', option:'typeKey', desc: 'To change the default \'type\' key (applicable if --compact is not set).' },
|
||||
{ arg: 'name-key', type: 'string', option:'nameKey', desc: 'To change the default \'name\' key (applicable if --compact is not set).' },
|
||||
{ arg: 'elements-key', type: 'string', option:'elementsKey', desc: 'To change the default \'elements\' key (applicable if --compact is not set).' }
|
||||
];
|
||||
|
||||
process.stdin.setEncoding('utf8');
|
||||
process.stdin.on('readable', function () {
|
||||
var chunk = process.stdin.read();
|
||||
if (chunk !== null) {
|
||||
stream += chunk;
|
||||
}
|
||||
});
|
||||
process.stdin.on('end', function () {
|
||||
process.stdout.write(xml2json(stream, {}) + '\n');
|
||||
});
|
||||
|
||||
options = helper.mapCommandLineArgs(requiredArgs, optionalArgs);
|
||||
|
||||
if (options.version) {
|
||||
console.log(project.version);
|
||||
process.exit(0);
|
||||
} else if (options.help || process.argv.length <= 2 + requiredArgs.length - 1) {
|
||||
console.log(helper.getCommandLineHelp('xml-js', requiredArgs, optionalArgs));
|
||||
process.exit(process.argv.length <= 2 ? 1 : 0);
|
||||
} else if ('src' in options) {
|
||||
if (fs.statSync(options.src).isFile()) {
|
||||
if (options.src.split('.').pop() === 'xml') {
|
||||
output = xml2json(fs.readFileSync(options.src, 'utf8'), options);
|
||||
} else if (options.src.split('.').pop() === 'json') {
|
||||
output = json2xml(fs.readFileSync(options.src, 'utf8'), options);
|
||||
}
|
||||
if (options.out) {
|
||||
fs.writeFileSync(options.out, output, 'utf8');
|
||||
} else {
|
||||
console.log(output);
|
||||
}
|
||||
process.exit(0);
|
||||
}
|
||||
} else {
|
||||
process.exit(1);
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"elements": [
|
||||
{
|
||||
"type": "element",
|
||||
"name": "a",
|
||||
"attributes": {
|
||||
"x": "1"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"type": "element",
|
||||
"name": "b",
|
||||
"elements": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "bye!"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
<a x="1">
|
||||
<b>bye!</b>
|
||||
</a>
|
||||
+8310
File diff suppressed because it is too large.
Load diff
+8
@@ -0,0 +1,8 @@
|
||||
!function(t,e){for(var n in e)t[n]=e[n]}(window,function(t){function e(r){if(n[r])return n[r].exports;var i=n[r]={i:r,l:!1,exports:{}};return t[r].call(i.exports,i,i.exports,e),i.l=!0,i.exports}var n={};return e.m=t,e.c=n,e.d=function(t,n,r){e.o(t,n)||Object.defineProperty(t,n,{configurable:!1,enumerable:!0,get:r})},e.n=function(t){var n=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(n,"a",n),n},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="",e(e.s=21)}([function(t,e,n){"use strict";function r(t){if(!(this instanceof r))return new r(t);c.call(this,t),l.call(this,t),t&&!1===t.readable&&(this.readable=!1),t&&!1===t.writable&&(this.writable=!1),this.allowHalfOpen=!0,t&&!1===t.allowHalfOpen&&(this.allowHalfOpen=!1),this.once("end",i)}function i(){this.allowHalfOpen||this._writableState.ended||o(a,this)}function a(t){t.end()}var o=n(6),s=Object.keys||function(t){var e=[];for(var n in t)e.push(n);return e};t.exports=r;var u=n(3);u.inherits=n(1);var c=n(16),l=n(10);u.inherits(r,c);for(var f=s(l.prototype),h=0;h<f.length;h++){var d=f[h];r.prototype[d]||(r.prototype[d]=l.prototype[d])}Object.defineProperty(r.prototype,"destroyed",{get:function(){return void 0!==this._readableState&&void 0!==this._writableState&&(this._readableState.destroyed&&this._writableState.destroyed)},set:function(t){void 0!==this._readableState&&void 0!==this._writableState&&(this._readableState.destroyed=t,this._writableState.destroyed=t)}}),r.prototype._destroy=function(t,e){this.push(null),this.end(),o(e,t)}},function(t,e){"function"==typeof Object.create?t.exports=function(t,e){t.super_=e,t.prototype=Object.create(e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}})}:t.exports=function(t,e){t.super_=e;var n=function(){};n.prototype=e.prototype,t.prototype=new n,t.prototype.constructor=t}},function(t,e){var n;n=function(){return this}();try{n=n||Function("return this")()||(0,eval)("this")}catch(t){"object"==typeof window&&(n=window)}t.exports=n},function(t,e,n){(function(t){function n(t){return Array.isArray?Array.isArray(t):"[object Array]"===y(t)}function r(t){return"boolean"==typeof t}function i(t){return null===t}function a(t){return null==t}function o(t){return"number"==typeof t}function s(t){return"string"==typeof t}function u(t){return"symbol"==typeof t}function c(t){return void 0===t}function l(t){return"[object RegExp]"===y(t)}function f(t){return"object"==typeof t&&null!==t}function h(t){return"[object Date]"===y(t)}function d(t){return"[object Error]"===y(t)||t instanceof Error}function p(t){return"function"==typeof t}function g(t){return null===t||"boolean"==typeof t||"number"==typeof t||"string"==typeof t||"symbol"==typeof t||void 0===t}function y(t){return Object.prototype.toString.call(t)}e.isArray=n,e.isBoolean=r,e.isNull=i,e.isNullOrUndefined=a,e.isNumber=o,e.isString=s,e.isSymbol=u,e.isUndefined=c,e.isRegExp=l,e.isObject=f,e.isDate=h,e.isError=d,e.isFunction=p,e.isPrimitive=g,e.isBuffer=t.isBuffer}).call(e,n(4).Buffer)},function(t,e,n){"use strict";(function(t){function r(){return a.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function i(t,e){if(r()<e)throw new RangeError("Invalid typed array length");return a.TYPED_ARRAY_SUPPORT?(t=new Uint8Array(e),t.__proto__=a.prototype):(null===t&&(t=new a(e)),t.length=e),t}function a(t,e,n){if(!(a.TYPED_ARRAY_SUPPORT||this instanceof a))return new a(t,e,n);if("number"==typeof t){if("string"==typeof e)throw new Error("If encoding is specified then the first argument must be a string");return c(this,t)}return o(this,t,e,n)}function o(t,e,n,r){if("number"==typeof e)throw new TypeError('"value" argument must not be a number');return"undefined"!=typeof ArrayBuffer&&e instanceof ArrayBuffer?h(t,e,n,r):"string"==typeof e?l(t,e,n):d(t,e)}function s(t){if("number"!=typeof t)throw new TypeError('"size" argument must be a number');if(t<0)throw new RangeError('"size" argument must not be negative')}function u(t,e,n,r){return s(e),e<=0?i(t,e):void 0!==n?"string"==typeof r?i(t,e).fill(n,r):i(t,e).fill(n):i(t,e)}function c(t,e){if(s(e),t=i(t,e<0?0:0|p(e)),!a.TYPED_ARRAY_SUPPORT)for(var n=0;n<e;++n)t[n]=0;return t}function l(t,e,n){if("string"==typeof n&&""!==n||(n="utf8"),!a.isEncoding(n))throw new TypeError('"encoding" must be a valid string encoding');var r=0|y(e,n);t=i(t,r);var o=t.write(e,n);return o!==r&&(t=t.slice(0,o)),t}function f(t,e){var n=e.length<0?0:0|p(e.length);t=i(t,n);for(var r=0;r<n;r+=1)t[r]=255&e[r];return t}function h(t,e,n,r){if(e.byteLength,n<0||e.byteLength<n)throw new RangeError("'offset' is out of bounds");if(e.byteLength<n+(r||0))throw new RangeError("'length' is out of bounds");return e=void 0===n&&void 0===r?new Uint8Array(e):void 0===r?new Uint8Array(e,n):new Uint8Array(e,n,r),a.TYPED_ARRAY_SUPPORT?(t=e,t.__proto__=a.prototype):t=f(t,e),t}function d(t,e){if(a.isBuffer(e)){var n=0|p(e.length);return t=i(t,n),0===t.length?t:(e.copy(t,0,0,n),t)}if(e){if("undefined"!=typeof ArrayBuffer&&e.bufLine truncated
|
||||
* The buffer module from node.js, for the browser.
|
||||
*
|
||||
* @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
|
||||
* @license MIT
|
||||
*/
|
||||
var z=n(23),J=n(24),Z=n(15);e.Buffer=a,e.SlowBuffer=g,e.INSPECT_MAX_BYTES=50,a.TYPED_ARRAY_SUPPORT=void 0!==t.TYPED_ARRAY_SUPPORT?t.TYPED_ARRAY_SUPPORT:function(){try{var t=new Uint8Array(1);return t.__proto__={__proto__:Uint8Array.prototype,foo:function(){return 42}},42===t.foo()&&"function"==typeof t.subarray&&0===t.subarray(1,1).byteLength}catch(t){return!1}}(),e.kMaxLength=r(),a.poolSize=8192,a._augment=function(t){return t.__proto__=a.prototype,t},a.from=function(t,e,n){return o(null,t,e,n)},a.TYPED_ARRAY_SUPPORT&&(a.prototype.__proto__=Uint8Array.prototype,a.__proto__=Uint8Array,"undefined"!=typeof Symbol&&Symbol.species&&a[Symbol.species]===a&&Object.defineProperty(a,Symbol.species,{value:null,configurable:!0})),a.alloc=function(t,e,n){return u(null,t,e,n)},a.allocUnsafe=function(t){return c(null,t)},a.allocUnsafeSlow=function(t){return c(null,t)},a.isBuffer=function(t){return!(null==t||!t._isBuffer)},a.compare=function(t,e){if(!a.isBuffer(t)||!a.isBuffer(e))throw new TypeError("Arguments must be Buffers");if(t===e)return 0;for(var n=t.length,r=e.length,i=0,o=Math.min(n,r);i<o;++i)if(t[i]!==e[i]){n=t[i],r=e[i];break}return n<r?-1:r<n?1:0},a.isEncoding=function(t){switch(String(t).toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"latin1":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return!0;default:return!1}},a.concat=function(t,e){if(!Z(t))throw new TypeError('"list" argument must be an Array of Buffers');if(0===t.length)return a.alloc(0);var n;if(void 0===e)for(e=0,n=0;n<t.length;++n)e+=t[n].length;var r=a.allocUnsafe(e),i=0;for(n=0;n<t.length;++n){var o=t[n];if(!a.isBuffer(o))throw new TypeError('"list" argument must be an Array of Buffers');o.copy(r,i),i+=o.length}return r},a.byteLength=y,a.prototype._isBuffer=!0,a.prototype.swap16=function(){var t=this.length;if(t%2!=0)throw new RangeError("Buffer size must be a multiple of 16-bits");for(var e=0;e<t;e+=2)b(this,e,e+1);return this},a.prototype.swap32=function(){var t=this.length;if(t%4!=0)throw new RangeError("Buffer size must be a multiple of 32-bits");for(var e=0;e<t;e+=4)b(this,e,e+3),b(this,e+1,e+2);return this},a.prototype.swap64=function(){var t=this.length;if(t%8!=0)throw new RangeError("Buffer size must be a multiple of 64-bits");for(var e=0;e<t;e+=8)b(this,e,e+7),b(this,e+1,e+6),b(this,e+2,e+5),b(this,e+3,e+4);return this},a.prototype.toString=function(){var t=0|this.length;return 0===t?"":0===arguments.length?I(this,0,t):m.apply(this,arguments)},a.prototype.equals=function(t){if(!a.isBuffer(t))throw new TypeError("Argument must be a Buffer");return this===t||0===a.compare(this,t)},a.prototype.inspect=function(){var t="",n=e.INSPECT_MAX_BYTES;return this.length>0&&(t=this.toString("hex",0,n).match(/.{2}/g).join(" "),this.length>n&&(t+=" ... ")),"<Buffer "+t+">"},a.prototype.compare=function(t,e,n,r,i){if(!a.isBuffer(t))throw new TypeError("Argument must be a Buffer");if(void 0===e&&(e=0),void 0===n&&(n=t?t.length:0),void 0===r&&(r=0),void 0===i&&(i=this.length),e<0||n>t.length||r<0||i>this.length)throw new RangeError("out of range index");if(r>=i&&e>=n)return 0;if(r>=i)return-1;if(e>=n)return 1;if(e>>>=0,n>>>=0,r>>>=0,i>>>=0,this===t)return 0;for(var o=i-r,s=n-e,u=Math.min(o,s),c=this.slice(r,i),l=t.slice(e,n),f=0;f<u;++f)if(c[f]!==l[f]){o=c[f],s=l[f];break}return o<s?-1:s<o?1:0},a.prototype.includes=function(t,e,n){return-1!==this.indexOf(t,e,n)},a.prototype.indexOf=function(t,e,n){return v(this,t,e,n,!0)},a.prototype.lastIndexOf=function(t,e,n){return v(this,t,e,n,!1)},a.prototype.write=function(t,e,n,r){if(void 0===e)r="utf8",n=this.length,e=0;else if(void 0===n&&"string"==typeof e)r=e,n=this.length,e=0;else{if(!isFinite(e))throw new Error("Buffer.write(string, encoding, offset[, length]) is no longer supported");e|=0,isFinite(n)?(n|=0,void 0===r&&(r="utf8")):(r=n,n=void 0)}var i=this.length-e;if((void 0===n||n>i)&&(n=i),t.length>0&&(n<0||e<0)||e>this.length)throw new RangeError("Attempt to write outside buffer bounds");r||(r="utf8");for(var a=!1;;)switch(r){case"hex":return w(this,t,e,n);case"utf8":case"utf-8":return _(this,t,e,n);case"ascii":return T(this,t,e,n);case"latin1":case"binary":return A(this,t,e,n);case"base64":return x(this,t,e,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return S(this,t,e,n);default:if(a)throw new TypeError("Unknown encoding: "+r);r=(""+r).toLowerCase(),a=!0}},a.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var $=4096;a.prototype.slice=function(t,e){var n=this.length;t=~~t,e=void 0===e?n:~~e,t<0?(t+=n)<0&&(t=0):t>n&&(t=n),e<0?(e+=n)<0&&(e=0):e>n&&(e=n),e<t&&(e=t);var r;if(a.TYPED_ARRAY_SUPPORT)r=this.subarray(t,e),r.__proto__=a.prototype;else{var i=e-t;r=new a(i,void 0);for(var o=0;o<i;++o)r[o]=this[o+t]}return r},a.prototype.readUIntLE=function(t,e,n){t|=0,e|=0,n||P(t,e,this.length);for(var r=this[t],i=1,a=0;++a<e&&(i*=256);)r+=this[t+a]*i;return r},a.prototype.readUIntBE=function(t,e,n){t|=Line truncated
|
||||
String.fromCodePoint||function(){var t=String.fromCharCode,e=Math.floor,n=function(){var n,r,i=[],a=-1,o=arguments.length;if(!o)return"";for(var s="";++a<o;){var u=Number(arguments[a]);if(!isFinite(u)||u<0||u>1114111||e(u)!==u)throw RangeError("Invalid code point: "+u);u<=65535?i.push(u):(u-=65536,n=55296+(u>>10),r=u%1024+56320,i.push(n,r)),(a+1===o||i.length>16384)&&(s+=t.apply(null,i),i.length=0)}return s};Object.defineProperty?Object.defineProperty(String,"fromCodePoint",{value:n,configurable:!0,writable:!0}):String.fromCodePoint=n}()}(e)}).call(e,n(4).Buffer)},function(t,e,n){"use strict";function r(t){var e=t.length;if(e%4>0)throw new Error("Invalid string. Length must be a multiple of 4");return"="===t[e-2]?2:"="===t[e-1]?1:0}function i(t){return 3*t.length/4-r(t)}function a(t){var e,n,i,a,o,s=t.length;a=r(t),o=new f(3*s/4-a),n=a>0?s-4:s;var u=0;for(e=0;e<n;e+=4)i=l[t.charCodeAt(e)]<<18|l[t.charCodeAt(e+1)]<<12|l[t.charCodeAt(e+2)]<<6|l[t.charCodeAt(e+3)],o[u++]=i>>16&255,o[u++]=i>>8&255,o[u++]=255&i;return 2===a?(i=l[t.charCodeAt(e)]<<2|l[t.charCodeAt(e+1)]>>4,o[u++]=255&i):1===a&&(i=l[t.charCodeAt(e)]<<10|l[t.charCodeAt(e+1)]<<4|l[t.charCodeAt(e+2)]>>2,o[u++]=i>>8&255,o[u++]=255&i),o}function o(t){return c[t>>18&63]+c[t>>12&63]+c[t>>6&63]+c[63&t]}function s(t,e,n){for(var r,i=[],a=e;a<n;a+=3)r=(t[a]<<16)+(t[a+1]<<8)+t[a+2],i.push(o(r));return i.join("")}function u(t){for(var e,n=t.length,r=n%3,i="",a=[],o=0,u=n-r;o<u;o+=16383)a.push(s(t,o,o+16383>u?u:o+16383));return 1===r?(e=t[n-1],i+=c[e>>2],i+=c[e<<4&63],i+="=="):2===r&&(e=(t[n-2]<<8)+t[n-1],i+=c[e>>10],i+=c[e>>4&63],i+=c[e<<2&63],i+="="),a.push(i),a.join("")}e.byteLength=i,e.toByteArray=a,e.fromByteArray=u;for(var c=[],l=[],f="undefined"!=typeof Uint8Array?Uint8Array:Array,h="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",d=0,p=h.length;d<p;++d)c[d]=h[d],l[h.charCodeAt(d)]=d;l["-".charCodeAt(0)]=62,l["_".charCodeAt(0)]=63},function(t,e){e.read=function(t,e,n,r,i){var a,o,s=8*i-r-1,u=(1<<s)-1,c=u>>1,l=-7,f=n?i-1:0,h=n?-1:1,d=t[e+f];for(f+=h,a=d&(1<<-l)-1,d>>=-l,l+=s;l>0;a=256*a+t[e+f],f+=h,l-=8);for(o=a&(1<<-l)-1,a>>=-l,l+=r;l>0;o=256*o+t[e+f],f+=h,l-=8);if(0===a)a=1-c;else{if(a===u)return o?NaN:1/0*(d?-1:1);o+=Math.pow(2,r),a-=c}return(d?-1:1)*o*Math.pow(2,a-r)},e.write=function(t,e,n,r,i,a){var o,s,u,c=8*a-i-1,l=(1<<c)-1,f=l>>1,h=23===i?Math.pow(2,-24)-Math.pow(2,-77):0,d=r?0:a-1,p=r?1:-1,g=e<0||0===e&&1/e<0?1:0;for(e=Math.abs(e),isNaN(e)||e===1/0?(s=isNaN(e)?1:0,o=l):(o=Math.floor(Math.log(e)/Math.LN2),e*(u=Math.pow(2,-o))<1&&(o--,u*=2),e+=o+f>=1?h/u:h*Math.pow(2,1-f),e*u>=2&&(o++,u/=2),o+f>=l?(s=0,o=l):o+f>=1?(s=(e*u-1)*Math.pow(2,i),o+=f):(s=e*Math.pow(2,f-1)*Math.pow(2,i),o=0));i>=8;t[n+d]=255&s,d+=p,s/=256,i-=8);for(o=o<<i|s,c+=i;c>0;t[n+d]=255&o,d+=p,o/=256,c-=8);t[n+d-p]|=128*g}},function(t,e,n){function r(){i.call(this)}t.exports=r;var i=n(8).EventEmitter;n(1)(r,i),r.Readable=n(9),r.Writable=n(32),r.Duplex=n(33),r.Transform=n(34),r.PassThrough=n(35),r.Stream=r,r.prototype.pipe=function(t,e){function n(e){t.writable&&!1===t.write(e)&&c.pause&&c.pause()}function r(){c.readable&&c.resume&&c.resume()}function a(){l||(l=!0,t.end())}function o(){l||(l=!0,"function"==typeof t.destroy&&t.destroy())}function s(t){if(u(),0===i.listenerCount(this,"error"))throw t}function u(){c.removeListener("data",n),t.removeListener("drain",r),c.removeListener("end",a),c.removeListener("close",o),c.removeListener("error",s),t.removeListener("error",s),c.removeListener("end",u),c.removeListener("close",u),t.removeListener("close",u)}var c=this;c.on("data",n),t.on("drain",r),t._isStdio||e&&!1===e.end||(c.on("end",a),c.on("close",o));var l=!1;return c.on("error",s),t.on("error",s),c.on("end",u),c.on("close",u),t.on("close",u),t.emit("pipe",c),t}},function(t,e){},function(t,e,n){"use strict";function r(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function i(t,e,n){t.copy(e,n)}var a=n(7).Buffer;t.exports=function(){function t(){r(this,t),this.head=null,this.tail=null,this.length=0}return t.prototype.push=function(t){var e={data:t,next:null};this.length>0?this.tail.next=e:this.head=e,this.tail=e,++this.length},t.prototype.unshift=function(t){var e={data:t,next:this.head};0===this.length&&(this.tail=e),this.head=e,++this.length},t.prototype.shift=function(){if(0!==this.length){var t=this.head.data;return 1===this.length?this.head=this.tail=null:this.head=this.head.next,--this.length,t}},t.prototype.clear=function(){this.head=this.tail=null,this.length=0},t.prototype.join=function(t){if(0===this.length)return"";for(var e=this.head,n=""+e.data;e=e.next;)n+=t+e.data;return n},t.prototype.concat=function(t){if(0===this.length)return a.alloc(0);if(1===this.length)return this.head.data;for(var e=a.allocUnsafe(t>>>0),n=this.head,r=0;n;)i(n.data,e,r),r+=n.data.length,n=n.next;return e},t}()},function(t,e,n){function r(t,e){this._id=t,this._clearFn=e}var i=Function.prototype.apply;e.setTimeout=function(){return new r(i.Line truncated
|
||||
+1
@@ -0,0 +1 @@
|
||||
module.exports = require('./lib');
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
module.exports = {
|
||||
|
||||
isArray: function(value) {
|
||||
if (Array.isArray) {
|
||||
return Array.isArray(value);
|
||||
}
|
||||
// fallback for older browsers like IE 8
|
||||
return Object.prototype.toString.call( value ) === '[object Array]';
|
||||
}
|
||||
|
||||
};
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
/*jslint node:true */
|
||||
|
||||
var xml2js = require('./xml2js');
|
||||
var xml2json = require('./xml2json');
|
||||
var js2xml = require('./js2xml');
|
||||
var json2xml = require('./json2xml');
|
||||
|
||||
module.exports = {
|
||||
xml2js: xml2js,
|
||||
xml2json: xml2json,
|
||||
js2xml: js2xml,
|
||||
json2xml: json2xml
|
||||
};
|
||||
+320
@@ -0,0 +1,320 @@
|
||||
var helper = require('./options-helper');
|
||||
var isArray = require('./array-helper').isArray;
|
||||
|
||||
var currentElement, currentElementName;
|
||||
|
||||
function validateOptions(userOptions) {
|
||||
var options = helper.copyOptions(userOptions);
|
||||
helper.ensureFlagExists('ignoreDeclaration', options);
|
||||
helper.ensureFlagExists('ignoreInstruction', options);
|
||||
helper.ensureFlagExists('ignoreAttributes', options);
|
||||
helper.ensureFlagExists('ignoreText', options);
|
||||
helper.ensureFlagExists('ignoreComment', options);
|
||||
helper.ensureFlagExists('ignoreCdata', options);
|
||||
helper.ensureFlagExists('ignoreDoctype', options);
|
||||
helper.ensureFlagExists('compact', options);
|
||||
helper.ensureFlagExists('indentText', options);
|
||||
helper.ensureFlagExists('indentCdata', options);
|
||||
helper.ensureFlagExists('indentAttributes', options);
|
||||
helper.ensureFlagExists('indentInstruction', options);
|
||||
helper.ensureFlagExists('fullTagEmptyElement', options);
|
||||
helper.ensureFlagExists('noQuotesForNativeAttributes', options);
|
||||
helper.ensureSpacesExists(options);
|
||||
if (typeof options.spaces === 'number') {
|
||||
options.spaces = Array(options.spaces + 1).join(' ');
|
||||
}
|
||||
helper.ensureKeyExists('declaration', options);
|
||||
helper.ensureKeyExists('instruction', options);
|
||||
helper.ensureKeyExists('attributes', options);
|
||||
helper.ensureKeyExists('text', options);
|
||||
helper.ensureKeyExists('comment', options);
|
||||
helper.ensureKeyExists('cdata', options);
|
||||
helper.ensureKeyExists('doctype', options);
|
||||
helper.ensureKeyExists('type', options);
|
||||
helper.ensureKeyExists('name', options);
|
||||
helper.ensureKeyExists('elements', options);
|
||||
helper.checkFnExists('doctype', options);
|
||||
helper.checkFnExists('instruction', options);
|
||||
helper.checkFnExists('cdata', options);
|
||||
helper.checkFnExists('comment', options);
|
||||
helper.checkFnExists('text', options);
|
||||
helper.checkFnExists('instructionName', options);
|
||||
helper.checkFnExists('elementName', options);
|
||||
helper.checkFnExists('attributeName', options);
|
||||
helper.checkFnExists('attributeValue', options);
|
||||
helper.checkFnExists('attributes', options);
|
||||
helper.checkFnExists('fullTagEmptyElement', options);
|
||||
return options;
|
||||
}
|
||||
|
||||
function writeIndentation(options, depth, firstLine) {
|
||||
return (!firstLine && options.spaces ? '\n' : '') + Array(depth + 1).join(options.spaces);
|
||||
}
|
||||
|
||||
function writeAttributes(attributes, options, depth) {
|
||||
if (options.ignoreAttributes) {
|
||||
return '';
|
||||
}
|
||||
if ('attributesFn' in options) {
|
||||
attributes = options.attributesFn(attributes, currentElementName, currentElement);
|
||||
}
|
||||
var key, attr, attrName, quote, result = [];
|
||||
for (key in attributes) {
|
||||
if (attributes.hasOwnProperty(key) && attributes[key] !== null && attributes[key] !== undefined) {
|
||||
quote = options.noQuotesForNativeAttributes && typeof attributes[key] !== 'string' ? '' : '"';
|
||||
attr = '' + attributes[key]; // ensure number and boolean are converted to String
|
||||
attr = attr.replace(/"/g, '"');
|
||||
attrName = 'attributeNameFn' in options ? options.attributeNameFn(key, attr, currentElementName, currentElement) : key;
|
||||
result.push((options.spaces && options.indentAttributes? writeIndentation(options, depth+1, false) : ' '));
|
||||
result.push(attrName + '=' + quote + ('attributeValueFn' in options ? options.attributeValueFn(attr, key, currentElementName, currentElement) : attr) + quote);
|
||||
}
|
||||
}
|
||||
if (attributes && Object.keys(attributes).length && options.spaces && options.indentAttributes) {
|
||||
result.push(writeIndentation(options, depth, false));
|
||||
}
|
||||
return result.join('');
|
||||
}
|
||||
|
||||
function writeDeclaration(declaration, options, depth) {
|
||||
currentElement = declaration;
|
||||
currentElementName = 'xml';
|
||||
return options.ignoreDeclaration ? '' : '<?' + 'xml' + writeAttributes(declaration[options.attributesKey], options, depth) + '?>';
|
||||
}
|
||||
|
||||
function writeInstruction(instruction, options, depth) {
|
||||
if (options.ignoreInstruction) {
|
||||
return '';
|
||||
}
|
||||
var key;
|
||||
for (key in instruction) {
|
||||
if (instruction.hasOwnProperty(key)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
var instructionName = 'instructionNameFn' in options ? options.instructionNameFn(key, instruction[key], currentElementName, currentElement) : key;
|
||||
if (typeof instruction[key] === 'object') {
|
||||
currentElement = instruction;
|
||||
currentElementName = instructionName;
|
||||
return '<?' + instructionName + writeAttributes(instruction[key][options.attributesKey], options, depth) + '?>';
|
||||
} else {
|
||||
var instructionValue = instruction[key] ? instruction[key] : '';
|
||||
if ('instructionFn' in options) instructionValue = options.instructionFn(instructionValue, key, currentElementName, currentElement);
|
||||
return '<?' + instructionName + (instructionValue ? ' ' + instructionValue : '') + '?>';
|
||||
}
|
||||
}
|
||||
|
||||
function writeComment(comment, options) {
|
||||
return options.ignoreComment ? '' : '<!--' + ('commentFn' in options ? options.commentFn(comment, currentElementName, currentElement) : comment) + '-->';
|
||||
}
|
||||
|
||||
function writeCdata(cdata, options) {
|
||||
return options.ignoreCdata ? '' : '<![CDATA[' + ('cdataFn' in options ? options.cdataFn(cdata, currentElementName, currentElement) : cdata.replace(']]>', ']]]]><![CDATA[>')) + ']]>';
|
||||
}
|
||||
|
||||
function writeDoctype(doctype, options) {
|
||||
return options.ignoreDoctype ? '' : '<!DOCTYPE ' + ('doctypeFn' in options ? options.doctypeFn(doctype, currentElementName, currentElement) : doctype) + '>';
|
||||
}
|
||||
|
||||
function writeText(text, options) {
|
||||
if (options.ignoreText) return '';
|
||||
text = '' + text; // ensure Number and Boolean are converted to String
|
||||
text = text.replace(/&/g, '&'); // desanitize to avoid double sanitization
|
||||
text = text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
||||
return 'textFn' in options ? options.textFn(text, currentElementName, currentElement) : text;
|
||||
}
|
||||
|
||||
function hasContent(element, options) {
|
||||
var i;
|
||||
if (element.elements && element.elements.length) {
|
||||
for (i = 0; i < element.elements.length; ++i) {
|
||||
switch (element.elements[i][options.typeKey]) {
|
||||
case 'text':
|
||||
if (options.indentText) {
|
||||
return true;
|
||||
}
|
||||
break; // skip to next key
|
||||
case 'cdata':
|
||||
if (options.indentCdata) {
|
||||
return true;
|
||||
}
|
||||
break; // skip to next key
|
||||
case 'instruction':
|
||||
if (options.indentInstruction) {
|
||||
return true;
|
||||
}
|
||||
break; // skip to next key
|
||||
case 'doctype':
|
||||
case 'comment':
|
||||
case 'element':
|
||||
return true;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function writeElement(element, options, depth) {
|
||||
currentElement = element;
|
||||
currentElementName = element.name;
|
||||
var xml = [], elementName = 'elementNameFn' in options ? options.elementNameFn(element.name, element) : element.name;
|
||||
xml.push('<' + elementName);
|
||||
if (element[options.attributesKey]) {
|
||||
xml.push(writeAttributes(element[options.attributesKey], options, depth));
|
||||
}
|
||||
var withClosingTag = element[options.elementsKey] && element[options.elementsKey].length || element[options.attributesKey] && element[options.attributesKey]['xml:space'] === 'preserve';
|
||||
if (!withClosingTag) {
|
||||
if ('fullTagEmptyElementFn' in options) {
|
||||
withClosingTag = options.fullTagEmptyElementFn(element.name, element);
|
||||
} else {
|
||||
withClosingTag = options.fullTagEmptyElement;
|
||||
}
|
||||
}
|
||||
if (withClosingTag) {
|
||||
xml.push('>');
|
||||
if (element[options.elementsKey] && element[options.elementsKey].length) {
|
||||
xml.push(writeElements(element[options.elementsKey], options, depth + 1));
|
||||
currentElement = element;
|
||||
currentElementName = element.name;
|
||||
}
|
||||
xml.push(options.spaces && hasContent(element, options) ? '\n' + Array(depth + 1).join(options.spaces) : '');
|
||||
xml.push('</' + elementName + '>');
|
||||
} else {
|
||||
xml.push('/>');
|
||||
}
|
||||
return xml.join('');
|
||||
}
|
||||
|
||||
function writeElements(elements, options, depth, firstLine) {
|
||||
return elements.reduce(function (xml, element) {
|
||||
var indent = writeIndentation(options, depth, firstLine && !xml);
|
||||
switch (element.type) {
|
||||
case 'element': return xml + indent + writeElement(element, options, depth);
|
||||
case 'comment': return xml + indent + writeComment(element[options.commentKey], options);
|
||||
case 'doctype': return xml + indent + writeDoctype(element[options.doctypeKey], options);
|
||||
case 'cdata': return xml + (options.indentCdata ? indent : '') + writeCdata(element[options.cdataKey], options);
|
||||
case 'text': return xml + (options.indentText ? indent : '') + writeText(element[options.textKey], options);
|
||||
case 'instruction':
|
||||
var instruction = {};
|
||||
instruction[element[options.nameKey]] = element[options.attributesKey] ? element : element[options.instructionKey];
|
||||
return xml + (options.indentInstruction ? indent : '') + writeInstruction(instruction, options, depth);
|
||||
}
|
||||
}, '');
|
||||
}
|
||||
|
||||
function hasContentCompact(element, options, anyContent) {
|
||||
var key;
|
||||
for (key in element) {
|
||||
if (element.hasOwnProperty(key)) {
|
||||
switch (key) {
|
||||
case options.parentKey:
|
||||
case options.attributesKey:
|
||||
break; // skip to next key
|
||||
case options.textKey:
|
||||
if (options.indentText || anyContent) {
|
||||
return true;
|
||||
}
|
||||
break; // skip to next key
|
||||
case options.cdataKey:
|
||||
if (options.indentCdata || anyContent) {
|
||||
return true;
|
||||
}
|
||||
break; // skip to next key
|
||||
case options.instructionKey:
|
||||
if (options.indentInstruction || anyContent) {
|
||||
return true;
|
||||
}
|
||||
break; // skip to next key
|
||||
case options.doctypeKey:
|
||||
case options.commentKey:
|
||||
return true;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function writeElementCompact(element, name, options, depth, indent) {
|
||||
currentElement = element;
|
||||
currentElementName = name;
|
||||
var elementName = 'elementNameFn' in options ? options.elementNameFn(name, element) : name;
|
||||
if (typeof element === 'undefined' || element === null || element === '') {
|
||||
return 'fullTagEmptyElementFn' in options && options.fullTagEmptyElementFn(name, element) || options.fullTagEmptyElement ? '<' + elementName + '></' + elementName + '>' : '<' + elementName + '/>';
|
||||
}
|
||||
var xml = [];
|
||||
if (name) {
|
||||
xml.push('<' + elementName);
|
||||
if (typeof element !== 'object') {
|
||||
xml.push('>' + writeText(element,options) + '</' + elementName + '>');
|
||||
return xml.join('');
|
||||
}
|
||||
if (element[options.attributesKey]) {
|
||||
xml.push(writeAttributes(element[options.attributesKey], options, depth));
|
||||
}
|
||||
var withClosingTag = hasContentCompact(element, options, true) || element[options.attributesKey] && element[options.attributesKey]['xml:space'] === 'preserve';
|
||||
if (!withClosingTag) {
|
||||
if ('fullTagEmptyElementFn' in options) {
|
||||
withClosingTag = options.fullTagEmptyElementFn(name, element);
|
||||
} else {
|
||||
withClosingTag = options.fullTagEmptyElement;
|
||||
}
|
||||
}
|
||||
if (withClosingTag) {
|
||||
xml.push('>');
|
||||
} else {
|
||||
xml.push('/>');
|
||||
return xml.join('');
|
||||
}
|
||||
}
|
||||
xml.push(writeElementsCompact(element, options, depth + 1, false));
|
||||
currentElement = element;
|
||||
currentElementName = name;
|
||||
if (name) {
|
||||
xml.push((indent ? writeIndentation(options, depth, false) : '') + '</' + elementName + '>');
|
||||
}
|
||||
return xml.join('');
|
||||
}
|
||||
|
||||
function writeElementsCompact(element, options, depth, firstLine) {
|
||||
var i, key, nodes, xml = [];
|
||||
for (key in element) {
|
||||
if (element.hasOwnProperty(key)) {
|
||||
nodes = isArray(element[key]) ? element[key] : [element[key]];
|
||||
for (i = 0; i < nodes.length; ++i) {
|
||||
switch (key) {
|
||||
case options.declarationKey: xml.push(writeDeclaration(nodes[i], options, depth)); break;
|
||||
case options.instructionKey: xml.push((options.indentInstruction ? writeIndentation(options, depth, firstLine) : '') + writeInstruction(nodes[i], options, depth)); break;
|
||||
case options.attributesKey: case options.parentKey: break; // skip
|
||||
case options.textKey: xml.push((options.indentText ? writeIndentation(options, depth, firstLine) : '') + writeText(nodes[i], options)); break;
|
||||
case options.cdataKey: xml.push((options.indentCdata ? writeIndentation(options, depth, firstLine) : '') + writeCdata(nodes[i], options)); break;
|
||||
case options.doctypeKey: xml.push(writeIndentation(options, depth, firstLine) + writeDoctype(nodes[i], options)); break;
|
||||
case options.commentKey: xml.push(writeIndentation(options, depth, firstLine) + writeComment(nodes[i], options)); break;
|
||||
default: xml.push(writeIndentation(options, depth, firstLine) + writeElementCompact(nodes[i], key, options, depth, hasContentCompact(nodes[i], options)));
|
||||
}
|
||||
firstLine = firstLine && !xml.length;
|
||||
}
|
||||
}
|
||||
}
|
||||
return xml.join('');
|
||||
}
|
||||
|
||||
module.exports = function (js, options) {
|
||||
options = validateOptions(options);
|
||||
var xml = [];
|
||||
currentElement = js;
|
||||
currentElementName = '_root_';
|
||||
if (options.compact) {
|
||||
xml.push(writeElementsCompact(js, options, 0, true));
|
||||
} else {
|
||||
if (js[options.declarationKey]) {
|
||||
xml.push(writeDeclaration(js[options.declarationKey], options, 0));
|
||||
}
|
||||
if (js[options.elementsKey] && js[options.elementsKey].length) {
|
||||
xml.push(writeElements(js[options.elementsKey], options, 0, !xml.length));
|
||||
}
|
||||
}
|
||||
return xml.join('');
|
||||
};
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
var js2xml = require('./js2xml.js');
|
||||
|
||||
module.exports = function (json, options) {
|
||||
if (json instanceof Buffer) {
|
||||
json = json.toString();
|
||||
}
|
||||
var js = null;
|
||||
if (typeof (json) === 'string') {
|
||||
try {
|
||||
js = JSON.parse(json);
|
||||
} catch (e) {
|
||||
throw new Error('The JSON structure is invalid');
|
||||
}
|
||||
} else {
|
||||
js = json;
|
||||
}
|
||||
return js2xml(js, options);
|
||||
};
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
var isArray = require('./array-helper').isArray;
|
||||
|
||||
module.exports = {
|
||||
|
||||
copyOptions: function (options) {
|
||||
var key, copy = {};
|
||||
for (key in options) {
|
||||
if (options.hasOwnProperty(key)) {
|
||||
copy[key] = options[key];
|
||||
}
|
||||
}
|
||||
return copy;
|
||||
},
|
||||
|
||||
ensureFlagExists: function (item, options) {
|
||||
if (!(item in options) || typeof options[item] !== 'boolean') {
|
||||
options[item] = false;
|
||||
}
|
||||
},
|
||||
|
||||
ensureSpacesExists: function (options) {
|
||||
if (!('spaces' in options) || (typeof options.spaces !== 'number' && typeof options.spaces !== 'string')) {
|
||||
options.spaces = 0;
|
||||
}
|
||||
},
|
||||
|
||||
ensureAlwaysArrayExists: function (options) {
|
||||
if (!('alwaysArray' in options) || (typeof options.alwaysArray !== 'boolean' && !isArray(options.alwaysArray))) {
|
||||
options.alwaysArray = false;
|
||||
}
|
||||
},
|
||||
|
||||
ensureKeyExists: function (key, options) {
|
||||
if (!(key + 'Key' in options) || typeof options[key + 'Key'] !== 'string') {
|
||||
options[key + 'Key'] = options.compact ? '_' + key : key;
|
||||
}
|
||||
},
|
||||
|
||||
checkFnExists: function (key, options) {
|
||||
return key + 'Fn' in options;
|
||||
}
|
||||
|
||||
};
|
||||
+362
@@ -0,0 +1,362 @@
|
||||
var sax = require('sax');
|
||||
var expat /*= require('node-expat');*/ = { on: function () { }, parse: function () { } };
|
||||
var helper = require('./options-helper');
|
||||
var isArray = require('./array-helper').isArray;
|
||||
|
||||
var options;
|
||||
var pureJsParser = true;
|
||||
var currentElement;
|
||||
|
||||
function validateOptions(userOptions) {
|
||||
options = helper.copyOptions(userOptions);
|
||||
helper.ensureFlagExists('ignoreDeclaration', options);
|
||||
helper.ensureFlagExists('ignoreInstruction', options);
|
||||
helper.ensureFlagExists('ignoreAttributes', options);
|
||||
helper.ensureFlagExists('ignoreText', options);
|
||||
helper.ensureFlagExists('ignoreComment', options);
|
||||
helper.ensureFlagExists('ignoreCdata', options);
|
||||
helper.ensureFlagExists('ignoreDoctype', options);
|
||||
helper.ensureFlagExists('compact', options);
|
||||
helper.ensureFlagExists('alwaysChildren', options);
|
||||
helper.ensureFlagExists('addParent', options);
|
||||
helper.ensureFlagExists('trim', options);
|
||||
helper.ensureFlagExists('nativeType', options);
|
||||
helper.ensureFlagExists('nativeTypeAttributes', options);
|
||||
helper.ensureFlagExists('sanitize', options);
|
||||
helper.ensureFlagExists('instructionHasAttributes', options);
|
||||
helper.ensureFlagExists('captureSpacesBetweenElements', options);
|
||||
helper.ensureAlwaysArrayExists(options);
|
||||
helper.ensureKeyExists('declaration', options);
|
||||
helper.ensureKeyExists('instruction', options);
|
||||
helper.ensureKeyExists('attributes', options);
|
||||
helper.ensureKeyExists('text', options);
|
||||
helper.ensureKeyExists('comment', options);
|
||||
helper.ensureKeyExists('cdata', options);
|
||||
helper.ensureKeyExists('doctype', options);
|
||||
helper.ensureKeyExists('type', options);
|
||||
helper.ensureKeyExists('name', options);
|
||||
helper.ensureKeyExists('elements', options);
|
||||
helper.ensureKeyExists('parent', options);
|
||||
helper.checkFnExists('doctype', options);
|
||||
helper.checkFnExists('instruction', options);
|
||||
helper.checkFnExists('cdata', options);
|
||||
helper.checkFnExists('comment', options);
|
||||
helper.checkFnExists('text', options);
|
||||
helper.checkFnExists('instructionName', options);
|
||||
helper.checkFnExists('elementName', options);
|
||||
helper.checkFnExists('attributeName', options);
|
||||
helper.checkFnExists('attributeValue', options);
|
||||
helper.checkFnExists('attributes', options);
|
||||
return options;
|
||||
}
|
||||
|
||||
function nativeType(value) {
|
||||
var nValue = Number(value);
|
||||
if (!isNaN(nValue)) {
|
||||
return nValue;
|
||||
}
|
||||
var bValue = value.toLowerCase();
|
||||
if (bValue === 'true') {
|
||||
return true;
|
||||
} else if (bValue === 'false') {
|
||||
return false;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
function addField(type, value) {
|
||||
var key;
|
||||
if (options.compact) {
|
||||
if (
|
||||
!currentElement[options[type + 'Key']] &&
|
||||
(isArray(options.alwaysArray) ? options.alwaysArray.indexOf(options[type + 'Key']) !== -1 : options.alwaysArray)
|
||||
) {
|
||||
currentElement[options[type + 'Key']] = [];
|
||||
}
|
||||
if (currentElement[options[type + 'Key']] && !isArray(currentElement[options[type + 'Key']])) {
|
||||
currentElement[options[type + 'Key']] = [currentElement[options[type + 'Key']]];
|
||||
}
|
||||
if (type + 'Fn' in options && typeof value === 'string') {
|
||||
value = options[type + 'Fn'](value, currentElement);
|
||||
}
|
||||
if (type === 'instruction' && ('instructionFn' in options || 'instructionNameFn' in options)) {
|
||||
for (key in value) {
|
||||
if (value.hasOwnProperty(key)) {
|
||||
if ('instructionFn' in options) {
|
||||
value[key] = options.instructionFn(value[key], key, currentElement);
|
||||
} else {
|
||||
var temp = value[key];
|
||||
delete value[key];
|
||||
value[options.instructionNameFn(key, temp, currentElement)] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isArray(currentElement[options[type + 'Key']])) {
|
||||
currentElement[options[type + 'Key']].push(value);
|
||||
} else {
|
||||
currentElement[options[type + 'Key']] = value;
|
||||
}
|
||||
} else {
|
||||
if (!currentElement[options.elementsKey]) {
|
||||
currentElement[options.elementsKey] = [];
|
||||
}
|
||||
var element = {};
|
||||
element[options.typeKey] = type;
|
||||
if (type === 'instruction') {
|
||||
for (key in value) {
|
||||
if (value.hasOwnProperty(key)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
element[options.nameKey] = 'instructionNameFn' in options ? options.instructionNameFn(key, value, currentElement) : key;
|
||||
if (options.instructionHasAttributes) {
|
||||
element[options.attributesKey] = value[key][options.attributesKey];
|
||||
if ('instructionFn' in options) {
|
||||
element[options.attributesKey] = options.instructionFn(element[options.attributesKey], key, currentElement);
|
||||
}
|
||||
} else {
|
||||
if ('instructionFn' in options) {
|
||||
value[key] = options.instructionFn(value[key], key, currentElement);
|
||||
}
|
||||
element[options.instructionKey] = value[key];
|
||||
}
|
||||
} else {
|
||||
if (type + 'Fn' in options) {
|
||||
value = options[type + 'Fn'](value, currentElement);
|
||||
}
|
||||
element[options[type + 'Key']] = value;
|
||||
}
|
||||
if (options.addParent) {
|
||||
element[options.parentKey] = currentElement;
|
||||
}
|
||||
currentElement[options.elementsKey].push(element);
|
||||
}
|
||||
}
|
||||
|
||||
function manipulateAttributes(attributes) {
|
||||
if ('attributesFn' in options && attributes) {
|
||||
attributes = options.attributesFn(attributes, currentElement);
|
||||
}
|
||||
if ((options.trim || 'attributeValueFn' in options || 'attributeNameFn' in options || options.nativeTypeAttributes) && attributes) {
|
||||
var key;
|
||||
for (key in attributes) {
|
||||
if (attributes.hasOwnProperty(key)) {
|
||||
if (options.trim) attributes[key] = attributes[key].trim();
|
||||
if (options.nativeTypeAttributes) {
|
||||
attributes[key] = nativeType(attributes[key]);
|
||||
}
|
||||
if ('attributeValueFn' in options) attributes[key] = options.attributeValueFn(attributes[key], key, currentElement);
|
||||
if ('attributeNameFn' in options) {
|
||||
var temp = attributes[key];
|
||||
delete attributes[key];
|
||||
attributes[options.attributeNameFn(key, attributes[key], currentElement)] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return attributes;
|
||||
}
|
||||
|
||||
function onInstruction(instruction) {
|
||||
var attributes = {};
|
||||
if (instruction.body && (instruction.name.toLowerCase() === 'xml' || options.instructionHasAttributes)) {
|
||||
var attrsRegExp = /([\w:-]+)\s*=\s*(?:"([^"]*)"|'([^']*)'|(\w+))\s*/g;
|
||||
var match;
|
||||
while ((match = attrsRegExp.exec(instruction.body)) !== null) {
|
||||
attributes[match[1]] = match[2] || match[3] || match[4];
|
||||
}
|
||||
attributes = manipulateAttributes(attributes);
|
||||
}
|
||||
if (instruction.name.toLowerCase() === 'xml') {
|
||||
if (options.ignoreDeclaration) {
|
||||
return;
|
||||
}
|
||||
currentElement[options.declarationKey] = {};
|
||||
if (Object.keys(attributes).length) {
|
||||
currentElement[options.declarationKey][options.attributesKey] = attributes;
|
||||
}
|
||||
if (options.addParent) {
|
||||
currentElement[options.declarationKey][options.parentKey] = currentElement;
|
||||
}
|
||||
} else {
|
||||
if (options.ignoreInstruction) {
|
||||
return;
|
||||
}
|
||||
if (options.trim) {
|
||||
instruction.body = instruction.body.trim();
|
||||
}
|
||||
var value = {};
|
||||
if (options.instructionHasAttributes && Object.keys(attributes).length) {
|
||||
value[instruction.name] = {};
|
||||
value[instruction.name][options.attributesKey] = attributes;
|
||||
} else {
|
||||
value[instruction.name] = instruction.body;
|
||||
}
|
||||
addField('instruction', value);
|
||||
}
|
||||
}
|
||||
|
||||
function onStartElement(name, attributes) {
|
||||
var element;
|
||||
if (typeof name === 'object') {
|
||||
attributes = name.attributes;
|
||||
name = name.name;
|
||||
}
|
||||
attributes = manipulateAttributes(attributes);
|
||||
if ('elementNameFn' in options) {
|
||||
name = options.elementNameFn(name, currentElement);
|
||||
}
|
||||
if (options.compact) {
|
||||
element = {};
|
||||
if (!options.ignoreAttributes && attributes && Object.keys(attributes).length) {
|
||||
element[options.attributesKey] = {};
|
||||
var key;
|
||||
for (key in attributes) {
|
||||
if (attributes.hasOwnProperty(key)) {
|
||||
element[options.attributesKey][key] = attributes[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (
|
||||
!(name in currentElement) &&
|
||||
(isArray(options.alwaysArray) ? options.alwaysArray.indexOf(name) !== -1 : options.alwaysArray)
|
||||
) {
|
||||
currentElement[name] = [];
|
||||
}
|
||||
if (currentElement[name] && !isArray(currentElement[name])) {
|
||||
currentElement[name] = [currentElement[name]];
|
||||
}
|
||||
if (isArray(currentElement[name])) {
|
||||
currentElement[name].push(element);
|
||||
} else {
|
||||
currentElement[name] = element;
|
||||
}
|
||||
} else {
|
||||
if (!currentElement[options.elementsKey]) {
|
||||
currentElement[options.elementsKey] = [];
|
||||
}
|
||||
element = {};
|
||||
element[options.typeKey] = 'element';
|
||||
element[options.nameKey] = name;
|
||||
if (!options.ignoreAttributes && attributes && Object.keys(attributes).length) {
|
||||
element[options.attributesKey] = attributes;
|
||||
}
|
||||
if (options.alwaysChildren) {
|
||||
element[options.elementsKey] = [];
|
||||
}
|
||||
currentElement[options.elementsKey].push(element);
|
||||
}
|
||||
element[options.parentKey] = currentElement; // will be deleted in onEndElement() if !options.addParent
|
||||
currentElement = element;
|
||||
}
|
||||
|
||||
function onText(text) {
|
||||
if (options.ignoreText) {
|
||||
return;
|
||||
}
|
||||
if (!text.trim() && !options.captureSpacesBetweenElements) {
|
||||
return;
|
||||
}
|
||||
if (options.trim) {
|
||||
text = text.trim();
|
||||
}
|
||||
if (options.nativeType) {
|
||||
text = nativeType(text);
|
||||
}
|
||||
if (options.sanitize) {
|
||||
text = text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
||||
}
|
||||
addField('text', text);
|
||||
}
|
||||
|
||||
function onComment(comment) {
|
||||
if (options.ignoreComment) {
|
||||
return;
|
||||
}
|
||||
if (options.trim) {
|
||||
comment = comment.trim();
|
||||
}
|
||||
addField('comment', comment);
|
||||
}
|
||||
|
||||
function onEndElement(name) {
|
||||
var parentElement = currentElement[options.parentKey];
|
||||
if (!options.addParent) {
|
||||
delete currentElement[options.parentKey];
|
||||
}
|
||||
currentElement = parentElement;
|
||||
}
|
||||
|
||||
function onCdata(cdata) {
|
||||
if (options.ignoreCdata) {
|
||||
return;
|
||||
}
|
||||
if (options.trim) {
|
||||
cdata = cdata.trim();
|
||||
}
|
||||
addField('cdata', cdata);
|
||||
}
|
||||
|
||||
function onDoctype(doctype) {
|
||||
if (options.ignoreDoctype) {
|
||||
return;
|
||||
}
|
||||
doctype = doctype.replace(/^ /, '');
|
||||
if (options.trim) {
|
||||
doctype = doctype.trim();
|
||||
}
|
||||
addField('doctype', doctype);
|
||||
}
|
||||
|
||||
function onError(error) {
|
||||
error.note = error; //console.error(error);
|
||||
}
|
||||
|
||||
module.exports = function (xml, userOptions) {
|
||||
|
||||
var parser = pureJsParser ? sax.parser(true, {}) : parser = new expat.Parser('UTF-8');
|
||||
var result = {};
|
||||
currentElement = result;
|
||||
|
||||
options = validateOptions(userOptions);
|
||||
|
||||
if (pureJsParser) {
|
||||
parser.opt = {strictEntities: true};
|
||||
parser.onopentag = onStartElement;
|
||||
parser.ontext = onText;
|
||||
parser.oncomment = onComment;
|
||||
parser.onclosetag = onEndElement;
|
||||
parser.onerror = onError;
|
||||
parser.oncdata = onCdata;
|
||||
parser.ondoctype = onDoctype;
|
||||
parser.onprocessinginstruction = onInstruction;
|
||||
} else {
|
||||
parser.on('startElement', onStartElement);
|
||||
parser.on('text', onText);
|
||||
parser.on('comment', onComment);
|
||||
parser.on('endElement', onEndElement);
|
||||
parser.on('error', onError);
|
||||
//parser.on('startCdata', onStartCdata);
|
||||
//parser.on('endCdata', onEndCdata);
|
||||
//parser.on('entityDecl', onEntityDecl);
|
||||
}
|
||||
|
||||
if (pureJsParser) {
|
||||
parser.write(xml).close();
|
||||
} else {
|
||||
if (!parser.parse(xml)) {
|
||||
throw new Error('XML parsing error: ' + parser.getError());
|
||||
}
|
||||
}
|
||||
|
||||
if (result[options.elementsKey]) {
|
||||
var temp = result[options.elementsKey];
|
||||
delete result[options.elementsKey];
|
||||
result[options.elementsKey] = temp;
|
||||
delete result.text;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
};
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
var helper = require('./options-helper');
|
||||
var xml2js = require('./xml2js');
|
||||
|
||||
function validateOptions (userOptions) {
|
||||
var options = helper.copyOptions(userOptions);
|
||||
helper.ensureSpacesExists(options);
|
||||
return options;
|
||||
}
|
||||
|
||||
module.exports = function(xml, userOptions) {
|
||||
var options, js, json, parentKey;
|
||||
options = validateOptions(userOptions);
|
||||
js = xml2js(xml, options);
|
||||
parentKey = 'compact' in options && options.compact ? '_parent' : 'parent';
|
||||
// parentKey = ptions.compact ? '_parent' : 'parent'; // consider this
|
||||
if ('addParent' in options && options.addParent) {
|
||||
json = JSON.stringify(js, function (k, v) { return k === parentKey? '_' : v; }, options.spaces);
|
||||
} else {
|
||||
json = JSON.stringify(js, null, options.spaces);
|
||||
}
|
||||
return json.replace(/\u2028/g, '\\u2028').replace(/\u2029/g, '\\u2029');
|
||||
};
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
{
|
||||
"name": "xml-js",
|
||||
"version": "1.6.11",
|
||||
"description": "A convertor between XML text and Javascript object / JSON text.",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/nashwaan/xml-js.git"
|
||||
},
|
||||
"author": "Yousuf Almarzooqi <ysf953@gmail.com>",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/nashwaan/xml-js/issues"
|
||||
},
|
||||
"homepage": "https://github.com/nashwaan/xml-js#readme",
|
||||
"keywords": [
|
||||
"XML",
|
||||
"xml",
|
||||
"js",
|
||||
"JSON",
|
||||
"json",
|
||||
"cdata",
|
||||
"CDATA",
|
||||
"doctype",
|
||||
"processing instruction",
|
||||
"Javascript",
|
||||
"js2xml",
|
||||
"json2xml",
|
||||
"xml2js",
|
||||
"xml2json",
|
||||
"transform",
|
||||
"transformer",
|
||||
"transforming",
|
||||
"transformation",
|
||||
"convert",
|
||||
"convertor",
|
||||
"converting",
|
||||
"conversion",
|
||||
"parse",
|
||||
"parser",
|
||||
"parsing"
|
||||
],
|
||||
"main": "lib/index.js",
|
||||
"bin": "./bin/cli.js",
|
||||
"types": "./types/index.d.ts",
|
||||
"scripts": {
|
||||
"build": "webpack",
|
||||
"doc": "node doc/compile-doc.js",
|
||||
"watch:doc": "watch \"npm run doc\" doc/templates/",
|
||||
"live:doc": "browser-sync start --port 9997 --server doc/ --files doc/templates/ --no-open --no-ui --no-online",
|
||||
"open:doc": "biased-opener --browser chrome http://localhost:9997",
|
||||
"start:doc": "npm-run-all --parallel watch:doc live:doc open:doc",
|
||||
"debug": "nodemon --inspect --watch lib/ --watch test/ --debug-brk test/index.js",
|
||||
"debug:cli": "nodemon --inspect --watch lib/ --debug-brk index.js -- --help",
|
||||
"jest": "jest --config=test/jest.conf.js",
|
||||
"jasmine": "jasmine JASMINE_CONFIG_PATH=./test/jasmine.json",
|
||||
"watch:jasmine": "watch \"npm run jasmine\" lib/ test/ --ignoreDirectoryPattern=/browse-.+/",
|
||||
"bundle:jasmine": "globify test/*.spec.js --watch --verbose --list --outfile test/browse-jasmine/bundle.js",
|
||||
"live:jasmine": "browser-sync start --port 9999 --server test/browse-jasmine/ --files test/browse-jasmine/ --no-open --no-ui --no-online",
|
||||
"open-help": "biased-opener --help",
|
||||
"open:jasmine": "biased-opener --browser chrome http://localhost:9999",
|
||||
"istanbul-original": "istanbul cover --dir test/coverage-jasmine -x test/browse-** test/index.js",
|
||||
"istanbul": "istanbul cover --dir test/coverage-jasmine test/index.js",
|
||||
"watch:istanbul": "watch \"npm run istanbul\" lib/ test/ --ignoreDirectoryPattern=/coverage-.+/",
|
||||
"live:istanbul": "browser-sync start --port 9998 --server test/coverage-jasmine/lcov-report/ --files test/coverage-jasmine/lcov-report/ --no-open --no-ui --no-online",
|
||||
"open:istanbul": "biased-opener --browser chrome http://localhost:9998",
|
||||
"live": "npm-run-all --parallel live:* open:*",
|
||||
"start": "npm-run-all --parallel bundle:jasmine live:jasmine open:jasmine watch:istanbul live:istanbul open:istanbul",
|
||||
"git:commit": "git add . && git commit -a -m \"Committed by npm script.\" && git push origin master",
|
||||
"git:push": "git push origin master",
|
||||
"deploy": "npm-run-all --serial coverage:* git:*",
|
||||
"coverage": "npm-run-all coverage:*",
|
||||
"coverage:a-step": "npm run istanbul",
|
||||
"coverage:coveralls": "cross-env COVERALLS_REPO_TOKEN=CaEwzjHxsKRqomJSYmGagrJdlR7uLHhHC && cat ./test/coverage-jasmine/lcov.info | coveralls",
|
||||
"coverage:codecov": "codecov --token=0e52af41-702b-4d7f-8aa3-61145ac36624 --file=test/coverage-jasmine/lcov.info ",
|
||||
"coverage:codacy": "cross-env CODACY_PROJECT_TOKEN=0207815122ea49a68241d1aa435f21f1 && cat ./test/coverage-jasmine/lcov.info | codacy-coverage",
|
||||
"coverage:codeclimate": "cross-env CODECLIMATE_REPO_TOKEN=60848a077f9070acf358b0c7145f0a2698a460ddeca7d8250815e75aa4333f7d codeclimate-test-reporter < test\\coverage-jasmine\\lcov.info",
|
||||
"prepublish": "npm run test",
|
||||
"test": "npm run jasmine && npm run jest && npm run test:types",
|
||||
"test:types": "tsc -p ./types"
|
||||
},
|
||||
"dependencies": {
|
||||
"sax": "^1.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-core": "^6.26.3",
|
||||
"babel-loader": "^7.1.4",
|
||||
"babel-preset-env": "^1.7.0",
|
||||
"biased-opener": "^0.2.8",
|
||||
"browser-sync": "^2.26.3",
|
||||
"cash-cat": "^0.2.0",
|
||||
"codacy-coverage": "^3.4.0",
|
||||
"codeclimate-test-reporter": "^0.5.1",
|
||||
"codecov": "^3.1.0",
|
||||
"coveralls": "^3.0.2",
|
||||
"cross-env": "^5.2.0",
|
||||
"eslint": "^5.12.0",
|
||||
"globify": "^2.3.4",
|
||||
"istanbul": "^0.4.5",
|
||||
"jasmine": "^3.3.1",
|
||||
"jest": "^20.0.4",
|
||||
"jest-cli": "^20.0.4",
|
||||
"jsonpath": "^1.0.0",
|
||||
"nodemon": "^1.18.9",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"prismjs": "^1.15.0",
|
||||
"typescript": "^3.2.2",
|
||||
"unminified-webpack-plugin": "^1.4.2",
|
||||
"watch": "^1.0.1",
|
||||
"webpack": "^3.10.0"
|
||||
}
|
||||
}
|
||||
+154
@@ -0,0 +1,154 @@
|
||||
export interface Attributes {
|
||||
[key: string]: string | number | undefined
|
||||
}
|
||||
|
||||
export interface DeclarationAttributes {
|
||||
version?: string | number
|
||||
encoding?: 'utf-8' | string
|
||||
standalone?: 'yes' | 'no'
|
||||
}
|
||||
|
||||
export interface ElementCompact {
|
||||
[key: string]: any
|
||||
_declaration?: {
|
||||
_attributes?: DeclarationAttributes
|
||||
}
|
||||
_instruction?: {
|
||||
[key: string]: string
|
||||
}
|
||||
_attributes?: Attributes
|
||||
_cdata?: string
|
||||
_doctype?: string
|
||||
_comment?: string
|
||||
_text?: string | number
|
||||
}
|
||||
|
||||
export interface Element {
|
||||
declaration?: {
|
||||
attributes?: DeclarationAttributes
|
||||
}
|
||||
instruction?: string
|
||||
attributes?: Attributes
|
||||
cdata?: string
|
||||
doctype?: string
|
||||
comment?: string
|
||||
text?: string | number | boolean
|
||||
type?: string
|
||||
name?: string
|
||||
elements?: Array<Element>
|
||||
}
|
||||
|
||||
declare namespace Options {
|
||||
interface XML2JSON extends XML2JS {
|
||||
spaces?: number | string
|
||||
}
|
||||
|
||||
interface XML2JS extends ChangingKeyNames, IgnoreOptions {
|
||||
compact?: boolean
|
||||
trim?: boolean
|
||||
sanitize?: boolean
|
||||
nativeType?: boolean
|
||||
addParent?: boolean
|
||||
alwaysArray?: boolean | Array<string>
|
||||
alwaysChildren?: boolean
|
||||
instructionHasAttributes?: boolean
|
||||
captureSpacesBetweenElements?: boolean
|
||||
doctypeFn?: (value: string, parentElement: object) => void;
|
||||
instructionFn?: (
|
||||
instructionValue: string,
|
||||
instructionName: string,
|
||||
parentElement: string
|
||||
) => void;
|
||||
cdataFn?: (value: string, parentElement: object) => void;
|
||||
commentFn?: (value: string, parentElement: object) => void;
|
||||
textFn?: (value: string, parentElement: object) => void;
|
||||
instructionNameFn?: (
|
||||
instructionName: string,
|
||||
instructionValue: string,
|
||||
parentElement: string
|
||||
) => void;
|
||||
elementNameFn?: (value: string, parentElement: object) => void;
|
||||
attributeNameFn?: (
|
||||
attributeName: string,
|
||||
attributeValue: string,
|
||||
parentElement: string
|
||||
) => void;
|
||||
attributeValueFn?: (
|
||||
attributeValue: string,
|
||||
attributeName: string,
|
||||
parentElement: string
|
||||
) => void;
|
||||
attributesFn?: (value: string, parentElement: string) => void;
|
||||
}
|
||||
|
||||
interface JS2XML extends ChangingKeyNames, IgnoreOptions {
|
||||
spaces?: number | string
|
||||
compact?: boolean
|
||||
indentText?: boolean
|
||||
indentCdata?: boolean
|
||||
indentAttributes?: boolean
|
||||
indentInstruction?: boolean
|
||||
fullTagEmptyElement?: boolean
|
||||
noQuotesForNativeAttributes?: boolean
|
||||
doctypeFn?: (value: string, currentElementName: string, currentElementObj: object) => void;
|
||||
instructionFn?: (
|
||||
instructionValue: string,
|
||||
instructionName: string,
|
||||
currentElementName: string,
|
||||
currentElementObj: object
|
||||
) => void;
|
||||
cdataFn?: (value: string, currentElementName: string, currentElementObj: object) => void;
|
||||
commentFn?: (value: string, currentElementName: string, currentElementObj: object) => void;
|
||||
textFn?: (value: string, currentElementName: string, currentElementObj: object) => void;
|
||||
instructionNameFn?: (
|
||||
instructionName: string,
|
||||
instructionValue: string,
|
||||
currentElementName: string,
|
||||
currentElementObj: object
|
||||
) => void;
|
||||
elementNameFn?: (value: string, currentElementName: string, currentElementObj: object) => void;
|
||||
attributeNameFn?: (
|
||||
attributeName: string,
|
||||
attributeValue: string,
|
||||
currentElementName: string,
|
||||
currentElementObj: object
|
||||
) => void;
|
||||
attributeValueFn?: (
|
||||
attributeValue: string,
|
||||
attributeName: string,
|
||||
currentElementName: string,
|
||||
currentElementObj: object
|
||||
) => void;
|
||||
attributesFn?: (value: string, currentElementName: string, currentElementObj: object) => void;
|
||||
fullTagEmptyElementFn?: (currentElementName: string, currentElementObj: object) => void;
|
||||
}
|
||||
|
||||
interface IgnoreOptions {
|
||||
ignoreDeclaration?: boolean
|
||||
ignoreInstruction?: boolean
|
||||
ignoreAttributes?: boolean
|
||||
ignoreComment?: boolean
|
||||
ignoreCdata?: boolean
|
||||
ignoreDoctype?: boolean
|
||||
ignoreText?: boolean
|
||||
}
|
||||
|
||||
interface ChangingKeyNames {
|
||||
declarationKey?: string
|
||||
instructionKey?: string
|
||||
attributesKey?: string
|
||||
textKey?: string
|
||||
cdataKey?: string
|
||||
doctypeKey?: string
|
||||
commentKey?: string
|
||||
parentKey?: string
|
||||
typeKey?: string
|
||||
nameKey?: string
|
||||
elementsKey?: string
|
||||
}
|
||||
}
|
||||
|
||||
export function js2xml(obj: Element | ElementCompact, options?: Options.JS2XML): string;
|
||||
export function json2xml(json: string, options?: Options.JS2XML): string;
|
||||
export function xml2json(xml: string, options?: Options.XML2JSON): string;
|
||||
export function xml2js(xml: string, options?: Options.XML2JS): Element | ElementCompact;
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"module": "commonjs",
|
||||
"noImplicitAny": true,
|
||||
"strictNullChecks": true,
|
||||
"noEmit": true
|
||||
},
|
||||
"files": [
|
||||
"./index.d.ts",
|
||||
"./xml-js-tests.ts"
|
||||
],
|
||||
"compileOnSave": false
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "xml-js",
|
||||
"main": "index.d.ts"
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
import { Element, ElementCompact } from './index'
|
||||
import * as convert from './index'
|
||||
|
||||
// Declaration
|
||||
const declarationCompact1: ElementCompact = { _declaration: { _attributes: { version: 2 } }};
|
||||
const declarationCompact2: ElementCompact = { _declaration: { _attributes: { version: '1.0', encoding: 'utf-8', standalone: 'yes' }}};
|
||||
const declaration1: Element = { declaration: { }};
|
||||
const declaration2: Element = { declaration: { attributes: { version: '1.0', encoding: 'utf-8', standalone: 'yes', }}};
|
||||
|
||||
// Processing Instruction
|
||||
const instructionCompact: ElementCompact = { _instruction: { go: 'there' }};
|
||||
const instruction: Element = { elements:[{ type: 'instruction', name: 'go', instruction: 'there' }]};
|
||||
|
||||
// Comment
|
||||
const commentCompact: ElementCompact = { _comment : 'Hello, World!' };
|
||||
const comment: Element = { elements: [{ type: 'comment', comment: 'Hello, World!' }]};
|
||||
|
||||
// CDATA
|
||||
const cdataCompact: ElementCompact = { _cdata: '<foo></bar>' };
|
||||
const cdata: Element = { elements : [{ type: 'cdata', cdata: '<foo></bar>' }]};
|
||||
|
||||
// Element
|
||||
const elementCompact1: ElementCompact = { a: {} };
|
||||
const element1: Element = { elements:[{ type: 'element', name: 'a' }]};
|
||||
|
||||
const elementCompact2: ElementCompact = { a: { _attributes: { x: '1.234', y:'It\'s', z: undefined }}};
|
||||
const element2: Element = { elements: [{ type: 'element', name: 'a', attributes: { x: '1.234', y: 'It\'s', z: undefined }}]};
|
||||
|
||||
const elementCompact3: ElementCompact = { a: { _text: ' Hi ' }};
|
||||
const element3: Element = { elements:[{ type: 'element', name: 'a', elements: [{ type: 'text', text: ' Hi ' }]}]};
|
||||
|
||||
const elementCompact4: ElementCompact = { a: {}, b: {} };
|
||||
const element4: Element = { elements:[{ type: 'element', name: 'a' }, { type: 'element', name: 'b' }]};
|
||||
|
||||
const elementCompact5: ElementCompact = { a: { b: {} }};
|
||||
const element5: Element = { elements: [{ type: 'element', name: 'a', elements: [{ type: 'element', name: 'b' }]}]};
|
||||
|
||||
const xml = `
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<note importance="high" logged="true">
|
||||
<title>Happy</title>
|
||||
<todo>Work</todo>
|
||||
<todo>Play</todo>
|
||||
</note>`;
|
||||
|
||||
// xml2js
|
||||
let jsResult1: any = convert.xml2js(xml, {compact:true});
|
||||
let jsResult2: any = convert.xml2js(xml, {compact:false});
|
||||
|
||||
// xml2json
|
||||
let jsonResult1: string = convert.xml2json(xml, {compact:true, spaces:4});
|
||||
let jsonResult2: string = convert.xml2json(xml, {compact:false});
|
||||
|
||||
// js2xml
|
||||
let xmlResult1: string = convert.js2xml({a:{}}, { compact:true, spaces:4});
|
||||
let xmlResult2: string = convert.js2xml({elements:[{type:'element', name:'a'}]}, {compact:false});
|
||||
|
||||
// json2xml
|
||||
let xmlResult3: string = convert.json2xml('{"a":{}}', { compact:true, spaces:4});
|
||||
let xmlResult4: string = convert.json2xml('{"elements":[{"type":"element","name":"a"}]}', {compact:false});
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const UnminifiedWebpackPlugin = require('unminified-webpack-plugin');
|
||||
|
||||
module.exports = {
|
||||
entry: {
|
||||
'dist': './lib/index.js',
|
||||
'doc': './lib/index.js'
|
||||
},
|
||||
output: {
|
||||
path: path.resolve(__dirname, '.'),
|
||||
filename: '[name]/xml-js.min.js',
|
||||
libraryTarget: 'window',
|
||||
// library: 'xmljs' // don't specify this
|
||||
},
|
||||
// module: {
|
||||
// rules: [
|
||||
// {
|
||||
// test: /\.(js)$/,
|
||||
// use: 'babel-loader'
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
plugins: [
|
||||
new webpack.optimize.UglifyJsPlugin(),
|
||||
new UnminifiedWebpackPlugin()
|
||||
]
|
||||
}
|
||||
Reference in new issue
Block a user