一、认识 package.xml 清单文件
package.xml 清单文件是 Salesforce 元数据部署的基础构建块。在这个动手项目里,你将学习元数据是什么、package.xml 清单如何按类型引用元数据组件、如何使用 Salesforce API 进行检索与部署,以及完整的工作流:创建项目、构建清单、从组织检索、部署到 scratch org、做出修改、拉回本地并提交到源代码控制。这是每一个 Salesforce DevOps 工作流的基础。
元数据、package.xml 与 Salesforce API
元数据组件与元数据类型:元数据(metadata)是组织中的资产(对象、选项卡、类等),这些资产也叫做元数据组件。你在 package.xml 文件中引用的每个元数据组件(例如自定义对象 Sticker__c 的自定义选项卡),都会对应一个编码文件,该文件定义了组件在数据库中的运作方式。元数据类型是元数据组件的总分类——例如 CustomObject 是标准与自定义对象的元数据类型,而 MyCustomObject__c 自定义对象(一个元数据组件)就是 CustomObject 类型的一个实例。
在 package.xml 示例中,元数据类型 CustomObject 和 CustomTab 指向两个元数据组件:自定义对象的 API 名是 Sticker__c;自定义选项卡被分配给该自定义对象,所以它的名字也是 Sticker__c。
用上面的 package.xml 检索元数据后,系统会返回定义组件如何运作的 .xml 文件。下面是关联 Sticker__c 自定义对象的自定义选项卡的 xml 文件示例。
你无需编辑这些文件,但理解各元数据组件之间如何相互关联很重要。
三种元数据组件类型:
- Simple(简单)——单个文件。这种元数据可独立检索和部署,无需其他元数据组件。
- Compound(复合)——相互调用的两个文件。例如 Apex 类或触发器包含两个文件:类文件和让类在组织内运作的 xml(-meta.xml)文件。
- Complex(复杂)——可能包含多个命名组件的文件,取决于拉取了哪些组件。例如一个自定义对象可能包含多个自定义字段及相互依赖的对应组件。部署复杂元数据组件时,可能需要把任何依赖组件一起部署。
元数据工具:Salesforce 提供了多种处理组织元数据的工具,如变更集或 Salesforce CLI。package.xml 只是工具箱里又一个好用的工具——它在创建非托管包、或只想抓取特定元数据组件部署时尤其有用。
package.xml 背后的语言:package.xml 清单用 XML(Extensible Markup Language,可扩展标记语言)编写。XML 是一种基于文本的语言,用于识别、组织和迁移元数据组件。它不像 Apex、Java、JavaScript 这类面向对象语言那样给组件带来「动作」,而是告诉系统要检索、部署或更新哪些特定的元数据组件。XML 文件通常被称为「package.xml 清单」,它包含一组元数据组件,通过 API 名称来标识它们,按类型列出每个组件。
XML 结构:XML 文档有两个主要部分——声明(declaration)和元素(elements / element trees)。几条 XML 规则:开始标签(如 <types>)必须有对应的闭合标签(</types>);元素名区分大小写,应始终小写(如 <members>、<types>);处理 Salesforce 元数据时,务必为所有元数据组件声明版本号:<version>64.0</version>。
Salesforce 相关标签的结构与用途:
<types>:包含一个或多个<members>标签和一个<name>标签,用于列出某类型的、要检索或部署的元数据组件。<members>:组件的完整名称。目录中每个组件定义一个<members>元素,是<types>的子元素。<name>:包含组件类型(如 CustomObject 或 Profile)。目录中每个组件类型定义一个 name,是<types>的子元素。<version>:被检索或部署文件的 Metadata API 版本号。部署时所有文件必须符合同一版本的 Metadata API。
XML 元素树以层级结构直接标识元数据组件:标签从根节点(<types>)开始,接着是标识组件组的父标签(<name>,告诉系统要查找什么类型的组件,如 CustomObject 或 FlexiPage/Lightning 页面),再下一个标签标识你想纳入 XML 文件的特定组件(<members>)。
在上例中,我们在一个元数据类型下调用两个对象:名为 Sticker__c 的自定义对象和名为 Contact 的标准对象,都在 CustomObject 元数据类型下;同时还调用了一个名为 Sticker_Record 的 Lightning Record 页面。
API 满天飞! Salesforce 提供了许多不同的 API 来程序化访问你的组织。下面这张表列出了 Salesforce 提供的主要 API:
| API 名称 | 协议 | 数据格式 | 通信方式 |
|---|---|---|---|
| REST API | REST | JSON, XML | 同步 |
| SOAP API | SOAP (WSDL) | XML | 同步 |
| Chatter REST API | REST | JSON, XML | 同步(照片异步处理) |
| User Interface API | REST | JSON | 同步 |
| Analytics REST API | REST | JSON, XML | 同步 |
| Bulk API | REST | CSV, JSON, XML | 异步 |
| Metadata API | SOAP (WSDL) | XML | 异步 |
| Streaming API | Bayeux | JSON | 异步(数据流) |
| Apex REST API | REST | JSON, XML, 自定义 | 同步 |
| Apex SOAP API | SOAP (WSDL) | XML | 同步 |
| Tooling API | REST 或 SOAP | JSON, XML, 自定义 | 同步 |
package.xml 对应的 API:不是每段元数据都能通过 UI 声明式获得——例如 Profile 这类元数据类型就无法在 Package Manager 中声明式访问。你可以用 SOAP API 发现和查找可用 package.xml 检索的元数据(SOAP API 开发者指南提供了对象及其用途的概述,以及说明对象间重要关系的实体关系图 ERD);用 Metadata API 在 package.xml 中调用特定的元数据类型(有时某些元数据类型不可访问或暴露方式与预期不同,如 Profile 中的某些权限,建议参考 Metadata API 开发者指南来确定要在 <name> 标签之间声明什么元数据类型)。
找到正确的元数据组件名称:处理 Metadata API 与 package.xml 时,知道每个组件该用哪个元数据类型可能很棘手。例如调用对象(无论自定义还是标准)就用 CustomObject 元数据类型;检索 Lightning Record 页面就用 FlexiPage。大多数元数据类型一目了然,但有些并不明显,需要稍作挖掘——SOAP API 和 ERD 图几乎总能为你指路。
二、用 package.xml 构建、部署与修改
第 3–5 单元执行完整的 package.xml 工作流:设置 VS Code 与 Salesforce CLI、授权 Dev Hub、创建 Salesforce DX 项目、构建 package.xml 清单、从 playground 检索元数据、部署到 scratch org、做出修改、拉回本地项目并提交到源代码控制。这就是基本的开发循环。
完整的 package.xml 工作流
设置(Setup):先安装代码编辑工具 Visual Studio Code(一个强大、高度可定制、跨平台的编辑器),再安装 Salesforce Extensions for VS Code(提供代码补全、语法高亮、Apex 调试等功能)——在 VS Code 的 Extensions 中搜索 salesforce extension pack 并安装/更新。
接着安装或升级 Salesforce CLI,用它轻松创建 scratch org、在组织与源代码仓库之间同步源代码。在 VS Code 终端运行 sf update 确认 CLI 安装正确。然后授权 Dev Hub:在 playground 的 Setup 中启用 Dev Hub(同时启用 Unlocked Packages 与 Second-Generation Managed Packages),记录用户名并重置密码,再在 VS Code 终端运行 sf org login web -d -a DevHub 登录并授权(该命令同时给组织设置别名 DevHub)。
安装非托管包:本模块提供了一些示例元数据(一个非托管包,如「贴纸(Sticker)」应用)。在 playground 的 Install a Package 选项卡粘贴 04tak0000009asH 并安装(选 Install for Admins Only),或从 App Launcher 的 Playground Starter 安装。安装完成后可在 Object Manager 查看 Sticker 自定义对象,在 Tabs 下看到新的 Stickers 自定义选项卡。
创建项目与清单:在 VS Code 终端导航到 Documents 目录,运行 sf project generate -n PackageXMLProject 创建名为 PackageXMLProject 的新项目(会构建一组文件夹与文件,方便用 CLI 管理元数据与包),再 cd PackageXMLProject 进入项目。在项目里新建一个 package.xml 文件,内容如下:
<?xml version="1.0" encoding="UTF-8"?><Package xmlns="http://soap.sforce.com/2006/04/metadata"><types><members>CUSTOM OBJECT API NAME HERE</members><name>CustomObject</name></types><types><members>CUSTOM TAB API NAME HERE</members><name>CustomTab</name></types><version>64.0</version></Package>
把 CUSTOM OBJECT API NAME HERE 和 CUSTOM TAB API NAME HERE 都替换为 Sticker__c 并保存。
从 playground 检索元数据:在 VS Code 终端运行 sf project retrieve start -o DevHub -x ./package.xml,该命令检索 XML 文件(-x)中引用的元数据,并把元数据文件加到 force-app 文件夹。完成后在文件夹树中确认 Sticker__c 对象和选项卡位于 force-app/main/default 文件夹(例如 force-app/main/default/objects 下应有 Sticker__c 文件夹,内含 Sticker__c.object-meta.xml)。
创建 scratch org 并部署:在终端运行 sf org create scratch -f config/project-scratch-def.json -d 创建 scratch org(用 -d 设为默认,通常一分钟内完成,记下输出的 org ID 与用户名)。然后用 sf project deploy start -a 64.0 把项目里的元数据推送到 scratch org(如果 scratch org 不是默认,需加 -u 参数指定用户名或别名)。
在 scratch org 中编辑:接下来做点开发——为贴纸项目创建一个自定义权限集(遵循最佳实践,不把权限堆到 Profile 上)。运行 sf org open 打开 scratch org,在 Setup → Permission Sets 新建,Label 填 Sticker Manager、API Name 填 Sticker_Manager,然后在 Object Settings 选择 Stickers,把 Tab Settings 设为 Available 和 Visible,Object Permissions 勾选 Read、Create、Edit、View All Records,保存。
拉回变更:开发完成后,在终端运行 sf project retrieve start -a 64.0 把所有在 scratch org 中做的变更拉回项目,新的自定义权限集文件会加到 force-app/main/default 目录结构(如 permissionsets 文件夹下的 Sticker_Manager.permissionset-meta.xml)。
检查包目录:拉取后务必目视确认组件与文件在正确的 force-app/main/default 目录结构中——本次唯一变更就是创建的 Sticker Manager 权限集,所以它应是终端成功信息里唯一列出的源组件。
修改 XML:package.xml 的一个「超能力」是选择性部署特定组件——当你只需要快速部署或更新单个组件、而非整个应用时尤其有用。接下来更新 package.xml:移除 CustomObject 和 CustomTab 两个元素树,新建一个元素树并填入刚创建的 Sticker_Manager 自定义权限集的 API 名:
<?xml version="1.0" encoding="UTF-8"?><Package xmlns="http://soap.sforce.com/2006/04/metadata"><types><members>CUSTOM PERMISSION SET API NAME HERE</members><name>PermissionSet</name></types><version>64.0</version></Package>
把 CUSTOM PERMISSION SET API NAME HERE 替换为 Sticker_Manager 并保存。
最佳部署实践:管理组织部署与协调开发变更颇具挑战,要留意组织限制——例如一次能检索或部署的文件数上限(默认 10,000 个文件)、同一时间能创建的 scratch org 数量上限,以及每次部署执行测试用例的数量。在不使用托管包或 unlocked packages 时,最佳部署实践是只部署需要部署的内容——用 package.xml 配合 CLI 能减少部署的文件数、避开组织限制、减少执行测试用例的数量、让部署更快。
部署到 playground:在 VS Code 终端用 sf project deploy start 部署新权限集(只需推送刚创建的权限集,无需全部推送)。成功后终端会显示已成功部署的元数据源。
用 package.xml 选择性部署元数据比大多数 Trailblazer 想象的要快。你不该用它部署组织里的全部元数据或整个应用——那是包开发(package development)的用途——但对于快速更新和元数据变更,package.xml 清单文件绝对是工具袋里的好帮手。



