【问题标题】:unable to parse SOAP XML response using google apps script无法使用谷歌应用脚​​本解析 SOAP XML 响应
【发布时间】:2020-09-21 23:17:06
【问题描述】:

我正在使用 google 应用程序脚本调用 SOAP XML Web 服务,目的是将响应内容插入到 google 工作表中。发出请求会返回具有有效数据值的预期响应,但是我在解析响应时遇到了困难。下面是我的功能...

function testFetch() {
  var response = UrlFetchApp.fetch(setScadaHost(), setOptions());
  var doc = XmlService.parse(response.getContentText());
  var ns = XmlService.getNamespace(setNsScada());
  var root = doc.getRootElement().getChild('scada-response', ns);
  var entries = [];
  for(var i in root) {
    var id = root[i].getAttribute('node-id').getValue();
    var td = root[i].getAttribute('trading-date').getValue();
    var tp = root[i].getAttribute('trading-period').getValue();
    var mw = root[i].getAttribute('generation').getValue();
    entries.push(id, new Date(td), tp, mw);
  }
  shtSoap.getRange(shtSoap.getLastRow()+1,1,entries.length, 4).setValues(entries);
}

shtSoap 在项目的其他地方定义,标识目标工作表。我得到的错误消息是“异常:范围内的行数必须至少为 1”并突出显示 .setValues() 行。

如果我 Logger.log(response); 我得到一个结构如下的 XML 响应:

<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <soapenv:Body>
        <scada-response response-type="Scada Service" xmlns="[domainhost]/response/scada">
            <node node-id="1st node"><trading-date value="2020-09-21"><trading-period value="32"><time-stamp value="16:21:00.000Z"><generation>1000</generation></time-stamp></trading-period></trading-date></node>
            <node node-id="2nd node"><trading-date value="2020-09-21"><trading-period value="32"><time-stamp value="16:21:00.000Z"><generation>1200</generation></time-stamp></trading-period></trading-date></node>
            <node node-id="3rd node"><trading-date value="2020-09-21"><trading-period value="32"><time-stamp value="16:21:00.000Z"><generation>1200</generation></time-stamp></trading-period></trading-date></node>
            <node node-id="4th node"><trading-date value="2020-09-21"><trading-period value="32"><time-stamp value="16:21:00.000Z"><generation>800</generation></time-stamp></trading-period></trading-date></node>
        </scada-response>
    </soapenv:Body>
</soapenv:Envelope>

如果我Logger.log 开启:

  • (entries)for 循环之后,我得到一个空数组。
  • (doc)doc 声明之后,我收到以下错误“文档:没有 DOCTYPE 声明,根是 [元素:]"

我也尝试在root 声明中将'scada-response' 换成'node',但得到了相同的结果。

非常感谢您提供的任何帮助以了解我哪里出错了。

【问题讨论】:

    标签: google-apps-script xml-parsing


    【解决方案1】:

    我相信你的目标如下。

    • 您想使用 Google Apps 脚本从问题中的 XML 数据中检索 node-idtrading-datetrading-periodgeneration 的值。
    • 您想将检索到的值放到电子表格中。

    修改点:

    • 在您的 XML 数据中,
      • scada-responsesoapenv:Body 的孩子。
      • nodescada-response 的子代。
      • trading-datenode 的孩子。
      • trading-periodtrading-date 的孩子。
      • generationtime-stamp 的孩子。
    • 在您的脚本中,var entries = []; 是循环中entries.push(id, new Date(td), tp, mw); 的一维数组。
      • 在这种情况下,我认为需要将id, new Date(td), tp, mwentries 的值作为一维数组。

    当以上几点反映到你的脚本中时,它变成如下。

    修改脚本:

    function testFetch() {
      var response = UrlFetchApp.fetch(setScadaHost(), setOptions());
      var doc = XmlService.parse(response.getContentText());
      
      // --- I modified below script.
      var ns1 = XmlService.getNamespace('soapenv', 'http://schemas.xmlsoap.org/soap/envelope/');
      var ns2 = XmlService.getNamespace('[domainhost]/response/scada');
      var nodeIds = doc.getRootElement().getChild('Body', ns1).getChild('scada-response', ns2).getChildren();
      var entries = nodeIds.map(c => {
        var tradingDate = c.getChild('trading-date', ns2);
        var tradingPeriod = tradingDate.getChild('trading-period', ns2);
        var id = c.getAttribute('node-id').getValue();
        var td = tradingDate.getAttribute('value').getValue();
        var tp = tradingPeriod.getAttribute('value').getValue();
        var mw = tradingPeriod.getChild('time-stamp', ns2).getChild('generation', ns2).getValue();
        return [id, new Date(td), tp, mw];
      });
      // ---
      
      shtSoap.getRange(shtSoap.getLastRow()+1,1,entries.length, 4).setValues(entries);
    }
    

    确认上述脚本的脚本:

    当您直接从您的 XML 数据测试上述脚本时,您还可以使用以下示例脚本。在这种情况下,请将其复制并粘贴到脚本编辑器并运行该函数。

    function myFunction() {
      var response = `<?xml version="1.0" encoding="utf-8"?>
    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <soapenv:Body>
            <scada-response response-type="Scada Service" xmlns="[domainhost]/response/scada">
                <node node-id="1st node"><trading-date value="2020-09-21"><trading-period value="32"><time-stamp value="16:21:00.000Z"><generation>1000</generation></time-stamp></trading-period></trading-date></node>
                <node node-id="2nd node"><trading-date value="2020-09-21"><trading-period value="32"><time-stamp value="16:21:00.000Z"><generation>1200</generation></time-stamp></trading-period></trading-date></node>
                <node node-id="3rd node"><trading-date value="2020-09-21"><trading-period value="32"><time-stamp value="16:21:00.000Z"><generation>1200</generation></time-stamp></trading-period></trading-date></node>
                <node node-id="4th node"><trading-date value="2020-09-21"><trading-period value="32"><time-stamp value="16:21:00.000Z"><generation>800</generation></time-stamp></trading-period></trading-date></node>
            </scada-response>
        </soapenv:Body>
    </soapenv:Envelope>`;
      var doc = XmlService.parse(response);
      var ns1 = XmlService.getNamespace('soapenv', 'http://schemas.xmlsoap.org/soap/envelope/');
      var ns2 = XmlService.getNamespace('[domainhost]/response/scada');
      var nodeIds = doc.getRootElement().getChild('Body', ns1).getChild('scada-response', ns2).getChildren();
      var entries = nodeIds.map(c => {
        var tradingDate = c.getChild('trading-date', ns2);
        var tradingPeriod = tradingDate.getChild('trading-period', ns2);
        var id = c.getAttribute('node-id').getValue();
        var td = tradingDate.getAttribute('value').getValue();
        var tp = tradingPeriod.getAttribute('value').getValue();
        var mw = tradingPeriod.getChild('time-stamp', ns2).getChild('generation', ns2).getValue();
        return [id, new Date(td), tp, mw];
      });
      console.log(entries)
    }

    注意:

    • 请在 V8 运行时使用上述修改后的脚本。

    参考:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-02-07
      • 1970-01-01
      • 1970-01-01
      • 2016-08-08
      • 2012-03-05
      • 1970-01-01
      • 2017-04-16
      相关资源
      最近更新 更多