当* // ... / @ NODE不起作用时,是否有比* / * / * / * / * [12]更好的XPATH语法?

时间:2019-04-10 01:56:33

标签: xml xpath

虽然我通过XPATH成功获得了(美国)PMMS 30年固定抵押贷款利率,但是获得(美国)联邦曲线收益率却没有那么成功。这些XML数据集可以使一个工作而不使另一个工作有何不同?

我尝试了许多变体,并且唯一适用于此数据集的变体是使用一系列带有数组限定符*/*/*/*的{​​{1}}。

此数据集中的元素总数[12] 180

我正在使用Google表格IMPORTXML(url,xpath)来执行此操作。

这项工作

count(*//)

这不是

=IMPORTXML("https://www.treasury.gov/resource-center/data-chart-center/interest-rates/pages/XmlView.aspx?data=yield","*/*/*/*/*[12]")

这些都不是

=IMPORTXML("https://www.treasury.gov/resource-center/data-chart-center/interest-rates/pages/XmlView.aspx?data=yield","*//d:BC_10YEAR")

还有许多其他变体-我想我已经尝试了所有这些变体,但是显然有些东西使我难以理解。

理想的结果是具体获取最新的 BC_10YEAR ,即发布时的最新情况,根据数据集(2019-04-09T20:36:32Z)为 2.49

*//*@d:BC_10YEAR *//@d:BC_10YEAR *//d:BC_10YEAR[1] *//m:properties[@d:BC_10YEAR] *//*m:properties[@d:BC_10YEAR]

数据集编码的网址

美国国库: <d:BC_10YEAR m:type="Edm.Double">2.49</d:BC_10YEAR>

FREDDIE MAC https://data.treasury.gov/feed.svc/DailyTreasuryYieldCurveRateData?$filter=month(NEW_DATE)%20eq%204%20and%20year(NEW_DATE)%20eq%202019

使用XPATH查询:

http://www.freddiemac.com/pmms/pmmsthin.html

2 个答案:

答案 0 :(得分:0)

当您说“更好”时,您的标准是什么?您是追求性能,可读性还是在寻找一种表达式,如果页面内容有微小变化,该表达式仍然可以使用?

其他尝试失败的主要原因可能是名称空间。如果XPath表达式中有名称,则本地名称和名称空间URI都必须与源文档中的名称匹配。前缀与执行XPath的名称空间绑定的方式取决于您使用的XPath API,有些人发现使用*[local-name()='xyz']/*[local-name()='abc']形式的构造来忽略名称空间更为方便。在XPath 2.0中,您可以编写/*:xyz/*:abc,但我想如果您使用的是XPath 2.0,您可能会这么说。

答案 1 :(得分:0)

我找到了一个简单的解决方案来获取使用 IMPORTFEEDSPLIT 的完整表。

最终产品是“A2”单元格中的单个 IMPORTFEED 请求,返回如下内容:

<头>
日期 1M 2M 3M 6M 1Y 2Y 3Y 5Y 7Y 10Y 20Y 30Y
2021-01-06T00:00:00 0.09 0.09 0.09 0.09 0.11 0.14 0.2 0.43 0.74 1.04 1.6 1.81
2021-01-11T00:00:00 0.09 0.08 0.08 0.1 0.1 0.14 0.22 0.5 0.84 1.15 1.68 1.88
2021-01-14T00:00:00 0.09 0.09 0.09 0.09 0.1 0.16 0.23 0.49 0.82 1.15 1.69 1.88
2021-01-20T00:00:00 0.08 0.08 0.08 0.1 0.1 0.13 0.19 0.45 0.78 1.1 1.65 1.84
2021-01-25T00:00:00 0.07 0.08 0.09 0.09 0.1 0.13 0.17 0.42 0.73 1.05 1.61 1.8

TL;DR

要获得最近的 10 年期美国国债利率 (BC_10YEAR):

=QUERY(ARRAYFORMULA(SPLIT(IMPORTFEED("https://data.treasury.gov/feed.svc/DailyTreasuryYieldCurveRateData?$orderby=NEW_DATE desc&$top=1")," ")),"Select Col12")

说明

1.在 URL 上使用 XQuery

假设我有一个名为 UrlFilterCell 的命名范围,它有这样的内容:

="NEW_DATE eq datetime'" & TEXT(TODAY()-1,"yyyy-MM-dd") & "'"

您可以将这个字符串构造为昨天,或者其他一些奇特的字符串,例如 year(NEW_DATE) gt 2020 and Id mod 3 eq 0(返回 2020 年之后年份的每第三条记录)。

然后将使用 IMPORTFEED 查询字符串构造 $filter= 部分:

IMPORTFEED("https://data.treasury.gov/feed.svc/DailyTreasuryYieldCurveRateData?$filter="&UrlFilterCell)

2.利用以空格分隔的 content

返回的 XML 被格式化为 Atom 提要,在 <content> 中有麻烦的字段:

  <entry>
    ...
    <content type="application/xml">
      <m:properties>
        <d:Id m:type="Edm.Int32">7700</d:Id>
        <d:NEW_DATE m:type="Edm.DateTime">2020-10-06T00:00:00</d:NEW_DATE>
        <d:BC_1MONTH m:type="Edm.Double">0.08</d:BC_1MONTH>
        ...

恶心。除了使用 IMPORTFEED 时,<content> 中的所有内容都会自动写出为空格分隔的字符串:

" 7784 2021-02-09T00:00:00 0.04 0.04 0.04 0.06 0.07 0.11 0.19 0.48 0.83 1.18 
1.78 1.95 1.95 "

太好了!只需使用 SPLIT 将每个分隔字符串转换为单独的列。

然后,使用 QUERY 仅选择我们想要的值。如果我们对日期 (Col2) 和所有 12 个持续时间 (BC_1MONTH, ..., BC_30YEAR) 感兴趣,则公式为:

=QUERY(ARRAYFORMULA(SPLIT(IMPORTFEED(UrlCell)," ")),"Select Col2,Col3,Col4,Col5,Col6,Col7,Col8,Col9,Col10,Col11,Col12,Col13,Col14")

根据您的需要修改列,不要忘记根据您的需要构造 UrlCell。例如,"SELECT Col12" 将只返回 BC_10YEAR 值。