【问题标题】:Google Apps Script XmlService - search by attributeGoogle Apps Script XmlService - 按属性搜索
【发布时间】:2018-01-19 06:10:13
【问题描述】:

有没有一种简单的方法可以通过 Google Apps 脚本中的属性来定位 XML 节点?这是一个 XML sn-p:

<hd:components>
    <hd:text name="ADM Custom admissions TE">
        <hd:prompt>Admission</hd:prompt>
        <hd:columnWidth widthType="minimum" minWidth="100"/>
    </hd:text>
    <hd:text name="ADM Insufficient heat end date TE">
        <hd:prompt>To</hd:prompt>
    </hd:text>
    <hd:text name="ADM Insufficient heat start date TE">
        <hd:prompt>From</hd:prompt>
    </hd:text>
    <hd:text name="ADM Third party payment period TE">
        <hd:defMergeProps unansweredText="__________"/>
        <hd:prompt>When (date or period)?</hd:prompt>
    </hd:text>

对于我试图解析的 XML 文件,“名称”属性是唯一标识符,而 GAS 认为是用于 XmlService.Element.getChild(name) 方法的“名称”(“此 sn-p 中显示的每个节点的 text") 是节点类型的非唯一分类器。我希望能够编写一个函数来从这个 XML 文件中检索一个特定的节点,只有 name 属性。其他语言中的 XMLPath 表示法使用 [@ 表示法具有此功能。有没有办法在 GAS 中做到这一点,或者我是否需要编写一个遍历 XML 的函数,直到找到具有正确名称属性的节点,或者将其存储在某种不同类型的数据结构中以便快速搜索 XML文件够大吗?

这是我开始写的 sn-p:如果没有内置函数也没关系,我只是想知道是否有更好/更快的方法来做到这一点。我的函数效率不高,我想知道 XmlService 是否有一个更有效的内部数据结构来加速搜索。我的方法是循环遍历所有元素的子元素,直到匹配为止。

function getComponentFromXML(xml,name) { 
  for (var i = 0; i < xml.length; i++) { 
    var x = xml[i];
    var xname = x.getAttribute('name').getValue();
    if (xname == name) {
      return getComponentAttributes(x);
    }
  }
}

【问题讨论】:

  • 您是否已经查看了Google Apps Script官方documentation关于XmlService和属性的信息?
  • 我做到了,但我没有看到已经定义为基于属性进行搜索的方法。这不是一个大功能,我只是担心以非标准和未优化的方式来实现它,特别是因为它在 Xpath 和其他不同语言的 XML 实现中可用。

标签: xml google-apps-script google-sheets xml-parsing


【解决方案1】:

没有内置搜索,因此唯一的方法是读取元素列表以查找具有所需属性“名称”值的元素。如果elements 是要搜索的元素数组,您可以这样做

var searchResults = elements.filter(function (e) {
  return e.getAttribute('name') && e.getAttribute('name').getValue() == searchString;
});

(当根本没有 'name' 属性时,需要这两项检查以避免错误。)

如何获得这样的数组elements可能取决于XML文档。如果像您的示例一样,要搜索的元素是根元素的直接子元素,则

var doc = XmlService.parse(xmlString);
var elements = doc.getRootElement().getChildren();

这将是一种快速简便的方法。

一般来说,要不递归地获取所有元素,可以使用getDescendants 方法。它返回一个 Content 对象数组,可以过滤为 Element 对象:

var elements = doc.getDescendants().filter(function (c) {
  return c.getType() == XmlService.ContentTypes.ELEMENT;
}).map(function (c) {
  return c.asElement();
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-29
    • 1970-01-01
    相关资源
    最近更新 更多