在 OPENXML 中指定元属性

适用于:SQL ServerAzure SQL 数据库Azure SQL 托管实例

XML 文档中的元属性特性用于描述 XML 项(例如元素节点、属性节点或其他任何 DOM 节点)的属性。 这些特性实际上并不存在于 XML 文档文本中。 但是,OPENXML 将为所有 XML 项提供这些元属性。 通过这些元属性可以提取 XML 节点的信息(例如本地定位和命名空间信息)。 这些信息将提供比文字表现形式更加详细的信息。

可以使用 ColPattern 参数将这些元属性映射到 OPENXML 语句中的行集列。 这些列将包含它们所映射到的元属性的值。 有关 OPENXML 语法的详细信息,请参阅 OPENXML (Transact-SQL)

若要访问元属性特性,应提供特定于 SQL Server 的命名空间。 此命名空间 urn:schemas-microsoft-com:xml-metaprop 允许用户访问元属性特性。 如果 OPENXML 查询的结果以边缘表格式返回,则每个元属性特性在边缘表中都有相应的一列(xmltext 元属性除外)。

有些元属性特性用于处理目的。 例如,xmltext 元属性特性用于溢出处理。 溢出处理针对文档中未用完/未处理的数据。 可以将 OPENXML 所生成的行集中的一列标识为溢出列。 为此,可以使用 ColPattern 参数将该列映射到 xmltext 元属性。 然后,该列将接收溢出数据。 flags 参数用于确定该列是包含所有数据还是只包含未用完的数据。

下表列出了每个经过分析的 XML 元素所具有的元属性特性。 可以使用命名空间 urn:schemas-microsoft-com:xml-metaprop 来访问这些元属性特性。 用户使用这些元属性在 XML 文档中直接设置的任何值均会被忽略。

注意

不能在任何 XPath 导航中引用这些元属性。

元属性特性 说明
@mp:id 提供由系统生成的、文档范围的 DOM 节点标识符。 只要文档未被重新分析,此 ID 就会引用同一个 XML 节点。

0 的 XML ID 表明该元素是根元素。 其父 XML ID 为 NULL。
@mp:localname 存储节点名的本地部分。 与前缀及命名空间 URI 一起用于命名元素节点或属性节点。
@mp:namespaceuri 提供当前元素的命名空间 URI。 如果此特性的值为 NULL,则表明不存在命名空间。
@mp:prefix 存储当前元素名的命名空间前缀。

如果不存在前缀 (NULL) 且给定了 URI,则表明指定的命名空间为默认命名空间。 如果没有给定 URI,则表明没有附加命名空间。
@mp:prev 存储相对于节点的前一个同级元素。 此特性将提供有关元素在文档中的排序顺序的信息。

@mp:prev 包含具有相同父元素的前一个同级元素的 XML ID。 如果某个元素位于同级列表的开头,则 @mp:prev 为 NULL。
@mp:xmltext 用于处理目的。 它是元素及其属性以及 OPENXML 溢出处理中所使用的子元素的文本序列化。

下表显示了使您得以检索关于层次结构的信息的其他父属性。

父元属性特性 说明
@mp:parentid ../\@mp:id
@mp:parentlocalname ../\@mp:localname
@mp:parentnamespacerui ../\@mp:namespaceuri
@mp:parentprefix ../\@mp:prefix

示例

下列示例说明了如何使用 OPENXML 来创建不同的行集视图。

A. 将 OPENXML 行集列映射到元属性

此示例使用 OPENXML 创建该示例 XML 文档的行集视图。 它专门显示了如何使用 ColPattern 参数将各种元属性特性映射到 OPENXML 语句中的行集列。

OPENXML 语句说明了以下信息:

  • id 列将映射到 @mp:id 元属性特性,表明该列包含该元素由系统生成的唯一 XML ID。

  • parent 列将映射到 @mp:parentid,表明该列包含该元素的父元素的 XML ID。

  • parentLocalName 列将映射到 @mp:parentlocalname,表明该列包含父元素的本地名。

然后,SELECT 语句将返回由 OPENXML 生成的行集:

DECLARE @idoc int;
DECLARE @doc nvarchar(1000);
-- Sample XML document
SET @doc = N'<root>
  <Customer cid= "C1" name="Janine" city="Issaquah">
      <Order oid="O1" date="1/20/1996" amount="3.5" />
      <Order oid="O2" date="4/30/1997" amount="13.4">Customer was very satisfied</Order>
   </Customer>
   <Customer cid="C2" name="Ursula" city="Oelde" >
      <Order oid="O3" date="7/14/1999" amount="100" note="Wrap it blue white red">
          <Urgency>Important</Urgency>
      </Order>
      <Order oid="O4" date="1/20/1996" amount="10000"/>
   </Customer>
</root>';
-- Create an internal representation of the XML document.
EXEC sp_xml_preparedocument @idoc OUTPUT, @doc;

-- Execute a SELECT statement using OPENXML rowset provider.
SELECT *
FROM OPENXML (@idoc, '/root/Customer/Order', 9)
      WITH (id int '@mp:id',
            oid char(5),
            date datetime,
            amount real,
            parentIDNo int '@mp:parentid',
            parentLocalName varchar(40) '@mp:parentlocalname');
EXEC sp_xml_removedocument @idoc;

结果如下:

id   oid         date                amount    parentIDNo  parentLocalName
--- ------- ---------------------- ---------- ------------ ---------------
6    O1    1996-01-20 00:00:00.000     3.5         2        Customer
10   O2    1997-04-30 00:00:00.000     13.4        2        Customer
19   O3    1999-07-14 00:00:00.000     100.0       15       Customer
25   O4    1996-01-20 00:00:00.000     10000.0     15       Customer

B. 检索整个 XML 文档

在本例中,使用 OPENXML 来创建示例 XML 文档的单列行集视图。 此列 (Col1) 将映射到 xmltext 元属性,并成为溢出列。 因此,此列将接收未用完的数据。 在本例中,它是整个文档。

然后,SELECT 语句将返回整个行集。

DECLARE @idoc int;
DECLARE @doc nvarchar(1000);
SET @doc = N'<?xml version="1.0"?>
<root>
  <Customer cid= "C1" name="Janine" city="Issaquah">
      <Order oid="O1" date="1/20/1996" amount="3.5" />
      <Order oid="O2" date="4/30/1997" amount="13.4">Customer was very
             satisfied</Order>
   </Customer>
   <Customer cid="C2" name="Ursula" city="Oelde" >
      <Order oid="O3" date="7/14/1999" amount="100" note="Wrap it blue
             white red">
     <MyTag>Testing to see if all the subelements are returned</MyTag>
          <Urgency>Important</Urgency>
      </Order>
      <Order oid="O4" date="1/20/1996" amount="10000"/>
   </Customer>
</root>';
-- Create an internal representation of the XML document.
EXEC sp_xml_preparedocument @idoc OUTPUT, @doc;

-- Execute a SELECT statement using OPENXML rowset provider.
SELECT *
FROM OPENXML (@idoc, '/')
   WITH (Col1 ntext '@mp:xmltext')

若要在没有 XML 声明的情况下检索整个文档,可以将查询指定为以下形式:

SELECT *
FROM OPENXML (@idoc, '/root')
   WITH (Col1 ntext '@mp:xmltext')
EXEC sp_xml_removedocument @idoc;

查询将返回带有名称根的根元素以及根元素所包含的数据。

C. 指定 xmltext 元属性来检索列中未使用的数据

此示例使用 OPENXML 创建该示例 XML 文档的行集视图。 该示例演示如何通过将 xmltext 元属性特性映射到 OPENXML 中的行集列来检索未使用的 XML 数据。

comment 列通过映射到 @mp:xmltext 元属性将其标识为溢出列。 flags 参数将设置为 9 (XML_ATTRIBUTE and XML_NOCOPY。) 这表示 attribute-centric 映射,并指明只能将未使用的数据复制到溢出列。

然后,SELECT 语句返回由 OPENXML 生成的行集。

在本例中,为 OPENXML 所生成行集中的 @mp:parentlocalname 列设置了 ParentLocalName 元属性。 因此,此列包含父元素的本地名。

在行集中还指定了另外两列,parentcommentparent 列将映射到 @mp:parentid,表明该列包含该元素的父元素的 XML ID。 comment 列通过映射到 @mp:xmltext 元属性将其标识为溢出列。

DECLARE @idoc int;
DECLARE @doc nvarchar(1000);
-- sample XML document
SET @doc = N'<root>
  <Customer cid= "C1" name="Janine" city="Issaquah">
      <Order oid="O1" date="1/20/1996" amount="3.5" />
      <Order oid="O2" date="4/30/1997" amount="13.4">Customer was very satisfied</Order>
   </Customer>
   <Customer cid="C2" name="Ursula" city="Oelde" >
      <Order oid="O3" date="7/14/1999" amount="100" note="Wrap it blue white red">
          <Urgency>Important</Urgency>
      </Order>
      <Order oid="O4" date="1/20/1996" amount="10000"/>
   </Customer>
</root>
';
-- Create an internal representation of the XML document.
EXEC sp_xml_preparedocument @idoc OUTPUT, @doc;

-- Execute a SELECT statement using OPENXML rowset provider.
SELECT *
FROM OPENXML (@idoc, '/root/Customer/Order', 9)
      WITH (oid char(5),
            date datetime,
            comment ntext '@mp:xmltext');
EXEC sp_xml_removedocument @idoc;

结果如下: 由于 oid 列和 date 列已用完,因此这些列不会出现在溢出列中。

oid   date                        comment
----- --------------------------- ----------------------------------------
O1    1996-01-20 00:00:00.000     <Order amount="3.5"/>
O2    1997-04-30 00:00:00.000     <Order amount="13.4">Customer was very
                                   satisfied</Order>
O3    1999-07-14 00:00:00.000     <Order amount="100" note="Wrap it blue
                                   white red"><Urgency>
                                   Important</Urgency></Order>
O4    1996-01-20 00:00:00.000     <Order amount="10000"/>

另请参阅