首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Google-Apps-Script将XML转换为JSON

Google-Apps-Script将XML转换为JSON
EN

Stack Overflow用户
提问于 2020-03-16 23:21:33
回答 2查看 711关注 0票数 0

我有一个XML字符串,如下所示:

'<ALEXA VER="0.9" URL="davidwalsh.name/" HOME="0" AID="="><SD TITLE="A" FLAGS="" HOST="davidwalsh.name"><TITLE TEXT="David Walsh Blog :: PHP, MySQL, CSS, Javascript, MooTools, and Everything Else"/><LINKSIN NUM="1102"/><SPEED TEXT="1421" PCT="51"/></SD><SD><POPULARITY URL="davidwalsh.name/" TEXT="7131"/><REACH RANK="5952"/><RANK DELTA="-1648"/></SD></ALEXA>'

我想把它转换成JSON格式:

代码语言:javascript
复制
  {
    "ALEXA":{
       "@attributes":{
          "VER":"0.9",
          "URL":"davidwalsh.name/",
          "HOME":"0",
          "AID":"="
       },
       "SD":[
          {
             "@attributes":{
                "TITLE":"A",
                "FLAGS":"",
                "HOST":"davidwalsh.name"
             },
             "TITLE":{
                "@attributes":{
                   "TEXT":"David Walsh Blog :: PHP, MySQL, CSS, Javascript, MooTools, and Everything Else"
                }
...

我已经找到了很多针对js的解决方案,但它们都不适用于google-apps-script。我还看到了这样一个问题:Parsing XML on a Google Apps script,但它并不完全符合我的情况:我喜欢将任何XML解析成JSON,而不仅仅是提供的示例。我已经找到了自己的解决方案(在答案中),但不确定它是否适合所有情况。

EN

回答 2

Stack Overflow用户

发布于 2020-03-16 23:21:33

我认为解决方案应该是一个递归函数。经过一些研究,我找到了David Walsh的this great code,并且能够采用它。这就是我要说的:

代码语言:javascript
复制
// Changes XML to JSON
// Original code: https://davidwalsh.name/convert-xml-json
function xmlToJson_(xml) {

  // Create the return object
  var obj = {};

  // get type
  var type = '';
  try { type = xml.getType(); } catch(e){}

  if (type == 'ELEMENT') {
    // do attributes
    var attributes = xml.getAttributes();
    if (attributes.length > 0) {
      obj["@attributes"] = {};
      for (var j = 0; j < attributes.length; j++) {
        var attribute = attributes[j];
        obj["@attributes"][attribute.getName()] = attribute.getValue();
      }
    }
  } else if (type == 'TEXT') {
    obj = xml.getValue();
  }

  // get children
  var elements = [];
  try { elements = xml.getAllContent(); } catch(e){}


  // do children
  if (elements.length > 0) {
    for(var i = 0; i < elements.length; i++) {
      var item = elements[i];

      var nodeName = false;
      try { nodeName = item.getName(); } catch(e){}

      if (nodeName)
      {
        if (typeof(obj[nodeName]) == "undefined") {
          obj[nodeName] = xmlToJson_(item);
        } else {
          if (typeof(obj[nodeName].push) == "undefined") {
            var old = obj[nodeName];
            obj[nodeName] = [];
            obj[nodeName].push(old);
          }
          obj[nodeName].push(xmlToJson_(item));
        }                
      }
    }
  }
  return obj;
};

我已经发布了示例on GitHub

用法:

代码语言:javascript
复制
  var xml = XmlService.parse(xmltext); 
  Logger.log(JSON.stringify(xmlToJson_(xml)));

参考资料:

票数 2
EN

Stack Overflow用户

发布于 2021-12-20 22:34:50

最初的答案对我不起作用。应用程序脚本XML API中可能有更改,但它不会包含没有子节点的文本内容。下面是我写的代码,看起来运行得很好。

请注意,它的输出方式与您提供的示例略有不同。我发现对于更广泛的用例,这可能是一种更一致的格式。我还发现,我所做的每件事都没有必要包含属性,这造成了混乱,所以我添加了一个不解析属性的版本。

如果包含属性,则输出遵循以下模式:

代码语言:javascript
复制
{foo:{attributes:{...},content:{...}}

要包括属性:

代码语言:javascript
复制
function xmlParse(element) {
  /*
   * Takes an XML element and returns an object containing its children or text
   * If children are present, recursively calls xmlTest() on them
   * 
   * If multiple children share a name, they are added as objects in an array
   * If children have unique names, they are simply added as keys
   * i.e. 
   * <foo><bar>one</bar><baz>two</baz></foo> === {foo: {bar: 'one', baz: 'two'}}
   * <foo><bar>one</bar><bar>two</bar></foo> === {foo: [{bar: 'one'},{bar: 'two'}]}
   */

  let obj = {}
  const rootName = element.getName();
  
  // Parse attributes
  const attributes = element.getAttributes();
  const attributesObj = {};

  for(const attribute of attributes) {
    attributesObj[attribute.getName()] = attribute.getValue();
  }

  obj[rootName] = {
    attributes: attributesObj,
    content: {}
  }

  const children = element.getChildren();
  const childNames = children.map(child => child.getName());

  if (children.length === 0) {
    // Base case - get text content if no children
    obj = {
      content: element.getText(),
      attributes: attributesObj
    }
  } else if (new Set(childNames).size !== childNames.length) {
    // If nonunique child names, add children as an array
    obj[rootName].content = [];
    for (const child of children) {
      if (child.getChildren().length === 0) {
        const childObj = {};
        childObj[child.getName()] = xmlParse(child);
        obj[rootName].content.push(childObj)
      } else {
        const childObj = xmlParse(child);
        obj[rootName].content.push(childObj)
      }
    }
  } else {
    // If unique child names, add children as keys
    obj[rootName].content = {};
    for (const child of children) {
      if (child.getChildren().length === 0) {
        obj[rootName].content[child.getName()] = xmlParse(child);
      } else {
        obj[rootName].content = xmlParse(child);
      }
    }
  }

  return obj;
}

不带属性:

代码语言:javascript
复制
function xmlParse(element) {
  /*
   * Takes an XML element and returns an object containing its children or text
   * If children are present, recursively calls xmlTest() on them
   * 
   * If multiple children share a name, they are added as objects in an array
   * If children have unique names, they are simply added as keys
   * i.e. 
   * <foo><bar>one</bar><baz>two</baz></foo> === {foo: {bar: 'one', baz: 'two'}}
   * <foo><bar>one</bar><bar>two</bar></foo> === {foo: [{bar: 'one'},{bar: 'two'}]}
   */

  let obj = {}
  const rootName = element.getName();

  const children = element.getChildren();
  const childNames = children.map(child => child.getName());

  if (children.length === 0) {
    // Base case - get text content if no children
    obj = element.getText();
  } else if (new Set(childNames).size !== childNames.length) {
    // If nonunique child names, add children as an array
    obj[rootName] = [];
    for (const child of children) {
      if (child.getChildren().length === 0) {
        const childObj = {};
        childObj[child.getName()] = xmlParse(child);
        obj[rootName].push(childObj)
      } else {
        const childObj = xmlParse(child);
        obj[rootName].push(childObj)
      }
    }
  } else {
    // If unique child names, add children as keys
    obj[rootName] = {};
    for (const child of children) {
      if (child.getChildren().length === 0) {
        obj[rootName][child.getName()] = xmlParse(child);
      } else {
        obj[rootName] = xmlParse(child);
      }
    }
  }

  return obj;
}

这两种方法的用法:

代码语言:javascript
复制
  const xml = XmlService.parse(xmlText); 
  const rootElement = xml.getRootElement();
  const obj = xmlParse(rootElement);
  const asJson = JSON.stringify(obj);

参考资料:

XMLService

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60708652

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档