【问题标题】:Pulling data from API as XML and converting to JSON从 API 中提取数据作为 XML 并转换为 JSON
【发布时间】:2021-09-22 23:16:21
【问题描述】:

这是我的第一个 javascript 项目,我试图从不同的 API 中提取数据以制作一个小型仪表板。我正在以 XML 格式从 API 中提取数据,并希望将其直接转换为 JSON 并将其存储在变量中。

const testdataurl = 'https://api.data.abs.gov.au/data/ABS,RES_DWELL/3.3GBRI.Q';
    
async function getData() {
    const response = await fetch(testdataurl);
    data = await response.text();
    console.log(data);
    }

getData()

如果您想查看 XML,可以在上面的代码中查看 API 端点。将它拉到 JSON 并存储在变量中对我来说最简单的方法是什么?

我已经研究过使用这个:

https://goessner.net/download/prj/jsonxml/

但我不确定如何最好地实现它。

谢谢

【问题讨论】:

  • 这能回答你的问题吗? Convert XML to JSON (and back) using Javascript
  • 为什么要转换成 json?不能直接当xml用吗?
  • @JackFleeting 我认为我不能将数据用作 XML。我正在尝试制作一个可以很好地显示数据的仪表板,并且我认为将我的所有 API 拉取为 JSON 会更容易使用

标签: javascript json xml api


【解决方案1】:

还有其他资源可以更好地解释如何将脚本导入 html 以使其在您的项目中可用。引用的脚本足够小,我只需将 sn-p 复制/粘贴到单个帖子中即可。由于某种原因,代码 sn-p 应该提供的 json 字符串返回了 undefined 段。我不确定为什么会这样,但是在检查了 xml 和返回的字符串之后,它看起来并不重要,所以我只是在解析为对象之前将其从 json 字符串中删除。

请记住,由于 CORS,此代码无法在 stackoverflow 上运行。我在 api.data.abs.gov.au 网站上对其进行了测试,以避免出现 CORS 问题。

希望这会有所帮助。

function parseXml(xml) {
   var dom = null;
   if (window.DOMParser) {
      try { 
         dom = (new DOMParser()).parseFromString(xml, "text/xml"); 
      } 
      catch (e) { dom = null; }
   }
   else if (window.ActiveXObject) {
      try {
         dom = new ActiveXObject('Microsoft.XMLDOM');
         dom.async = false;
         if (!dom.loadXML(xml)) // parse error ..

            window.alert(dom.parseError.reason + dom.parseError.srcText);
      } 
      catch (e) { dom = null; }
   }
   else
      alert("cannot parse xml string!");
   return dom;
}

/*  This work is licensed under Creative Commons GNU LGPL License.

    License: http://creativecommons.org/licenses/LGPL/2.1/
   Version: 0.9
    Author:  Stefan Goessner/2006
    Web:     http://goessner.net/ 
*/
function xml2json(xml, tab) {
   var X = {
      toObj: function(xml) {
         var o = {};
         if (xml.nodeType==1) {   // element node ..
            if (xml.attributes.length)   // element with attributes  ..
               for (var i=0; i<xml.attributes.length; i++)
                  o["@"+xml.attributes[i].nodeName] = (xml.attributes[i].nodeValue||"").toString();
            if (xml.firstChild) { // element has child nodes ..
               var textChild=0, cdataChild=0, hasElementChild=false;
               for (var n=xml.firstChild; n; n=n.nextSibling) {
                  if (n.nodeType==1) hasElementChild = true;
                  else if (n.nodeType==3 && n.nodeValue.match(/[^ \f\n\r\t\v]/)) textChild++; // non-whitespace text
                  else if (n.nodeType==4) cdataChild++; // cdata section node
               }
               if (hasElementChild) {
                  if (textChild < 2 && cdataChild < 2) { // structured element with evtl. a single text or/and cdata node ..
                     X.removeWhite(xml);
                     for (var n=xml.firstChild; n; n=n.nextSibling) {
                        if (n.nodeType == 3)  // text node
                           o["#text"] = X.escape(n.nodeValue);
                        else if (n.nodeType == 4)  // cdata node
                           o["#cdata"] = X.escape(n.nodeValue);
                        else if (o[n.nodeName]) {  // multiple occurence of element ..
                           if (o[n.nodeName] instanceof Array)
                              o[n.nodeName][o[n.nodeName].length] = X.toObj(n);
                           else
                              o[n.nodeName] = [o[n.nodeName], X.toObj(n)];
                        }
                        else  // first occurence of element..
                           o[n.nodeName] = X.toObj(n);
                     }
                  }
                  else { // mixed content
                     if (!xml.attributes.length)
                        o = X.escape(X.innerXml(xml));
                     else
                        o["#text"] = X.escape(X.innerXml(xml));
                  }
               }
               else if (textChild) { // pure text
                  if (!xml.attributes.length)
                     o = X.escape(X.innerXml(xml));
                  else
                     o["#text"] = X.escape(X.innerXml(xml));
               }
               else if (cdataChild) { // cdata
                  if (cdataChild > 1)
                     o = X.escape(X.innerXml(xml));
                  else
                     for (var n=xml.firstChild; n; n=n.nextSibling)
                        o["#cdata"] = X.escape(n.nodeValue);
               }
            }
            if (!xml.attributes.length && !xml.firstChild) o = null;
         }
         else if (xml.nodeType==9) { // document.node
            o = X.toObj(xml.documentElement);
         }
         else
            alert("unhandled node type: " + xml.nodeType);
         return o;
      },
      toJson: function(o, name, ind) {
         var json = name ? ("\""+name+"\"") : "";
         if (o instanceof Array) {
            for (var i=0,n=o.length; i<n; i++)
               o[i] = X.toJson(o[i], "", ind+"\t");
            json += (name?":[":"[") + (o.length > 1 ? ("\n"+ind+"\t"+o.join(",\n"+ind+"\t")+"\n"+ind) : o.join("")) + "]";
         }
         else if (o == null)
            json += (name&&":") + "null";
         else if (typeof(o) == "object") {
            var arr = [];
            for (var m in o)
               arr[arr.length] = X.toJson(o[m], m, ind+"\t");
            json += (name?":{":"{") + (arr.length > 1 ? ("\n"+ind+"\t"+arr.join(",\n"+ind+"\t")+"\n"+ind) : arr.join("")) + "}";
         }
         else if (typeof(o) == "string")
            json += (name&&":") + "\"" + o.toString() + "\"";
         else
            json += (name&&":") + o.toString();
         return json;
      },
      innerXml: function(node) {
         var s = ""
         if ("innerHTML" in node)
            s = node.innerHTML;
         else {
            var asXml = function(n) {
               var s = "";
               if (n.nodeType == 1) {
                  s += "<" + n.nodeName;
                  for (var i=0; i<n.attributes.length;i++)
                     s += " " + n.attributes[i].nodeName + "=\"" + (n.attributes[i].nodeValue||"").toString() + "\"";
                  if (n.firstChild) {
                     s += ">";
                     for (var c=n.firstChild; c; c=c.nextSibling)
                        s += asXml(c);
                     s += "</"+n.nodeName+">";
                  }
                  else
                     s += "/>";
               }
               else if (n.nodeType == 3)
                  s += n.nodeValue;
               else if (n.nodeType == 4)
                  s += "<![CDATA[" + n.nodeValue + "]]>";
               return s;
            };
            for (var c=node.firstChild; c; c=c.nextSibling)
               s += asXml(c);
         }
         return s;
      },
      escape: function(txt) {
         return txt.replace(/[\\]/g, "\\\\")
                   .replace(/[\"]/g, '\\"')
                   .replace(/[\n]/g, '\\n')
                   .replace(/[\r]/g, '\\r');
      },
      removeWhite: function(e) {
         e.normalize();
         for (var n = e.firstChild; n; ) {
            if (n.nodeType == 3) {  // text node
               if (!n.nodeValue.match(/[^ \f\n\r\t\v]/)) { // pure whitespace text node
                  var nxt = n.nextSibling;
                  e.removeChild(n);
                  n = nxt;
               }
               else
                  n = n.nextSibling;
            }
            else if (n.nodeType == 1) {  // element node
               X.removeWhite(n);
               n = n.nextSibling;
            }
            else                      // any other node
               n = n.nextSibling;
         }
         return e;
      }
   };
   if (xml.nodeType == 9) // document node
      xml = xml.documentElement;
   var json = X.toJson(X.toObj(X.removeWhite(xml)), xml.nodeName, "\t");
   return "{\n" + tab + (tab ? json.replace(/\t/g, tab) : json.replace(/\t|\n/g, "")) + "\n}";
}

const testdataurl = 'https://api.data.abs.gov.au/data/ABS,RES_DWELL/3.3GBRI.Q';
    
async function getData() {
  const response = await fetch(testdataurl);
  data = await response.text();
  const dom = parseXml(data);
  const myJsonStr = xml2json(dom);
  const fixedJsonStr = myJsonStr.replace(/\nundefined/, "");
  const jsonObj = JSON.parse(fixedJsonStr);
  console.log(jsonObj);
}

getData();

【讨论】:

  • 您好,感谢您的回复。有没有办法让我只调用那个 xml2json 库而不是在我的 javascript 文件中包含整个代码?我曾尝试使用import "xml2json";,但出现错误“无法在模块外使用导入语句”
  • 还有其他资源可以更好地解释如何将脚本导入 html 以使其在项目中可用。检查一下stackoverflow.com/questions/51164405/… 基本上你将文件下载到你的项目目录中,并包含一个&lt;script src="my-directory/jsToInclude.js"&gt;&lt;/script&gt; 标记确保它位于使用脚本的 js 链接之前。
  • 非常感谢您的帮助,汤姆。此处返回的 JSON 对象似乎不包含有关该 XML 端点的任何相关信息。例如:可以在 XML 中找到的“id="TIME_PERIOD" value="2020-Q2"" 在该 JSON 对象中找不到。我在这里错过了什么吗?
  • 对我来说,返回的对象包含带有{id: "TIME_PERIOD", value: "2020-Q2"} 的项目。试试看itemReturned["message:GenericData"]["message:DataSet"]["generic:Obs"][0]["generic:ObsDimension"]["@id"]。如果您接受我上面的回答,我将不胜感激。
猜你喜欢
  • 1970-01-01
  • 2015-02-18
  • 1970-01-01
  • 2012-02-04
  • 1970-01-01
  • 1970-01-01
  • 2017-03-10
  • 2020-04-19
  • 1970-01-01
相关资源
最近更新 更多