从XML中提取元素并转换为数据集

时间:2013-12-09 16:50:13

标签: sql-server xml tsql

我试图用T-SQL粉碎一些XML。这是我的XML(有些人可能认为它来自死锁图):

<resource-list>
    <metadatalock subresource="DATA_SPACE" classid="data_space_id = 65601" dbid="7" id="lockb0553200" mode="X">
      <owner-list>
        <owner id="process806e5b88" mode="Sch-S" />
      </owner-list>
      <waiter-list>
        <waiter id="process11e2cb708" mode="Sch-M" requestType="convert" />
      </waiter-list>
    </metadatalock>
    <objectlock lockPartition="0" objid="98099390" subresource="FULL" dbid="7" objectname="" id="lockbe2cfc00" mode="Sch-M" associatedObjectId="98099390">
      <owner-list>
        <owner id="process11e2cb708" mode="Sch-M" />
      </owner-list>
      <waiter-list>
        <waiter id="process806e5b88" mode="Sch-S" requestType="wait" />
      </waiter-list>
    </objectlock>
  </resource-list>

我想要的是为每个孩子提取一个包含行的数据集(从那里我相当自信我可以使用value()函数进一步粉碎它)。换句话说,我想要这个1列,2行数据集:

 <metadatalock subresource="DATA_SPACE" classid="data_space_id = 65601" dbid="7" id="lockb0553200" mode="X">
   <owner-list>
     <owner id="process806e5b88" mode="Sch-S" />
   </owner-list>
   <waiter-list>
     <waiter id="process11e2cb708" mode="Sch-M" requestType="convert" />
   </waiter-list>
 </metadatalock>
 <objectlock lockPartition="0" objid="98099390" subresource="FULL" dbid="7" objectname="" id="lockbe2cfc00" mode="Sch-M" associatedObjectId="98099390">
   <owner-list>
     <owner id="process11e2cb708" mode="Sch-M" />
   </owner-list>
   <waiter-list>
     <waiter id="process806e5b88" mode="Sch-S" requestType="wait" />
   </waiter-list>
 </objectlock>

(我可能没有解释过这个,基本上我想要第1行中的metadatalock节点和第2行中的objectlock节点。)

这是我到目前为止所拥有的:

SELECT  XEventData.XEvent.query('/')
FROM    #resourceList
CROSS APPLY [resource-list].nodes('//resource-list/') AS XEventData ( XEvent )

但只返回错误:

  

Msg 9341,Level 16,State 1,Line 3
  XQuery [#resourceList.resource-list.nodes()]:''附近的语法错误,   期待一步表达。

因此我有点卡住了。我认为我在CROSS APPLY中使用nodes()是正确的道路,但我无法得到我需要的东西。

有人可以帮忙吗?

3 个答案:

答案 0 :(得分:1)

答案 1 :(得分:1)

感谢马丁史密斯留下评论,其中包含一个链接,引导我找到这个解决方案:

DECLARE @xml XML = '<resource-list>
  <metadatalock subresource="DATA_SPACE" classid="data_space_id = 65601" dbid="7" id="lockb0553200" mode="X">
    <owner-list>
      <owner id="process806e5b88" mode="Sch-S" />
    </owner-list>
    <waiter-list>
      <waiter id="process11e2cb708" mode="Sch-M" requestType="convert" />
    </waiter-list>
  </metadatalock>
  <objectlock lockPartition="0" objid="98099390" subresource="FULL" dbid="7" objectname="" id="lockbe2cfc00" mode="Sch-M" associatedObjectId="98099390">
    <owner-list>
      <owner id="process11e2cb708" mode="Sch-M" />
    </owner-list>
    <waiter-list>
      <waiter id="process806e5b88" mode="Sch-S" requestType="wait" />
    </waiter-list>
  </objectlock>
</resource-list>'
IF OBJECT_ID('tempdb..#resourceList') IS NOT NULL
    DROP TABLE #resourceList;
SELECT  [resource-list]=@xml
INTO    #resourceList

SELECT  MainLock.Process.query('.') AS node
FROM    #resourceList
CROSS APPLY [resource-list].nodes('//resource-list') AS Lock ( List )
CROSS APPLY Lock.List.nodes('*') AS MainLock (Process)

基本上只需再次交叉申请。我也不知道.nodes('*')也非常有用。

答案 2 :(得分:0)

实际上,不需要第二个CROSS APPLY ... NODES():

SELECT  Lock.List.query('.') AS node
FROM    #resourceList
CROSS APPLY [resource-list].nodes('/resource-list/*') AS Lock (List)

ML