Stdlib.xmlToObject

Discussion of the xtools Toolkit

Moderators: Tom, Kukurykus

myranalis

Stdlib.xmlToObject

Post by myranalis »

I am trying to parse the PSE6 action xml (below) using Stdlib.xmlToObject but I don't seem to get anything under the 'global' object. global.name just returns blank. Can someone point me in the right direction?

Code: Select all<?xml version="1.0" encoding="UTF-8"?>
<PSEContent xmlns="http://ns.adobe.com/PSEContent/1.0/">
<global>

  <name id="Name" value="ActionName" localize="true" />
 
  <type value="effect" />

  <typecategory id="TypeCat" value="ActionCategory" localize="true" />
 
  </global>
</PSEContent>
Mike Hale

Stdlib.xmlToObject

Post by Mike Hale »

My guess is X did not intend that function to parse xml with attributes. I imagine that he has other scripts for that purpose. This function looks to me like a helper function to convert simple xml to script parameter objects similar to the one in Adobe's Image Procssor.jsx.

I know that he is really busy with a project he is working on, so in the meantime here is my fix to that function until he has time to respond.

Code: Select allvar Stdlib = {};
Stdlib.xmlToObject = function(xml, obj, parent) {
  if (xml.constructor == String) {
    xml = new XML(xml);
  } else if (xml instanceof XML) {
    xml = xml.copy();
  } else {
    Error.runtimeError(2, "xml");
  }

  xml.normalize();

  if (xml.hasSimpleContent()) {
    var str = xml.toString();
    if (parent) {
      parent[xml.localName()] = str;
    }
    return str;
  }

  var type;
  // do the eval because of non-CS/2 syntax
  eval('type = xml.@type.toString()');

  if (type == 'array') {
    obj = [];
  } else {
    obj = {};
  }

  var els = xml.elements();
  var len = els.length();
  if (len > 0) {
    for (var i = 0; i < len; i++) {
      var child = els;
      var val = '';
      var idx = (type == 'array') ? i : child.localName();

      if (child.hasComplexContent()) {
        val = Stdlib.xmlToObject(child);
      }

      if (child.hasSimpleContent()) {
        var ctype;
        // do the eval because of non-CS/2 syntax
        eval('ctype = child.@type.toString()');
        val = child.text().toString();

        if (val) {
          if (ctype == 'number') {
            val = Number(val);
          }
          if (ctype == 'boolean') {
            val = val.toLowerCase() == 'true';
          }
        }
      }

      obj[idx] = val;
     //mlh edit
     if(child.attributes().length()>0){
        obj[idx] = {};
        for( var a = 0;a<child.attributes().length();a++ ){
           obj[idx][child.attributes()[a].localName().toString()] = child.attributes()[a].toString();
      }
   }
   // mlh edit ends
    }
  } else {
    obj = xml.toString();
  }

  if (parent) {
    parent[xml.localName()] = obj;
  }

  return obj;
};
var ax = '<?xml version="1.0" encoding="UTF-8"?><PSEContent xmlns="http://ns.adobe.com/PSEContent/1.0/"><global><name id="Name" value="ActionName" localize="true" /><type value="effect" /><typecategory id="TypeCat" value="ActionCategory" localize="true" /></global></PSEContent>';
var myXml  = new XML(ax);
var myObj = Stdlib.xmlToObject(myXml);
alert( myObj.global.name.value )
myranalis

Stdlib.xmlToObject

Post by myranalis »

Thanks Mike. Its not working quite right yet though. Even if I use

Code: Select allvar pXML = Stdlib.readXMLFile(this.SCRIPTS_FOLDER + C_XML_PSE6)

to read it into a plain XML object I can't use pXML.global to retrieve that element. So I thought maybe something was badly formed in the XML, but I can't see anything??
Mike Hale

Stdlib.xmlToObject

Post by Mike Hale »

Are you using a different xml or the one you posted? It works for me with the xml you posted as either a string or from a file. I saved your sample xml to the Desktop as text.xml



Code: Select allvar Stdlib = {};
Stdlib.xmlToObject = function(xml, obj, parent) {
  if (xml.constructor == String) {
    xml = new XML(xml);
  } else if (xml instanceof XML) {
    xml = xml.copy();
  } else {
    Error.runtimeError(2, "xml");
  }

  xml.normalize();

  if (xml.hasSimpleContent()) {
    var str = xml.toString();
    if (parent) {
      parent[xml.localName()] = str;
    }
    return str;
  }

  var type;
  // do the eval because of non-CS/2 syntax
  eval('type = xml.@type.toString()');

  if (type == 'array') {
    obj = [];
  } else {
    obj = {};
  }

  var els = xml.elements();
  var len = els.length();
  if (len > 0) {
    for (var i = 0; i < len; i++) {
      var child = els;
      var val = '';
      var idx = (type == 'array') ? i : child.localName();

      if (child.hasComplexContent()) {
        val = Stdlib.xmlToObject(child);
      }

      if (child.hasSimpleContent()) {
        var ctype;
        // do the eval because of non-CS/2 syntax
        eval('ctype = child.@type.toString()');
        val = child.text().toString();

        if (val) {
          if (ctype == 'number') {
            val = Number(val);
          }
          if (ctype == 'boolean') {
            val = val.toLowerCase() == 'true';
          }
        }
      }

      obj[idx] = val;
     //mlh edit
     if(child.attributes().length()>0){
        obj[idx] = {};
        for( var a = 0;a<child.attributes().length();a++ ){
           obj[idx][child.attributes()[a].localName().toString()] = child.attributes()[a].toString();
      }
   }
   // mlh edit ends
    }
  } else {
    obj = xml.toString();
  }

  if (parent) {
    parent[xml.localName()] = obj;
  }

  return obj;
};
Stdlib.readXMLFile = function(fptr) {
  var file = Stdlib.convertFptr(fptr);
  if (!file.exists) {
    Error.runtimeError(48); // File/Folder does not exist
  }

  file.encoding = "UTF8";
  file.lineFeed = "unix";
  file.open("r", "TEXT", "????");
  var str = file.read();
  file.close();

  return new XML(str);
};
Stdlib.convertFptr = function(fptr) {
  var f;
  if (fptr.constructor == String) {
    f = File(fptr);

  } else if (fptr instanceof File || fptr instanceof Folder) {
    f = fptr;

  } else {
    Error.runtimeError(19, "fptr");
  }
  return f;
};

var myXml  = Stdlib.readXMLFile('~/Desktop/test.xml');
var myObj = Stdlib.xmlToObject(myXml);
alert( myObj.global.name.id );// alerts 'Name'
alert( myObj.global.typecategory.value );alerts 'ActionCategory'
myranalis

Stdlib.xmlToObject

Post by myranalis »

It is comming from a file. Trying to upload the actual file as an attachment...
myranalis

Stdlib.xmlToObject

Post by myranalis »

For what it is worth.. here's my actual test code just reading into an XML object. 'pGlobal' returns nothing, and the alert shows nothing.

Code: Select allvar pXMLFile = new File('~/Desktop/PSE6.xml');
var pXML = Stdlib.readXMLFile(pXMLFile);
var pGlobal = pXML.global

alert(pGlobal.name.@value)
Mike Hale

Stdlib.xmlToObject

Post by Mike Hale »

As I understand it, if a namespace is defined in the XML you have to use that Namespace in the elements name's.

Code: Select allvar pXMLFile = new File('~/Desktop/PSE6.xml');
var pXML = Stdlib.readXMLFile(pXMLFile);
var ns = new Namespace ("http://ns.adobe.com/PSEContent/1.0/");
var pGlobal = new XML(pXML.ns::global);

alert(pGlobal.ns::name.@value);

Did you want to use the XML in the file as XML or as an Object? When I used the zip you uploaded the alerts in xml to object code still work for me. Maybe I didn't construct the object as you expected.
Mike Hale

Stdlib.xmlToObject

Post by Mike Hale »

One other question, where are you running these snippets?
myranalis

Stdlib.xmlToObject

Post by myranalis »

Running in the ESTK at the moment, although PS is the real aim

I'm happy to manipulate the XML object directly if I can that to work. I just want to update the name and category and write it out to a new file.

I'll try adding your namespace code and see how it goes.
Mike Hale

Stdlib.xmlToObject

Post by Mike Hale »

This may not be the best way, but it makes sense to me to edit the xml as a whole. So I would not break out the global child.

Note I don't know any thing about PE6 actions so I may have edited the wrong attributes, but the concept is valid.

Code: Select all// @include '/C/Program Files/Adobe/xtools/xlib/stdlib.js'
var pXMLFile = new File('~/Desktop/PSE6.xml');
var pXML = Stdlib.readXMLFile(pXMLFile);
var ns = new Namespace ("http://ns.adobe.com/PSEContent/1.0/");
pXML.ns::global.ns::name.@value = 'newActionName';
pXML.ns::global.ns::typecategory.@value = 'newActionCategory';
Stdlib.writeXMLFile('~/Desktop/test.xml', pXML);// written to a different file for testing
var myXML = Stdlib.readXMLFile('~/Desktop/test.xml');
alert( myXML.ns::global.ns::name.@value );