Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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

remove _text #53

Open
Nickx58 opened this issue Feb 27, 2018 · 10 comments
Open

remove _text #53

Nickx58 opened this issue Feb 27, 2018 · 10 comments

Comments

@Nickx58
Copy link

Nickx58 commented Feb 27, 2018

"title": {
"_text": "You Won't Believe What These 31 Oscar Winners Look Like Now"
},

@gpender
Copy link

gpender commented Apr 20, 2018

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){}
}

@euberdeveloper
Copy link

euberdeveloper commented May 16, 2018

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
 }
}

@gpender
Copy link

gpender commented May 16, 2018

Good call!

@mickadoua
Copy link

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

@egoarka
Copy link

egoarka commented Mar 18, 2019

@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) {}
};

@JamesCoyle
Copy link

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.

@paul-uz
Copy link

paul-uz commented May 20, 2022

@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

@quyendqmz
Copy link

Yes, removeJsonTextAttribute function does not work when nativeType: true.
Is there any solution?

@moldypenguins
Copy link

moldypenguins commented Oct 26, 2022

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) {}
};

@JCLedesmaDev
Copy link

JCLedesmaDev commented Nov 4, 2022

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.


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

codigo
options
node_modules

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants