如何在SQL Server中选择xsi:type属性的值?

时间:2010-03-19 12:35:24

标签: sql xml sql-server-2005 sql-server-2008 xsd

考虑这个xml文档:

DECLARE @X XML (DOCUMENT search.SearchParameters)  = '<parameters xmlns="http://www.educations.com/Search/Parameters.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <parameter xsi:type="category" categoryID="38" />
</parameters>';

我想访问“type”属性的值。

根据此blog postxsi:type属性很特殊,通常的关键字/功能无法访问。

我该怎么办?

PS:我试过

WITH XMLNAMESPACES (
 'http://www.educations.com/Search/Parameters.xsd' as p,
 'http://www.w3.org/2001/XMLSchema-instance' as xsi)
  SELECT @X.value('(/p:parameters/p:parameter/@xsi:type)[1]','nvarchar(max)')

但它不起作用。

2 个答案:

答案 0 :(得分:2)

如果没有指定集合,这对我来说很好:

DECLARE @X XML
SET @x = N' 
<parameters xmlns="http://www.educations.com/Search/Parameters.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <parameter  xsi:type="category" categoryID="38" />
</parameters>'
;

WITH    XMLNAMESPACES
        (
        'http://www.educations.com/Search/Parameters.xsd' as p,
        'http://www.w3.org/2001/XMLSchema-instance' as xsi
        )
SELECT  @X.value('(/p:parameters/p:parameter/@xsi:type)[1]','nvarchar(max)')

您能否发布search.SearchParameters的内容?

<强>更新

在架构绑定XML上,这似乎是不可能的。

您可以将列转换为freetype XML

WITH    XMLNAMESPACES
        (
        'http://www.educations.com/Search/Parameters.xsd' as p,
        'http://www.w3.org/2001/XMLSchema-instance' as xsi
        )
SELECT  CAST(@X AS XML).value('(/p:parameters/p:parameter/@xsi:type)[1]','nvarchar(max)')

(但您无法在列上使用任何XML索引),或对特定类型执行布尔检查:

WITH XMLNAMESPACES
        (
        'http://www.educations.com/Search/Parameters.xsd' as p
        )
SELECT @X.query('(/p:parameters/p:parameter)[1] instance of element(*, p:category?)')

答案 1 :(得分:0)

我知道这是一个老问题,但是我昨天遇到了这个问题,并且在SQL中找不到这个限制的明显答案。但是,如果您可以控制架构,我已经确定了解决方法。

只需在每个子类型上创建一个具有相同名称的属性(我的示例中的widgetType)。

将每个属性设置为一个简单类型的xsi:string并对其设置限制,因此唯一的值是您的子类型的名称。此外,将其设置为属性的默认值。

如果将此架构绑定到xml数据列,则始终可以查询基本上镜像xsi:type值的此属性。

我承认这不太理想,但它比将值转换为无类型并且失去索引的好处更好。

以下是一个例子:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema targetNamespace="http://tempuri.org/XMLSchema.xsd"
           elementFormDefault="qualified"
           xmlns="http://tempuri.org/XMLSchema.xsd"
           xmlns:mstns="http://tempuri.org/XMLSchema.xsd"
           xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="widget"
              type="baseWidget" />
  <xs:complexType name="baseWidget"
                  abstract="true"></xs:complexType>
  <xs:complexType name="widgetA">
    <xs:complexContent>
      <xs:extension base="baseWidget">
        <xs:attribute name="widgetType"
                      default="widgetA">
          <xs:simpleType>
            <xs:restriction base="xs:string">
              <xs:enumeration value="widgetA" />
            </xs:restriction>
          </xs:simpleType>
        </xs:attribute>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>
  <xs:complexType name="widgetB">
    <xs:complexContent>
      <xs:extension base="baseWidget">
        <xs:attribute name="widgetType"
                      default="widgetB">
          <xs:simpleType>
            <xs:restriction base="xs:string">
              <xs:enumeration value="widgetB" />
            </xs:restriction>
          </xs:simpleType>
        </xs:attribute>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>
</xs:schema>

如果要在没有widgetType属性的情况下将xml条目放入绑定到此模式的表中,则SQL会因默认值而自动添加它。它始终可供您查询。

<?xml version="1.0" encoding="utf-8"?>
<widget xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:type="widgetA"
        widgetType="widgetA"
        xmlns="http://tempuri.org/XMLSchema.xsd" />