xml-js
xml-js copied to clipboard
remove _text
"title": { "_text": "You Won't Believe What These 31 Oscar Winners Look Like Now" },
Try adding a textFn callback
convert.xml2json(xmlMsg,{textFn:RemoveJsonTextAttribute});
function RemoveJsonTextAttribute(value,parentElement){ try{ var keyNo = Object.keys(parentElement._parent).length; var keyName = Object.keys(parentElement._parent)[keyNo-1]; parentElement._parent[keyName] = value; } catch(e){} }
It is not completely right: it does not works for not string values
if I have this xml:
<person>
<age>18</age>
<name>Mario</name>
<diplomated>false</diplomated>
<person>
and this options:
var options = {
compact: true,
trim: true,
nativeType: true,
ignoreDeclaration: true,
ignoreInstruction: true,
ignoreAttributes: true,
ignoreComment: true,
ignoreCdata: true,
ignoreDoctype: true,
textFn: removeJsonTextAttribute
};
with nativeType set at true values like "true" or "12" will be true and 12, but in the lib this happens before the calling of textFn, wich is made by the external module sax. So textFn will manage only elements with string value if nativeType is set at true.
The result would be:
{
person: {
age: { _text: 18; },
name: "mario",
diplomated: { _text: false; }
}
}
if native type would have been false the result would be:
{
person: {
age: "18",
name: "mario",
diplomated: "false"
}
}
THE SOLUTION if you want both nativeType: true and _text removed I found this solution:
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;
}
var removeJsonTextAttribute = function(value, parentElement) {
try {
var keyNo = Object.keys(parentElement._parent).length;
var keyName = Object.keys(parentElement._parent)[keyNo - 1];
parentElement._parent[keyName] = nativeType(value);
} catch (e) {}
}
var options = {
compact: true,
trim: true,
ignoreDeclaration: true,
ignoreInstruction: true,
ignoreAttributes: true,
ignoreComment: true,
ignoreCdata: true,
ignoreDoctype: true,
textFn: removeJsonTextAttribute
};
//Then use the xml2js function or xml2json function
explained: I copied the function that convert string in its native type from the lib, I copied the remove text function from gpender but I added the nativeType function at the value. I removed the nativeType: true option. So, because nativeType is false, the not string types won't be ignored by the textFn functions and _text will be removed for them too. The textFn function will convert the string to its native type so the result is:
{
person: {
age: 18,
name: "mario",
diplomated: false
}
}
Good call!
hello, some issues with this method,
<Dossier><Objectif>obj1</Objectif><Objectif>obj2</Objectif><Objectif>obj3</Objectif></Dossier>
will return
{Objectif: 'obj3' }
i think parentElement._parent[keyName] = nativeType(value)
erase the last value
@mickadoua
this snippet solve this problem
const removeJsonTextAttribute = function(value, parentElement) {
try {
const parentOfParent = parentElement._parent;
const pOpKeys = Object.keys(parentElement._parent);
const keyNo = pOpKeys.length;
const keyName = pOpKeys[keyNo - 1];
const arrOfKey = parentElement._parent[keyName];
const arrOfKeyLen = arrOfKey.length;
if (arrOfKeyLen > 0) {
const arr = arrOfKey;
const arrIndex = arrOfKey.length - 1;
arr[arrIndex] = value;
} else {
parentElement._parent[keyName] = value;
}
} catch (e) {}
};
Is there a way to get this to completely remove tags like <example/>
where there is never anything in the object? I don't care about reproducing the XML as I'm just converting a third party XML API into JSON so it is easier to work with. The API sends empty tags when there is no information for that datapoint but that leaves my JSON full of those keys like example: {}
but I'd rather have example: null
or just not have it at all.
@mickadoua
this snippet solve this problem
const removeJsonTextAttribute = function(value, parentElement) { try { const parentOfParent = parentElement._parent; const pOpKeys = Object.keys(parentElement._parent); const keyNo = pOpKeys.length; const keyName = pOpKeys[keyNo - 1]; const arrOfKey = parentElement._parent[keyName]; const arrOfKeyLen = arrOfKey.length; if (arrOfKeyLen > 0) { const arr = arrOfKey; const arrIndex = arrOfKey.length - 1; arr[arrIndex] = value; } else { parentElement._parent[keyName] = value; } } catch (e) {} };
This does not work in combination with nativeType: true
Yes, removeJsonTextAttribute function does not work when nativeType: true. Is there any solution?
Yes, removeJsonTextAttribute function does not work when nativeType: true. Is there any solution?
Set nativeType in options to false and let the nativeType function handle converting the values
var options = {
compact: true,
nativeType: false,
textFn: removeJsonTextAttribute
};
const nativeType = function(value) {
let nValue = Number(value);
if (!isNaN(nValue)) {
return nValue;
}
let bValue = value.toLowerCase();
if (bValue === 'true') {
return true;
} else if (bValue === 'false') {
return false;
}
return value;
}
const removeJsonTextAttribute = function(value, parentElement) {
try {
const parentOfParent = parentElement._parent;
const pOpKeys = Object.keys(parentElement._parent);
const keyNo = pOpKeys.length;
const keyName = pOpKeys[keyNo - 1];
const arrOfKey = parentElement._parent[keyName];
const arrOfKeyLen = arrOfKey.length;
if (arrOfKeyLen > 0) {
const arr = arrOfKey;
const arrIndex = arrOfKey.length - 1;
arr[arrIndex] = value;
} else {
parentElement._parent[keyName] = nativeType(value);
}
} catch (e) {}
};
Is there a way to get this to completely remove tags like
<example/>
where there is never anything in the object? I don't care about reproducing the XML as I'm just converting a third party XML API into JSON so it is easier to work with. The API sends empty tags when there is no information for that datapoint but that leaves my JSON full of those keys likeexample: {}
but I'd rather haveexample: null
or just not have it at all.
I found the solution to solve the 'example: {} ' object problem, by directly modifying the library. For this, I went to node_modules, "xml-js" > lib > xmljs.js and on line 286, there is the "onEndElement" method. Here, add the following code:
if (typeof currentElement[name] === 'object' && Object.keys(currentElement[name]).length === 0) { currentElement[name] = options.defaultValue
I define that when a property comes with an empty object, I change the value of said property. In order to dynamically define the value to change to the options that are passed to them, I add a property called 'defaultValue' and pass the value in question