Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add current element to elementNameFn callback. Add new callback endElementFn. #162

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ Most converters will produce compact output like this `{a:[{_:{x:"1"}},{_:{x:"3"
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.
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.
Expand Down Expand Up @@ -240,7 +240,7 @@ Two default values mean the first is used for *non-compact* output and the secon

> **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'}`
> **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
Expand All @@ -263,10 +263,11 @@ console.log(result); // {"NAME":{"_text":"Ali"},"BAR:AGE":{"_text":"30"}}
| `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();}}`. |
| `elementNameFn` | `(value, parentElement, currentElement)` | 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();}}`. |
| `endElementFn` | `(name, parentElement, currentElement)` | To perform additional processing for current object when it's ends. For example, `{endElementFn: function(name, parentElement) { parentElement.name.toUpperCase(); }}`. |

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

Expand Down
9 changes: 5 additions & 4 deletions lib/xml2js.js
Original file line number Diff line number Diff line change
Expand Up @@ -198,17 +198,16 @@ function onInstruction(instruction) {
}

function onStartElement(name, attributes) {
var element;
var element = {};
if (typeof name === 'object') {
attributes = name.attributes;
name = name.name;
}
attributes = manipulateAttributes(attributes);
if ('elementNameFn' in options) {
name = options.elementNameFn(name, currentElement);
name = options.elementNameFn(name, currentElement, element);
}
if (options.compact) {
element = {};
if (!options.ignoreAttributes && attributes && Object.keys(attributes).length) {
element[options.attributesKey] = {};
var key;
Expand Down Expand Up @@ -236,7 +235,6 @@ function onStartElement(name, attributes) {
if (!currentElement[options.elementsKey]) {
currentElement[options.elementsKey] = [];
}
element = {};
element[options.typeKey] = 'element';
element[options.nameKey] = name;
if (!options.ignoreAttributes && attributes && Object.keys(attributes).length) {
Expand Down Expand Up @@ -282,6 +280,9 @@ function onComment(comment) {

function onEndElement(name) {
var parentElement = currentElement[options.parentKey];
if ('endElementFn' in options) {
options.endElementFn(name, parentElement, currentElement);
}
if (!options.addParent) {
delete currentElement[options.parentKey];
}
Expand Down
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@
"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"
},
Expand Down
3 changes: 2 additions & 1 deletion types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ declare namespace Options {
instructionValue: string,
parentElement: string
) => void;
elementNameFn?: (value: string, parentElement: object) => void;
elementNameFn?: (value: string, parentElement: object, currentElement: object) => void;
attributeNameFn?: (
attributeName: string,
attributeValue: string,
Expand All @@ -79,6 +79,7 @@ declare namespace Options {
parentElement: string
) => void;
attributesFn?: (value: string, parentElement: string) => void;
endElementFn?: (value: string, parentElement: object, currentElement: object) => void;
}

interface JS2XML extends ChangingKeyNames, IgnoreOptions {
Expand Down