警告:本页面介绍的是 Google 的旧版 API,即 Google 数据 API;它仅与 Google 数据 API 目录中列出的许多 API 相关,其中许多 API 已替换为较新的 API。如需了解特定新 API,请参阅新 API 的文档。如需了解如何使用较新的 API 向请求授权,请参阅 Google 帐号身份验证和授权。
本文档介绍了许多 Google API 使用的 Google 数据协议,包括有关查询内容、结果内容等的信息。
如需详细了解 Google 数据协议,请参阅开发者指南概览页面和协议基础知识文档。
观众
本文适用于想要了解用于实现 Google 数据协议的 API 使用的 XML 格式和协议的详细信息。
如果您只是想编写使用这些 API 之一的代码,则无需了解这些详细信息,而可以使用特定于语言的客户端库。
但如果您想了解该协议,请阅读本文档。例如,阅读本文档可以帮助您完成以下任何任务:
- 评估 Google 数据协议架构
- 在不使用所提供的客户端库的情况下使用协议进行编码
- 使用新语言编写客户端库
本文档假定您了解 XML、命名空间、联合 Feed 以及 HTTP 中的 GET
、POST
、PUT
和 DELETE
请求的基础知识,以及 HTTP 的“资源”概念。如需详细了解这些内容,请参阅本文档中的其他资源部分。
本文档不依赖任何特定的编程语言;您可以使用任何允许您发出 HTTP 请求并解析基于 XML 的响应的编程语言来发送和接收 Google 数据协议消息。
协议详情
本部分介绍了 Google 数据协议文档格式和查询语法。
文档格式
Google 数据协议和 Atom 具有相同的基本数据模型,即存储一些全球数据和任意数量的条目的容器。对于每种协议,格式由基本架构定义,但可以使用外部命名空间进行扩展。
Atom 是 Google 数据协议的默认格式。如需请求其他格式的响应,请使用 alt
查询参数;如需了解详情,请参阅查询请求。
注意:大多数 Google 数据协议 Feed 都是采用 Atom 命名空间,通过在 Feed 元素上指定 xmlns
属性可将 Atom 命名空间用作默认命名空间,如协议基础知识中的示例所示。因此,本文档中的示例没有为 Atom 格式的 Feed 中的元素明确指定 atom:
。
下表显示了架构元素的 Atom 表示形式。这些表中未提及的所有数据都被视为普通 XML。除非另有说明,否则指定列中的 XML 元素均位于 Atom 命名空间中。
注意:此摘要使用标准的 XPath 表示法:具体来说,斜杠表示元素层次结构,@ 符号表示元素的属性。
在以下每个表格中,突出显示的项为必填项。
下表显示了 Google 数据协议 Feed 的元素:
Feed 架构项 | Atom 表示法 |
---|---|
Feed 标题 | /feed/title |
Feed ID | /feed/id |
Feed HTML 链接 | /feed/link[@rel="alternate"] \[@type="text/html"]/@href |
Feed 说明 | /feed/subtitle |
Feed 语言 | /feed/@xml:lang |
Feed 版权 | /feed/rights |
Feed 作者 |
(某些情况下是必需的;请参阅 Atom 规范。) |
Feed 上次更新日期 | /feed/updated (RFC 3339 格式) |
Feed 类别 | /feed/category/@term |
Feed 类别架构 | /feed/category/@scheme |
Feed 生成器 | /feed/generator /feed/generator/@uri |
Feed 图标 | /feed/icon |
Feed 徽标 | /feed/logo |
下表显示了 Google 数据协议搜索结果 Feed 的元素。请注意,该协议会在搜索结果 Feed 中公开某些 OpenSearch 1.1 响应元素。
搜索结果 Feed 架构项 | Atom 表示法 |
---|---|
搜索结果数量 | /feed/openSearch:totalResults |
搜索结果起始索引 | /feed/openSearch:startIndex |
每页的搜索结果数 | /feed/openSearch:itemsPerPage |
下表显示了 Google 数据协议条目的各元素:
条目架构项 | Atom 表示法 |
---|---|
条目 ID | /feed/entry/id |
条目标题 | /feed/entry/title |
条目链接 | /feed/entry/link |
条目摘要 |
(某些情况下是必需的;请参阅 Atom 规范。) |
条目内容 |
(如果没有内容元素,则条目必须包含至少一个 |
条目作者 |
(某些情况下是必需的;请参阅 Atom 规范。) |
条目类别 | /feed/entry/category/@term |
条目类别方案 | /feed/entry/category/@scheme |
参评发布日期 | /feed/entry/published (RFC 3339) |
条目更新日期 | /feed/entry/updated (RFC 3339) |
查询
本部分介绍如何使用查询系统。
查询模型设计原则
查询模型非常简单。基本原则如下:
- 查询以 HTTP URI 的形式表示,而不是以 HTTP 标头或载荷的形式表示。此方法的一个好处是,您可以链接到查询。
- 谓词的范围限定为单个项。因此,无法发送关联查询,例如“查找来自今天至少向我发送 10 封电子邮件的用户的所有电子邮件”。
- 查询可谓词集的属性非常有限;大多数查询只是全文搜索查询。
- 结果排序取决于实现。
- 该协议本身就可扩展。如果您希望在服务中公开其他谓词或排序方式,可通过引入新参数轻松完成。
查询请求
客户端通过发出 HTTP GET
请求来查询 Google 服务。查询 URI 由资源的 URI(在 Atom 中称为 FeedURI)后跟查询参数组成。大多数查询参数都表示为传统的 ?name=value[&...]
网址参数。类别参数的处理方式不同,请参阅下文。
例如,如果 FeedURI 为 http://www.example.com/feeds/jo
,那么您可以使用以下 URI 发送查询:
http://www.example.com/feeds/jo?q=Darcy&updated-min=2005-04-19T15:30:00Z
Google 数据协议支持 HTTP 条件 GET
。实现该协议的 API 会根据返回的 Feed 或条目中的 <atom:updated>
元素值设置 Last-Modified 响应标头。客户端可以将此值作为 If-Modified-Since 请求标头的值发回,以避免在内容未发生更改时再次检索该内容。如果内容自 If-Modified-Since 以来没有变化,则服务会返回 304(未修改)HTTP 响应。
实现 Google 数据协议的 API 必须支持 alt
查询;对其他参数的支持是可选的。传递给定服务无法理解的标准参数会导致 403 Forbidden
响应。传递不受支持的非标准参数会导致 400 Bad Request
响应。如需了解其他状态代码,请参阅本文档中的 HTTP 状态代码部分。
下表汇总了标准查询参数。所有参数值都需要经过网址编码。
参数 | 含义 | 备注 |
---|---|---|
alt |
替代表示法类型 |
|
author |
条目作者 |
|
category |
类别查询过滤条件 |
|
/-/category |
类别查询过滤条件 |
|
条目 ID | 要检索的特定条目的 ID |
|
fields |
响应过滤条件 |
|
max-results |
要检索的结果数上限 | 对于任何具有默认 max-results 值(限制默认 Feed 大小)的服务,如果您希望接收整个 Feed,则可以指定非常大的数字。 |
prettyprint |
返回带有标识和换行符的 XML 响应 |
|
published-min ,published-max |
条目发布日期的边界 |
|
q |
全文查询字符串 |
|
start-index |
要检索的第一个结果的索引(从 1 开始) |
|
strict |
严格的查询参数检查 |
|
updated-min ,updated-max |
条目更新日期的边界 |
|
关于类别查询
我们决定为类别查询提供一种不同寻常的格式。您无需进行如下查询:
http://example.com/jo?category=Fritz&category=2006
我们可以使用:
http://example.com/jo/-/Fritz/2006
此方法可在不使用查询参数的情况下识别资源,并能生成更简洁的 URI。我们之所以选择类别方法,是因为我们认为类别查询是最常见的查询之一。
这种方法的缺点是,您需要在此类类别查询中使用 /-/
,以便服务可以区分类别查询与其他资源 URI(例如 http://example.com/jo/MyPost/comments
)。
查询响应
查询将返回 Atom Feed、Atom 条目或 RSS Feed,具体取决于请求参数。
查询结果直接在 <feed>
元素或 <channel>
元素下包含以下 OpenSearch 元素(具体取决于结果是 Atom 还是 RSS):
openSearch:totalResults
- 查询的搜索结果总数(不一定全部存在于结果 Feed 中)。
openSearch:startIndex
- 第一个结果的索引(从 1 开始)。
openSearch:itemsPerPage
- 每页最多可显示的内容项数。这样,客户端就可以生成指向任意一组后续网页的直接链接。不过,如需了解使用此数字的可能的误区,请参阅查询请求部分的表
start-index
注意事项。
Atom 响应 Feed 和条目还可以包含以下任意 Atom 和 Data API 元素(以及 Atom 规范中列出的其他元素):
<link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="..."/>
- 指定用于检索整个 Atom Feed 的 URI。
<link rel="http://schemas.google.com/g/2005#post" type="application/atom+xml" href="..."/>
- 指定 Atom Feed 的 PostURI(可在其中发布新条目)。
<link rel="self" type="..." href="..."/>
- 包含此资源的 URI。
type
属性的值取决于请求的格式。如果在此期间没有任何数据更改,则向此 URI 发送另一个 GET 会返回相同的响应。 <link rel="previous" type="application/atom+xml" href="..."/>
- 指定此查询集的上一个分块的 URI(如果分块的话)。
<link rel="next" type="application/atom+xml" href="..."/>
- 指定此查询集的下一个分块(如果分块了)的 URI。
<link rel="edit" type="application/atom+xml" href="..."/>
- 指定 Atom 条目的 EditURI(即发送已更新条目的位置)。
以下是响应搜索查询的示例响应正文:
<?xml version="1.0" encoding="UTF-8"?> <feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:gd='http://schemas.google.com/g/2005' gd:etag='W/"C0QBRXcycSp7ImA9WxRVFUk."'> <id>http://www.example.com/feed/1234.1/posts/full</id> <updated>2005-09-16T00:42:06Z</updated> <title type="text">Books and Romance with Jo and Liz</title> <link rel="alternate" type="text/html" href="http://www.example.net/"/> <link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://www.example.com/feed/1234.1/posts/full"/> <link rel="http://schemas.google.com/g/2005#post" type="application/atom+xml" href="http://www.example.com/feed/1234.1/posts/full"/> <link rel="self" type="application/atom+xml" href="http://www.example.com/feed/1234.1/posts/full"/> <author> <name>Elizabeth Bennet</name> <email>liz@gmail.com</email> </author> <generator version="1.0" uri="http://www.example.com">Example Generator Engine</generator> <openSearch:totalResults>2</openSearch:totalResults> <openSearch:startIndex>0</openSearch:startIndex> <entry gd:etag='W/"C0QBRXcycSp7ImA9WxRVGUo."'> <id>http://www.example.com/feed/1234.1/posts/full/4521614025009481151</id> <published>2005-01-09T08:00:00Z</published> <updated>2005-01-09T08:00:00Z</updated> <category scheme="http://www.example.com/type" term="blog.post"/> <title type="text">This is the title of entry 1009</title> <content type="xhtml"> <div xmlns="http://www.w3.org/1999/xhtml">This is the entry body of entry 1009</div> </content> <link rel="alternate" type="text/html" href="http://www.example.com/posturl"/> <link rel="edit" type="application/atom+xml" href="http://www.example.com/feed/1234.1/posts/full/4521614025009481151"/> <author> <name>Elizabeth Bennet</name> <email>liz@gmail.com</email> </author> </entry> <entry gd:etag='W/"C0QBRXrurSp7ImA9WxRVGUo."'> <id>http://www.example.com/feed/1234.1/posts/full/3067545004648931569</id> <published>2005-01-07T08:00:00Z</published> <updated>2005-01-07T08:02:00Z</updated> <category scheme="http://www.example.com/type" term="blog.post"/> <title type="text">This is the title of entry 1007</title> <content type="xhtml"> <div xmlns="http://www.w3.org/1999/xhtml">This is the entry body of entry 1007</div> </content> <link rel="alternate" type="text/html" href="http://www.example.com/posturl"/> <link rel="edit" type="application/atom+xml" href="http://www.example.com/feed/1234.1/posts/full/3067545004648931569"/> <author> <name>Elizabeth Bennet</name> <email>liz@gmail.com</email> </author> </entry> </feed>
如果请求的 Feed 采用 Atom 格式,并且如果未指定查询参数,并且结果不包含所有条目,则会将以下元素插入顶级 Feed:<link rel="next" type="application/atom+xml" href="..."/>
。它指向包含下一组条目的 Feed。后续集包含相应的 <link rel="previous" type="application/atom+xml" href="..."/>
元素。通过遵循所有下一个链接,客户端可以从 Feed 中检索所有条目。
HTTP 状态代码
下表介绍了各种 HTTP 状态代码在 Data API 环境中的含义。
编码 | 说明 |
---|---|
200 OK | 无错误。 |
201 已创建 | 已成功创建资源。 |
304 未修改 | 在该请求的 If-Modified-Since 标头中指定的时间之后,该资源并未发生更改。 |
400 请求无效 | 请求 URI 或标头无效,或不受支持的非标准参数。 |
401 未授权 | 需要授权。 |
403 已禁止 | 标准参数不受支持,或者身份验证或授权失败。 |
404 无法找到 | 找不到资源(例如 Feed 或条目)。 |
409 冲突 | 指定的版本号与资源的最新版本号不匹配。 |
410 结束 | 请求的更改历史记录已不在此服务器上。有关详情,请参阅特定服务的文档。 |
500 内部服务器错误 | 内部错误。这是用于所有无法识别的服务器错误的默认代码。 |
资源版本控制 (ETag)
有时,您需要能够引用特定条目的特定版本。
这在以下两种情况下尤为重要:
- 执行“条件检索”,即客户端请求条目,而服务器仅在条目自客户端上次请求以来发生了更改时才发送条目。
- 确保多个客户端不会意外覆盖彼此的更改。如果客户端为条目指定旧版本标识符,Data API 通过更新和删除操作就会失败。
Google Data API 使用 ETag(HTTP 的标准部分)来处理这两种情况。
ETag 是用于指定特定条目的特定版本的标识符。服务器将一个 ETag 附加到它向客户端发送的条目和 Feed 元素。如果条目或 Feed 发生更改,其 ETag 也会随之更改。
Google 数据 API 在两个位置提供 ETag:在 ETag
HTTP 标头中,以及在 <feed>
和 <entry>
元素的 gd:etag
属性中。
在 Google Data API 中,ETag 通常是字母和数字字符串,有时还包括连字符和英文句点;该字符串通常用引号括起来。(引号是 ETag 的一部分。)例如,以下是来自 Data API 条目的 ETag:"S0wCTlpIIip7ImA0X0QI"
。
ETag 有两种:强和弱。强 ETag 用于标识特定条目的特定版本,可用于避免覆盖其他客户端的更改。在 Google Data API 中,弱 ETag 仅用于条件检索。弱 ETag 始终以 W/
开头。例如 W/"D08FQn8-eil7ImA9WxZbFEw."
并非所有 Google Data API 都支持强大的 ETag。如果是这样,则安全系数高的 ETag 仅用于条目;Feed 中的 ETag 弱。
以下示例展示了从支持强 ETag 的服务检索到的 Feed(包括部分 HTTP 标头):
GData-Version: 2.0 ETag: W/"C0QBRXcycSp7ImA9WxRVFUk." ... <?xml version='1.0' encoding='utf-8'?> <feed xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005' gd:etag='W/"C0QBRXcycSp7ImA9WxRVFUk."'> ... <entry gd:etag='"CUUEQX47eCp7ImA9WxRVEkQ."'> ... </entry> </feed>
支持版本 2 数据 API 的客户端库将以透明的方式为您处理 ETag。以下信息适用于不使用客户端库的客户端,以及有兴趣在协议一级处理版本控制的读者。
注意:如需了解 Data API 1.0 版中使用的资源版本控制系统,请参阅 1.0 参考指南。
条件检索
如果要检索以前检索过的条目,您可以通过让服务器发送自上次检索后更改的条目来提高效率。
要进行此类条件检索,请发送包含 HTTP If-None-Match
标头的 HTTP GET
请求。在标头中,指定条目的 ETag。
以下是 If-None-Match
标头的示例:
If-None-Match: W/"D08FQn8-eil7ImA9WxZbFEw."
服务器收到此请求后,会检查您所输入的条目是否与您指定的 ETag 相同。如果这些 ETag 匹配,则表示相应条目未发生变化,且服务器会返回 HTTP 304 Not Modified
状态代码。
如果两个 ETag 不匹配,则该条目自您上次请求后已被修改,服务器将返回该条目。
更新条目
要避免覆盖其他客户端的更改,最简单的方法就是让服务器确保当客户端发送更新后的条目时,客户端启动的条目版本与服务器存储的当前版本相同。如果第二个客户端先于客户端进行更新,则客户端的更新将被拒绝,因为客户端不再基于最新版本的修改。
当您的客户端从支持强 ETag 的服务检索数据时,每个条目都有一个 ETag,用于充当该条目版本的唯一版本标识符。
注意:使用 ETag 进行更新仅适用于强大的 ETag。对于提供弱 ETag 的服务,所有更新都会成功,而不管其他人是否在您检索到条目之后更新了相应条目;最新的更新始终会覆盖任何其他之前的更新。因此,请勿在更新或删除时发送较弱的 ETag。否则,您会收到错误消息。
因此,当客户端向 strong-ETag 服务发送更新时,需要指定所更新条目的版本。为此,您可以采用以下两种方法:
- 使用
If-Match
HTTP 标头。 - 在
<atom:entry>
元素中使用gd:etag
属性。
我们建议尽可能使用 If-Match
方法。
如需使用 If-Match
更新条目,请先获取要更新的条目。根据需要修改条目,然后创建包含修改后的条目的新 PUT
请求。(有关要使用的网址的详细信息,请参阅特定服务的文档。)
在发送 PUT
之前,请添加包含原始条目中的 ETag 的 HTTP If-Match
标头:
If-Match: "S0wCTlpIIip7ImA0X0QI"
然后发送 PUT
请求。
如果更新成功,服务器将返回 HTTP 200 OK
状态代码以及更新后的条目的副本。
如果由于您指定的 ETag 与条目中的当前 ETag 不匹配(这意味着该条目自上次检索以来在服务器上发生更改)而更新失败,服务器将返回 HTTP 412 Precondition Failed
状态代码。
如果无法轻松编写 HTTP 标头,或者因其他原因需要避免使用 If-Match
标头,您可以改为使用 gd:etag
属性。
如果您不发送 If-Match
标头,则服务器会将更新后的条目的 gd:etag
属性值用作隐式 If-Match
值。
要替换版本控制系统并更新该条目(无论自您检索以来是否有其他人更新了该条目),请使用 If-Match: *
而不是在标头中指定 ETag。
如需了解哪些服务支持增强型 ETag,请参阅迁移指南。
删除条目
删除使用强 ETag 的条目与更新它们非常相似。
如需删除具有强 ETag 的条目,请先检索要删除的条目,然后向该条目的编辑网址发送 DELETE
请求。
如果您想确保自己删除的条目在检索后已被其他客户端更改,请添加包含原始条目 ETag 值的 HTTP If-Match
标头。
如果您希望覆盖版本控制系统并删除该条目(无论自您检索以来是否有其他人更新了该条目),请使用 If-Match: *
而不是在标头中指定 ETag。
如果某个条目没有强 ETag,则 DELETE
请求会始终成功。
部分响应(实验性)
默认情况下,服务器在处理完请求后会发回目标资源的完整表示形式。部分响应允许您仅请求感兴趣的元素或属性,而不是请求完整的资源。这让您的客户端应用可以避免传输、解析和存储不需要的字段,因此可以更高效地使用网络、CPU 和内存资源。
如需了解您使用的产品是否有部分响应,请参阅其 API 文档。
如需请求部分响应,请使用 fields
查询参数指定您希望返回的元素或属性。示例如下:
http://www.example.com/feeds?fields=link,entry(@gd:etag,id,updated,link[@rel='edit']))
服务器的响应仅包含 Feed 的链接和条目元素;条目元素仅包含 ETag、ID、已更新和修改链接信息。以下部分介绍了 fields
查询参数语法。如需详细了解响应,请参阅处理部分响应。
注意:您可以对返回数据的任何请求使用 fields
查询参数。除了 GET
之外,还包含 POST
和 PUT
(以及用于进行部分更新的 PATCH
)。不过,fields
查询参数只会影响响应数据,不会影响您必须提供的数据或者更新或创建的字段。
fields 参数语法摘要
fields
查询参数值的格式基于 XPath 语法;不过,它仅支持一部分有效 XPath 表达式。以下内容对受支持的语法进行了总结。如需了解更多示例,请参阅下一部分。
- 使用逗号分隔列表来选择多个字段。
- 使用
a/b
选择嵌套在元素a
内的元素b
;使用a/b/c
选择嵌套在b
内的元素c
。 - 使用
'@'
前缀标识具有给定名称的属性;省略'@'
前缀以引用元素。 - 应用字段条件以选择符合特定条件的元素,方法是在要限制的元素后面添加表达式“
[ ]
”。例如,
fields=entry[author/name='Elizabeth']
仅返回伊丽莎白是作者的 Feed 条目。 - 通过将表达式放在任何所选元素后面的圆括号“
( )
”中,可指定字段子选择器,以便仅请求特定属性或子元素。例如,
fields=entry(id,author/email)
只会返回每个 Feed 条目的 ID 和作者的电子邮件地址。 - 您可以使用英文双引号或单引号分隔字符串
。
要转义英文双引号或单引号,请重复该引号。例如,
"""Hello,"" he said"
会生成字符串"Hello," he said
,'''Hello,'' he said'
会生成字符串'Hello,' he said
。 - 您可以在字段选择中使用通配符。
例如,
entry/gd:*
会选择gd
命名空间中的所有条目子元素,entry/@gd:*
会选择同一命名空间中的子元素属性。
fields
查询参数充当输出过滤条件。这意味着,系统仅在处理查询的其余部分之后才会计算部分响应。例如,如果您还指定了 max-results
查询参数来指明每页需要 20 个结果,则系统会生成前 20 个结果,并根据得出的部分计算结果。如果 fields
规范与查询选择的前 20 个条目中的任何一项都不匹配,则会返回空的 Feed;您不会获得返回的前 20 个条目。
注意:请勿尝试将字段条件用作查询选择器。也就是说,不要试图检索完整的 Feed 并应用字段条件从非常大的数据集中滤除相关项。尽可能使用其他查询参数(如 start-index
和 max-results
)将每个查询的结果缩减为便于管理的大小。否则,因使用不当而导致严重的性能下降可能会抵消部分响应所带来的性能提升。
设置 fields 参数值的格式
以下准则介绍了如何构造 fields
查询参数值。每条准则都包含示例,并提供了有关参数值如何影响响应的说明。
注意:与所有查询参数值一样,fields
参数值也必须采用网址编码。为便于阅读,下面的示例省略了编码。
- 确定您希望返回的字段,或者进行字段选择。
fields
查询参数值是以逗号分隔的元素或属性列表(统称为“字段”),并且每个字段都是相对于资源表示形式的根元素指定的。因此,如果您要检索 Feed,则字段是相对于<feed>
元素指定的;如果您要检索单个条目,则字段是相对于<entry>
元素指定的。如果您选择的元素是(或属于)Feed 中的一个重复元素,该服务会返回该元素的所有实例。
下面是一些 Feed 级示例:
示例 效果 entry
返回所有 <entry>
元素以及这些条目的所有子元素,但不返回<feed>
的其他任何子元素。id,entry
返回 Feed <id>
和所有<entry>
元素。entry/title
返回所有 Feed 条目的 <title>
元素。
每当返回嵌套元素时,响应中均会包含父元素的封闭标记。父级标记不会包含任何其他子元素或属性,除非还明确选择了它们。
entry/author/uri
仅返回所有 Feed 条目的 <author>
元素的<uri>
子元素。entry/*:rating
对于所有 Feed 条目,在任何命名空间中仅返回本地名称为 rating
的子元素。
下面是一些入门级示例:
示例 效果 author
返回目标条目的 <author>
子元素。@gd:etag
返回目标条目的 etag
属性。author/uri
返回目标条目的 <author>
元素的<uri>
子元素。media:group/media:*
返回目标条目的 media
命名空间中<media:group>
的所有子字段。- 仅限所选字段符合特定条件,或者使用字段条件。
- 默认情况下,如果您的请求指定某个元素多次发生,则部分响应将包括该元素的所有实例。不过,您还可以指定响应应仅包含具有特定属性值的元素,或使用“
[ ]
”语法满足某些其他条件的元素,如以下示例所示。如需了解详情,请参阅字段条件语法部分。示例 效果 entry[link/@rel='edit']
返回 rel
属性值为'edit'
的<link>
元素的所有 Feed 条目。entry/title[text()='Today']
返回 Feed 条目中发生的任何 <title>
元素(如果其内容为'Today'
)。entry/author[name='Jo']
如果 Feed 条目中含有内容为 'Jo'
的<name>
子元素,则返回这些<author>
元素。author[name='Jo']
如果目标条目中的 <name>
子元素包含内容'Jo'
,则返回目标条目中的<author>
元素。 - 仅请求部分选定元素,或使用字段子选择。
- 默认情况下,如果您的请求指定特定元素,该服务会完整地返回这些元素。您可以指定响应应仅包含所选元素中的特定子元素。如下例所示,您可以使用“
( )
”子选择语法来实现此目的。示例 效果 entry/author(uri)
仅返回 Feed 条目中作者的 <uri>
子元素。entry/author[name='Jo'](uri)
对于作者名称为 'Jo'
的任何条目,仅返回<author>
的<uri>
子元素。entry(link(@rel,
@href))
仅返回 Feed 条目中每个 <link>
元素的rel
和href
属性的值。entry(title,link[@rel='edit'])
仅返回具有每个 Feed 条目的修改 rel
属性的<title>
和<link>
元素。entry(title,author(uri)
为每个 Feed 条目返回 <title>
元素和作者<uri>
元素。
详细了解字段条件语法
您可以对字段或子字段使用字段条件。如果条件为 true,则所选字段将包含在结果中。如果没有字段条件,则会包含所选类型的所有字段。
所选字段的文本值用于比较。在这种情况下,如果字段是元素,则文本值是其内容;如果字段是属性,则文本值是该属性的值。如果该字段没有文本值,则比较会失败,并且该字段不包含在结果中。
下表显示了字段条件支持的 XPath 运算符,并提供了一些示例。
运营商 | 语法 | 示例 |
---|---|---|
字符串比较 |
|
|
逻辑比较 | and |
|
数值比较 | = 、eq != 或 ne > 或 gt > = 或 ge < 或 lt <= 或 le
|
|
日期比较 | 使用数值比较运算符,如示例所示。 | 如需比较日期或日期/时间,您可以将元素、属性或字符串字面量转换为
|
存在 | 使用元素或属性的名称,如示例所示。 |
|
Boolean | true() false()
|
布尔值在测试期间非常有用,可将字段条件强制设置为 true 或 false 状态。
|
处理部分响应
支持部分响应的服务器处理完包含 fields
查询参数的有效请求之后,会发回 HTTP 200 OK
状态代码以及所请求的属性或元素。如果 fields
查询参数出现错误或因其他原因而无效,服务器将返回 HTTP 400 Bad Request
状态代码。
响应的根元素是 <feed>
或 <entry>
,具体取决于目标 URI。根元素的内容仅包含该 Feed 或条目的所选字段,以及所有父元素的封闭标记。
可通过以下两种方式回放请求的 fields
查询参数:
- 根元素具有
gd:fields
属性,用于显示请求中指定的fields
查询参数的值。 - 如果目标 URI 是 Feed,则每个可修改的条目都有一个
gd:fields
属性,用于显示适用于它的fields
选择部分。
注意:为了在部分响应中看到这些 gd:fields
属性值,您必须将它们包含在 fields
查询参数规范中。您可以通过使用 @gd:fields
或更通用的 @gd:*
(其中也包含 ETag 信息)来显式执行此操作。
以下示例查询要求服务器返回仅包含 gd
命名空间中属性(Feed 级别和入门级别)的文档,以及每个 ID 条目的 Feed ID、标题和修改链接。
http://example.com/myFeed?fields=@gd:*,id,entry(@gd:*,title,link[@rel='edit'])
服务器会返回以下部分响应以及 200 Successful
HTTP 状态代码:
<?xml version='1.0' encoding='utf-8'?> <feed xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005' gd:etag='W/"DEAEQH47eCp7IWA9WxBVGUo."' gd:fields='@gd:*,id,entry(@gd:*,title,link[@rel='edit'])> <id>http://example.com/myFeed</id> <entry gd:etag='"EksPTg1Bfyp7IWA6WhJT"' gd:fields="@gd:*,title,link[@rel='edit']"> <link rel='edit' href='http://example.com/myFeed/1/'/> <title>This year</title> </entry> <entry gd:etag='"EksPQA1Cdyp7IWA6WhJT"' gd:fields="@gd:*,title,link[@rel='edit']"> <link rel='edit' href='http://example.com/myFeed/2/'/> <title>Last year</title> </entry> <entry d:etag='"EksPQAxHeCp7IWA6WhJT"' gd:fields="@gd:*,title,link[@rel='edit']"> <link rel='edit' href='http://example.com/myFeed/3/'/> <title>Today</title> </entry> </feed>
如果所选字段不匹配,服务仍会返回 200 Successful
HTTP 状态代码,但部分响应是空 Feed:
<?xml version='1.0' encoding='utf-8'?> <feed xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005' gd:etag='W/"DEAEQH47eCp7IWA9WxBVGUo."' gd:fields='@gd:*,id,entry(@gd:*,title,link[@rel='edit'])> </feed>
部分更新(实验性)
如果 Google 产品支持部分响应和可编辑资源,您还可以使用部分更新。使用部分更新时,您可以只发送要更新的字段,而不是发送完整资源表示法的修改版本。这样可以让您的客户端应用在使用更新以及使用部分响应检索数据时更加高效。
但是,在进行部分更新时,您必须使用 PATCH
请求,而不是 PUT
。PATCH
的语义非常强大,可让您通过单个请求添加、替换和删除特定条目的特定字段。
如需了解您当前使用的产品是否有部分更新,请参阅特定产品的文档。
提交部分更新请求
如需提交部分更新请求,请向您通常使用 PUT
更新资源时所用的网址发送 HTTP PATCH
请求。PATCH
请求的正文是一个 <entry>
元素,用于指定要添加或修改的字段。该条目的 gd:fields
属性表示您想删除的字段。
服务器以特定顺序处理 PATCH
请求:
- 它首先从资源表示中移除
gd:fields
属性指定的字段。gd:fields
属性的语法与请求部分响应时使用的fields
查询参数相同。有关详情,请参阅支持的语法。 - 然后,它会合并到表示正文中提供的数据的现有资源。
如需详细了解如何合并数据,请参阅下文的添加或更新字段。
注意:由于 PATCH
请求的正文通常不符合 Atom 整合格式,因此您在 PATCH
请求中使用的 Content-Type
为 application/xml
。
以下是部分更新请求的示例:
PATCH /myFeed/1/1/ Content-Type: application/xml <entry xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005' gd:fields='description'> <title>New title</title> </entry>
此 PATCH
请求会对目标 URI 条目在服务器上存储的资源表示法进行以下更改:
- 移除
<description>
元素。 - 更新
<title>
元素。
部分更新请求的语义
以下说明介绍了如何设置 PATCH
请求以删除、添加或更新条目内的特定字段。单个 PATCH
请求可以执行这些操作的任意组合。
删除字段。使用
<entry>
元素的gd:fields
属性来标识要从资源中删除的所有字段。以下示例请求会删除与条目关联的标题和摘要。不过,该请求不会为相应条目添加或更新任何其他数据。PATCH /myfeed/1/1/ Content-Type: application/xml <entry xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005' gd:fields='title,summary'/>
添加或更新字段。使用
<entry>
元素的正文指定要为资源添加或更新的数据。执行以下任一删除操作后,这些字段将合并到资源的现有数据中:系统会添加尚未显示的字段。如果资源数据尚未为某个字段指定值,则该字段会添加到现有数据中。例如,如果某个条目没有标题,而您的
PATCH
请求包含<title>
元素,则系统会将新标题添加到该条目中。已替换或附加已存在的字段。合并资源数据中已指定的字段的具体行为取决于字段的特征:
非重复字段会被替换。如果资源数据已指定非重复元素的值,则您在
PATCH
请求中指定的值会替换该元素的现有值。例如,在下面的示例中,新标题将取代现有标题。PATCH /myFeed/1/1/ Content-Type: application/xml <entry xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005'> <title>New Title</title> </entry>
下面给出了一个更复杂的示例。在此示例中,假设该条目只能有一个作者,并且目标资源已经具有作者姓名和电子邮件地址的值。尽管
<author>
元素有两个子字段,但提供的数据中仅包含<name>
元素。因此,只有该字段的值会被覆盖。所提供的数据中缺少<email>
元素的值,该值保持不变。PATCH /myfeed/1/1/ Content-Type: application/xml <entry xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005'> <author> <name>New Name</name> </author> </entry>
附加了重复字段。如果资源数据已指定重复元素的值,那么您提供的新元素将添加到现有的一组值中。
请注意,除了添加重复元素的新实例之外,您可能还希望执行其他操作。例如,您可能想要执行以下操作之一:
替换整个重复元素列表。您可以使用
gd:fields
属性(例如gd:fields='ns:accessControl'
)删除所有重复字段,并提供一整套替换字段。由于所有现有元素首先被删除,因此您提供的这组字段在附加时不会与任何现有值冲突。替换某个重复元素的一组现有值中的一个值。在这种情况下,只需定义足够具体的
gd:fields
值即可移除单个元素,避免删除您想要保留的其他值。例如,如需仅移除action
为embed
的访问权限控制,您可以使用gd:fields='ns:accessControl[@action="embed"]'
。然后,在<entry>
元素的正文中提供要将其替换的单个字段:PATCH /myfeed/1/1/ Content-Type: application/xml <entry xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005' gd:fields='ns:accessControl[@action="embed"]> <ns:accessControl action="embed" permission="allowed" /> </entry>
处理对部分更新的响应
处理完有效的部分更新请求后,API 会返回 200 OK
HTTP 响应代码。默认情况下,响应的正文是您更新的完整条目。服务器会在成功处理 PATCH
请求时更新 ETag 值,就像处理 PUT
一样。
如果 PATCH
请求导致的新资源状态在语法或语义上是无效的,则服务器会返回 HTTP 400 Bad Request
或 422 Unprocessable Entity
HTTP 状态代码,并且资源状态会保持不变。例如,如果您尝试删除必填字段,但没有提供替代字段,则服务器会返回错误。
注意:了解不同字段之间的关系非常重要。仅更新部分相互依赖的值可能会使资源进入不一致状态。例如,可将开始时间更新为晚于结束时间的值。虽然该 API 应返回错误代码,但我们建议您全面测试这些条件,以确保一致性。
不支持 PATCH 时的备用表示法
如果您的防火墙不支持 PATCH
,请发出 HTTP POST
请求并将替换标头设置为 PATCH
,如下所示:
POST /myfeed/1/1/ X-HTTP-Method-Override: PATCH Content-Type: application/xml ...
使用部分响应和部分更新
您可以将部分响应用作后续部分更新请求的基础。如果您这样做,请指定包含修改链接的 fields
查询参数,以及 @gd:*
。这样可确保部分响应包含 ETag 和 gd:fields
属性值等信息,这对后续请求非常重要。
以下示例返回了部分响应,您可以将其作为未来部分更新的基础:
http://example.com/myFeed/1/1/?fields=@gd:*,link[@rel='edit'](@href),gd:who
服务器做出以下响应:
<?xml version='1.0' encoding='utf-8'?> <entry xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005' gd:etag='"E0UKRAREeCp7IWA6WhJT"' gd:fields="@gd;*,link[@rel='edit'](@href),gd:who"> <link href='http://example.com/myFeed/1/1/'/> <gd:who email='liz@gmail.com'/> <gd:who email='jo@gmail.com'/> <gd:who email='jane@gmail.com'/> </entry>
假设您想移除电子邮件地址为 'jane@gmail.com'
的用户,添加电子邮件地址为 'will@gmail.com'
的用户,并将当前列为 'jo@gmail.com'
的用户的电子邮件地址更改为 'josy@gmail.com'
。
您可以执行这些更改,只需从上一个响应的结果开始,仅修改不同的字段,然后将修改后的部分条目作为 PATCH
请求的正文提交。对于此示例,所需的修改如下:
- 从提供的元素列表中删除
<gd:who email='jane'/>
。 - 将
<gd:who email='will@gmail.com'/>
添加到提供的元素列表中。 - 将
<gd:who email='jo@gmail.com'/>
替换为<gd:who email='josy@gmail.com'/>
。
基于部分响应的 PATCH
请求如下所示:
PATCH /myFeed/1/1/ Content-Type: application/xml <entry gd:fields="@gd:*,link[@rel='edit'](@href),gd:who" gd:etag="FE8LQQJJeSp7IWA6WhVa"> <link href='http://example.com/myFeed/1/1'/> <gd:who email='liz@gmail.com'/> <gd:who email='josy@gmail.com'/> <gd:who email='will@gmail.com'/> </entry>
注意:此方法依赖于条目的部分响应中包含的 gd:fields
和 gd:etag
属性(如果支持)。除了您明确要移除的字段之外,部分条目的正文必须保留部分响应中的所有字段和属性。您可以使用新值更新正文中的任何现有字段,还可以添加要添加的任何新字段。
身份验证
当客户端尝试访问服务时,可能需要向服务提供用户的凭据,以证明用户有权执行相关操作。
客户端应该使用何种身份验证方法取决于客户端类型:
- 桌面应用应使用 Google 专用的身份验证系统,即针对已安装应用的帐号身份验证。(基于网络的客户端不应使用此系统。)
- 基于网络的客户端(例如 Google 服务的第三方前端)应使用名为适用于 Web 应用的帐号身份验证代理(也称为“AuthSub”)的 Google 专用身份验证系统。
在 EGL 系统中,桌面客户端要求用户提供其凭据,然后将这些凭据发送到 Google 身份验证系统。
如果身份验证成功,则身份验证系统会返回一个令牌,该客户端随后会在发送 Data API 请求时使用该令牌(在 HTTP 授权标头中)。
如果身份验证失败,服务器将返回 403“禁止访问”状态代码,以及包含适用于身份验证的质询的 WWW-Authenticate 标头。
AuthSub 系统的工作方式类似,只不过它不是要求用户提供凭据,而是将用户连接到请求凭据的 Google 服务。然后,该服务会返回 Web 应用可以使用的令牌;这种方法的优势在于,Google(而不是 Web 前端)可以安全地处理和存储用户的凭据。
要详细了解这些身份验证系统,请参阅 Google 数据 API 身份验证概览或 Google 帐号身份验证文档。
会话状态
许多业务逻辑实现都需要会话粘性,即跟踪用户会话的状态。
Google 通过以下两种方式跟踪会话状态:使用 Cookie,使用可作为查询参数发送的令牌。这两种方法可实现相同的效果。我们建议客户支持下列任一会话状态跟踪方法(两种方法足以满足需求)。如果客户端不支持其中任一方法,则该客户端仍可使用 Data API,但与支持这些方法的客户端相比,性能可能会受影响。具体而言,如果客户端不支持这些方法,那么每个请求都会产生重定向,因此每个请求(及任何关联数据)都会发送到服务器两次,这会影响客户端和服务器的性能。
Google 客户端库会处理会话状态,因此如果您使用我们的库,则无需执行任何操作即可获得会话状态支持。
其他资源
以下第三方文档可能对您有所帮助:
- Atom 和 RSS 的比较
- IBM 的 Atom 概览
- RSS 的 Dublin Core 扩展程序
- HTTP 1.1 方法定义;针对
GET
、POST
、PUT
和DELETE
的规范 - HTTP 1.1 状态代码定义
- 如何创建 REST 协议
- 以 REST 方式构建 Web 服务
- XML 技术简介
- XML 命名空间示例
- HTTP 规范的 ETag 部分