Skip to content

Commit ddb6a5f

Browse files
committed
Updated readme and run npm audit fix.
1 parent d27442a commit ddb6a5f

7 files changed

Lines changed: 574 additions & 923 deletions

File tree

README.md

Lines changed: 49 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -60,26 +60,28 @@ Written purely in JavaScript which means it can be used in Node environment and
6060

6161
* **Typings Info Included**:
6262
Support type checking and code suggestion via intellisense.
63-
Thanks to the wonderful efforts by [DenisCarriere](https://github.com/DenisCarriere)
63+
Thanks to the wonderful efforts by [DenisCarriere](https://github.com/DenisCarriere).
6464

6565
## Compact vs Non-Compact
6666

6767
Most XML to JSON converters (including online converters) convert `<a/>` to some compact output like `{"a":{}}`
6868
instead of non-compact output like `{"elements":[{"type":"element","name":"a"}]}`.
6969

7070
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.
71-
Most converters will produce compact output like `{a:[{_:{x:"1"}},{_:{x:"3"}}], b:{_:{x:"2"}}}`,
72-
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"/>`
73-
which has not preserved the order of elements! There is an inherent limitation in the compact representation
74-
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"}}]`.
71+
Most converters will produce compact output like this `{a:[{_:{x:"1"}},{_:{x:"3"}}], b:{_:{x:"2"}}}`,
72+
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"/>`
73+
which has not preserved the order of elements!
74+
75+
The reason behind this behavior is due to the inherent limitation in the compact representation.
76+
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"}}]`.
7577

7678
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.
7779

7880
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.
7981

8082
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.
8183
This library provides both options. Use `{compact: false}` if you are not sure because it preserves everything;
82-
otherwise use `{compact: true}` if you want to save space and you don't care about mixing elements of same type and losing their order.
84+
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.
8385

8486
Tip: You can reduce the output size by using shorter [key names](#options-for-changing-key-names).
8587

@@ -164,7 +166,7 @@ The below options are applicable for both `js2xml()` and `json2xml()` functions.
164166
|:----------------------|:--------|:------------|
165167
| `spaces` | `0` | Number of spaces to be used for indenting XML output. Passing characters like `' '` or `'\t'` are also accepted. |
166168
| `compact` | `false` | Whether the *input* object is in compact form or not. By default, input is expected to be in non-compact form. |
167-
| | | 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 |
169+
| | | 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 |
168170
| `fullTagEmptyElement` | `false` | Whether to produce element without sub-elements as full tag pairs `<a></a>` rather than self closing tag `<a/>`. |
169171
| `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) |
170172
| `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). |
@@ -237,41 +239,59 @@ To change default key names in the output object or the default key names assume
237239

238240
Two default values mean the first is used for *non-compact* output and the second is for *compact* output.
239241

240-
> **TIP**: You probably want to set `{textKey: 'value', cdataKey: 'value', commentKey: 'value'}` for *non-compact* output
242+
> **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.
243+
244+
> **TIP**: In non-compact mode, you probably want to set `{textKey: 'value', cdataKey: 'value', commentKey: 'value'}`
241245
> to make it more consistent and easier for your client code to go through the contents of text, cdata, and comment.
242246
243247
## Options for Custom Processing Functions
244248

245249
For XML → JS object / JSON, following custom callback functions can be supplied:
246250

251+
```js
252+
var convert = require('xml-js');
253+
var xml = '<foo:Name>Ali</Name> <bar:Age>30</bar:Age>';
254+
var options = {compact: true, elementNameFn: function(val) {return val.replace('foo:','').toUpperCase();}};
255+
var result = convert.xml2json(xml, options);
256+
console.log(result); // {"NAME":{"_text":"Ali"},"BAR:AGE":{"_text":"30"}}
257+
```
258+
247259
| Option | Signature | Description |
248260
|:--------------------|:----------|:------------|
249-
| `doctypeFn` | `(value, parentElement)` | To perform additional processing for DOCTYPE. For example, `{doctypeFn: function(val) {return val.toUpperCase();}` |
250-
| `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. |
251-
| `cdataFn` | `(value, parentElement)` | To perform additional processing for CData. For example, `{cdataFn: function(val) {return val.toUpperCase();}`. |
252-
| `commentFn` | `(value, parentElement)` | To perform additional processing for comments. For example, `{commentFn: function(val) {return val.toUpperCase();}`. |
253-
| `textFn` | `(value, parentElement)` | To perform additional processing for texts inside elements. For example, `{textFn: function(val) {return val.toUpperCase();}`. |
254-
| `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. |
255-
| `elementNameFn` | `(value, parentElement)` | To perform additional processing for element name. For example, `{elementNameFn: function(val) {return val.toUpperCase();}`. |
256-
| `attributeNameFn` | `(attributeName, attributeValue, parentElement)` | To perform additional processing for attribute name. For example, `{attributeNameFn: function(val) {return val.toUpperCase();}`. |
257-
| `attributeValueFn` | `(attributeValue, attributeName, parentElement)` | To perform additional processing for attributeValue. For example, `{attributeValueFn: function(val) {return val.toUpperCase();}`. |
258-
| `attributesFn` | `(value, parentElement)` | To perform additional processing for attributes object. For example, `{attributesFn: function(val) {return val.toUpperCase();}`. |
261+
| `doctypeFn` | `(value, parentElement)` | To perform additional processing for DOCTYPE. For example, `{doctypeFn: function(val) {return val.toUpperCase();}}` |
262+
| `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. |
263+
| `cdataFn` | `(value, parentElement)` | To perform additional processing for CData. For example, `{cdataFn: function(val) {return val.toUpperCase();}}`. |
264+
| `commentFn` | `(value, parentElement)` | To perform additional processing for comments. For example, `{commentFn: function(val) {return val.toUpperCase();}}`. |
265+
| `textFn` | `(value, parentElement)` | To perform additional processing for texts inside elements. For example, `{textFn: function(val) {return val.toUpperCase();}}`. |
266+
| `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. |
267+
| `elementNameFn` | `(value, parentElement)` | To perform additional processing for element name. For example, `{elementNameFn: function(val) {return val.toUpperCase();}}`. |
268+
| `attributeNameFn` | `(attributeName, attributeValue, parentElement)` | To perform additional processing for attribute name. For example, `{attributeNameFn: function(val) {return val.toUpperCase();}}`. |
269+
| `attributeValueFn` | `(attributeValue, attributeName, parentElement)` | To perform additional processing for attributeValue. For example, `{attributeValueFn: function(val) {return val.toUpperCase();}}`. |
270+
| `attributesFn` | `(value, parentElement)` | To perform additional processing for attributes object. For example, `{attributesFn: function(val) {return val.toUpperCase();}}`. |
259271

260272
For JS object / JSON → XML, following custom callback functions can be supplied:
261273

274+
```js
275+
var convert = require('xml-js');
276+
var json = '{"name":{"_text":"Ali"},"age":{"_text":"30"}}';
277+
var options = {compact: true, textFn: function(val, elementName) {return elementName === 'age'? val + '';}};
278+
var result = convert.json2xml(json, options);
279+
console.log(result); // <foo:Name>Ali</Name> <bar:Age>30</bar:Age>
280+
```
281+
262282
| Option | Signature | Description |
263283
|:--------------------|:----------|:------------|
264-
| `doctypeFn` | `(value, currentElementName, currentElementObj)` | To perform additional processing for DOCTYPE. For example, `{doctypeFn: function(val) {return val.toUpperCase();}` |
265-
| `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. |
266-
| `cdataFn` | `(value, currentElementName, currentElementObj)` | To perform additional processing for CData. For example, `{cdataFn: function(val) {return val.toUpperCase();}`. |
267-
| `commentFn` | `(value, currentElementName, currentElementObj)` | To perform additional processing for comments. For example, `{commentFn: function(val) {return val.toUpperCase();}`. |
268-
| `textFn` | `(value, currentElementName, currentElementObj)` | To perform additional processing for texts inside elements. For example, `{textFn: function(val) {return val.toUpperCase();}`. |
269-
| `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. |
270-
| `elementNameFn` | `(value, currentElementName, currentElementObj)` | To perform additional processing for element name. For example, `{elementNameFn: function(val) {return val.toUpperCase();}`. |
271-
| `attributeNameFn` | `(attributeName, attributeValue, currentElementName, currentElementObj)` | To perform additional processing for attribute name. For example, `{attributeNameFn: function(val) {return val.toUpperCase();}`. |
272-
| `attributeValueFn` | `(attributeValue, attributeName, currentElementName, currentElementObj)` | To perform additional processing for attributeValue. For example, `{attributeValueFn: function(val) {return val.toUpperCase();}`. |
273-
| `attributesFn` | `(value, currentElementName, currentElementObj)` | To perform additional processing for attributes object. For example, `{attributesFn: function(val) {return val.toUpperCase();}`. |
274-
| `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'}`. |
284+
| `doctypeFn` | `(value, currentElementName, currentElementObj)` | To perform additional processing for DOCTYPE. For example, `{doctypeFn: function(val) {return val.toUpperCase();}`. |
285+
| `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. |
286+
| `cdataFn` | `(value, currentElementName, currentElementObj)` | To perform additional processing for CData. For example, `{cdataFn: function(val) {return val.toUpperCase();}}`. |
287+
| `commentFn` | `(value, currentElementName, currentElementObj)` | To perform additional processing for comments. For example, `{commentFn: function(val) {return val.toUpperCase();}}`. |
288+
| `textFn` | `(value, currentElementName, currentElementObj)` | To perform additional processing for texts inside elements. For example, `{textFn: function(val) {return val.toUpperCase();}}`. |
289+
| `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. |
290+
| `elementNameFn` | `(value, currentElementName, currentElementObj)` | To perform additional processing for element name. For example, `{elementNameFn: function(val) {return val.toUpperCase();}}`. |
291+
| `attributeNameFn` | `(attributeName, attributeValue, currentElementName, currentElementObj)` | To perform additional processing for attribute name. For example, `{attributeNameFn: function(val) {return val.toUpperCase();}}`. |
292+
| `attributeValueFn` | `(attributeValue, attributeName, currentElementName, currentElementObj)` | To perform additional processing for attributeValue. For example, `{attributeValueFn: function(val) {return val.toUpperCase();}}`. |
293+
| `attributesFn` | `(value, currentElementName, currentElementObj)` | To perform additional processing for attributes object. For example, `{attributesFn: function(val) {return val.toUpperCase();}}`. |
294+
| `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'}}`. |
275295
276296
# Command Line
277297

0 commit comments

Comments
 (0)