如本主题中所述, 使用 FOR XML、RAW 和 AUTO 模式构造 XML 不会对从查询结果生成的 XML 形状进行太多控制。 但是,EXPLICIT 模式在从查询结果生成所需的 XML 方面提供了最大的灵活性。
显式模式查询必须以特定方式编写,以便将所需 XML 的其他信息(如 XML 中的预期嵌套)显式指定为查询的一部分。 根据请求的 XML,编写 EXPLICIT 模式查询可能比较繁琐。 你可能会发现 ,将 PATH 模式 与嵌套结合使用是编写 EXPLICIT 模式查询的更简单的替代方法。
由于在 EXPLICIT 模式下将所需的 XML 描述为查询的一部分,因此必须确保生成的 XML 格式良好且有效。
EXPLICIT 模式下的行集处理
EXPLICIT 模式将查询执行产生的行集转换为 XML 文档。 为了使 EXPLICIT 模式生成 XML 文档,行集必须具有特定格式。 这要求编写 SELECT 查询以生成行集、 通用表,并采用特定格式,以便处理逻辑可以生成所需的 XML。
首先,查询必须生成以下两个元数据列:
第一列必须提供当前元素的标记号、整数类型,并且列名必须为 Tag。 查询必须为每个将从行集中构造的元素提供唯一的标签号。
第二列必须提供父元素的标记号,并且此列名必须是 Parent。 这样,“标记”和“父项”列能够提供层次结构信息。
这些元数据列值以及列名称中的信息用于生成所需的 XML。 请注意,您的查询必须以特定格式提供列名。 另请注意, 父 列中的 0 或 NULL 指示相应的元素没有父元素。 该元素作为顶级元素添加到 XML 中。
若要了解查询生成的通用表是如何处理成生成 XML 结果的,假设你已编写生成此通用表的查询:
请注意以下关于此通用表:
前两列是 Tag 和 Parent 列,是元列。 这些值确定层次结构。
列名称以某种方式指定,如本主题后面部分所述。
从此通用表生成 XML 时,此表中的数据垂直分区为列组。 分组基于 标记 值和列名确定。 在构造 XML 时,处理逻辑为每个行选择一组列并构造元素。 以下示例中适用以下内容:
对于第一行中的 标记 列值为1,名称中含有相同标记号1的列,Customer!1!cid 和 Customer!1!name,构成一个组。 这些列用于处理行,你可能已注意到生成的元素的形状为 <
Customer id=... name=...>。 本主题稍后将介绍列名称格式。对于 标记列 值 2 的行,列 Order!2!id 和 Order!2!date 构成一个组, <
Order id=... date=... />然后用于构造元素。对于 标记 列值 3 的行,columns OrderDetail!3!id!id 和 OrderDetail!3!pid!idref 构成组。 每行都从这些列生成一个元素 <
OrderDetail id=... pid=...>。
请注意,在生成 XML 层次结构时,将按顺序处理行。 XML 层次结构已确定,如下所示:
第一行指定 标记 值 1 和 父 值 NULL。 因此,相应的元素( <
Customer> 元素)将作为 XML 中的顶级元素添加。<Customer cid="C1" name="Janine">第二行标识 标记 值 2 和 父 值 1。 因此,元素( <
Order> 元素)将添加为元素的 <Customer> 子元素。<Customer cid="C1" name="Janine"> <Order id="O1" date="1/20/1996">接下来的两行标识 标记 值 3 和 父 值 2。 因此,这两个元素( <
OrderDetail> 元素)将添加为元素的 <Order> 子元素。<Customer cid="C1" name="Janine"> <Order id="O1" date="1/20/1996"> <OrderDetail id="OD1" pid="P1"/> <OrderDetail id="OD2" pid="P2"/>最后一行将 2 标识为 标记 编号,1 标识为 父 标记编号。 因此,将另一个 <
Order> 元素子元素添加到 <Customer> 父元素。<Customer cid="C1" name="Janine"> <Order id="O1" date="1/20/1996"> <OrderDetail id="OD1" pid="P1"/> <OrderDetail id="OD2" pid="P2"/> </Order> <Order id="O2" date="3/29/1997"> </Customer>
总之, 标记 和 父 元列中的值、列名中提供的信息以及行的正确顺序生成在使用 EXPLICIT 模式时所需的 XML。
通用表行排序
在构造 XML 时,将按顺序处理通用表中的行。 因此,为了检索与父节点正确关联的子实例,必须对行集中的行进行排序,使每个父节点后紧跟着它的子节点。
在通用表中指定列名
编写 EXPLICIT 模式查询时,必须使用此格式指定生成的行集中的列名称。 它们提供转换信息,包括元素和属性名称以及通过使用指令指定的其他信息。
这是一般格式:
ElementName!TagNumber!AttributeName!Directive
下面是格式的各个部分的说明。
ElementName
元素的结果通用标识符。 例如,如果将 Customers 指定为 ElementName, <则会生成 Customers> 元素。
TagNumber
分配给元素的唯一标记值。 此值在两个元数据列 (Tag 和 Parent)的帮助下确定生成的 XML 中元素的嵌套。
AttributeName
提供在指定 ElementName 中构造的属性的名称。 如果未指定 指令 ,则会出现这种行为。
如果指定 指令 并且它是 xml、 cdata 或 元素,则此值用于构造 ElementName 的元素子元素,并将列值添加到其中。
如果指定 指令 则 属性名称 可以为空。 例如,ElementName!TagNumber!!命令。 在这种情况下,列值由 ElementName 直接包含。
命令
指令 是可选的,你可以使用它提供用于构造 XML 的其他信息。
指令 有两个用途。
其中一个用途是将值编码为 ID、IDREF 和 IDREFS。 可以将 ID、IDREF 和 IDREFS 关键字指定为指令。 这些指令覆盖属性类型。 这样,就可以创建文档内链接。
此外,可以使用 指令 来指示如何将字符串数据映射到 XML。 hide、element、elementxsinil、xml、xmltext 和 cdata 关键字可用作指令。 隐藏指令隐藏节点。 仅出于排序目的检索值,但不希望在生成的 XML 中包含这些值时,这非常有用。
元素指令生成包含的元素而不是特性。 包含的数据被编码为一个实体。 例如,字符 < 变为 <。 对于 NULL 列值,不会生成任何元素。 如果希望为 null 列值生成元素,可以指定 elementxsinil 指令。 这将生成具有属性 xsi:nil=TRUE 的元素。
xml 指令与元素指令相同,只是没有发生实体编码。 请注意,元素指令可以与 ID、IDREF 或 IDREFS 结合使用,而 xml 指令不允许与任何其他指令结合使用,但隐藏除外。
cdata 指令通过使用 CDATA 节来封装数据。 内容未进行实体编码。 原始数据类型必须是文本类型,例如 varchar、 nvarchar、 text 或 ntext。 此指令只能与 隐藏一起使用。 使用此指令时,不得指定 AttributeName 。
在大多数情况下,允许合并这两个组之间的指令,但不允许将它们组合在一起。
如果未指定 指令 和 AttributeName ,例如 Customer!1,则隐含 元素 指令,如 Customer!1!!元素和列数据包含在 ElementName 中。
如果指定了 xmltext 指令,列的内容将被包裹在一个与文档其他部分集成的单个标签中。 此指令可用于通过 OPENXML 提取存储在某列中的溢出、未使用及 XML 格式的数据。 有关详细信息,请参阅 OPENXML (SQL Server)。
如果指定 AttributeName ,则标记名称将替换为指定的名称。 否则,该属性会被追加到封闭元素当前属性列表的开头,并将内容置于包含体的开头,而无需进行实体编码。 具有此指令的列必须是文本类型,例如 varchar、 nvarchar、 char、 nchar、 text 或 ntext。 此指令只能与 隐藏一起使用。 此指令可用于提取存储在列中的溢出数据。 如果内容不是格式正确的 XML,则行为未定义。
本节中
以下示例演示了 EXPLICIT 模式的使用。
另请参阅
将 RAW 模式与 FOR XML 一起使用
将 AUTO 模式与 FOR XML 配合使用
将 PATH 模式与 FOR XML 配合使用
SELECT (Transact-SQL)
FOR XML (SQL Server)