You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+49-29Lines changed: 49 additions & 29 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -60,26 +60,28 @@ Written purely in JavaScript which means it can be used in Node environment and
60
60
61
61
***Typings Info Included**:
62
62
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).
64
64
65
65
## Compact vs Non-Compact
66
66
67
67
Most XML to JSON converters (including online converters) convert `<a/>` to some compact output like `{"a":{}}`
68
68
instead of non-compact output like `{"elements":[{"type":"element","name":"a"}]}`.
69
69
70
70
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"}}]`.
75
77
76
78
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.
77
79
78
80
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.
79
81
80
82
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.
81
83
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.
83
85
84
86
Tip: You can reduce the output size by using shorter [key names](#options-for-changing-key-names).
85
87
@@ -164,7 +166,7 @@ The below options are applicable for both `js2xml()` and `json2xml()` functions.
164
166
|:----------------------|:--------|:------------|
165
167
|`spaces`|`0`| Number of spaces to be used for indenting XML output. Passing characters like `' '` or `'\t'` are also accepted. |
166
168
|`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 |
168
170
|`fullTagEmptyElement`|`false`| Whether to produce element without sub-elements as full tag pairs `<a></a>` rather than self closing tag `<a/>`. |
169
171
|`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)|
170
172
|`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
237
239
238
240
Two default values mean the first is used for *non-compact* output and the second is for *compact* output.
239
241
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'}`
241
245
> to make it more consistent and easier for your client code to go through the contents of text, cdata, and comment.
242
246
243
247
## Options for Custom Processing Functions
244
248
245
249
For XML → JS object / JSON, following custom callback functions can be supplied:
246
250
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) {returnval.replace('foo:','').toUpperCase();}};
|`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();}}`. |
259
271
260
272
For JS object / JSON → XML, following custom callback functions can be supplied:
261
273
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 +'';}};
|`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) {returnval.toUpperCase();}`. |
285
+
| `instructionFn` | `(instructionValue, instructionName, currentElementName, currentElementObj)` | To perform additional processing for content of Processing Instruction value. For example, `{instructionFn:function(val) {returnval.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) {returnval.toUpperCase();}}`. |
287
+
| `commentFn` | `(value, currentElementName, currentElementObj)` | To perform additional processing for comments. For example, `{commentFn:function(val) {returnval.toUpperCase();}}`. |
288
+
| `textFn` | `(value, currentElementName, currentElementObj)` | To perform additional processing for texts inside elements. For example, `{textFn:function(val) {returnval.toUpperCase();}}`. |
289
+
| `instructionNameFn` | `(instructionName, instructionValue, currentElementName, currentElementObj)` | To perform additional processing for Processing Instruction name. For example, `{instructionNameFn:function(val) {returnval.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) {returnval.toUpperCase();}}`. |
291
+
| `attributeNameFn` | `(attributeName, attributeValue, currentElementName, currentElementObj)` | To perform additional processing for attribute name. For example, `{attributeNameFn:function(val) {returnval.toUpperCase();}}`. |
292
+
| `attributeValueFn` | `(attributeValue, attributeName, currentElementName, currentElementObj)` | To perform additional processing for attributeValue. For example, `{attributeValueFn:function(val) {returnval.toUpperCase();}}`. |
293
+
| `attributesFn` | `(value, currentElementName, currentElementObj)` | To perform additional processing for attributes object. For example, `{attributesFn:function(val) {returnval.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'}}`. |
0 commit comments