xquery等效于XML节点中的tsql where子句

时间:2012-06-12 17:51:08

标签: xml tsql sql-server-2005 xquery

我正在尝试粉碎具有不寻常布局的XML文件,因为项目没有使用传统元素和属性进行排列,而是采用一种“xml中的列表”格式:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> 
<SOAP-ENV:Body> 
<ns:Lists xmlns:ns="urn:Listing"> 
    <ns:items>
      <ns:listRef>List1</ns:listRef> 
      <ns:name>Test list items</ns:name> 
      <ns:extendedFields>
         <ns:extendedField>
             <ns:name>Fruit</ns:name> 
             <ns:data>Apple</ns:data> 
      </ns:extendedField>
      <ns:extendedField>
             <ns:name>Vegetable</ns:name> 
              <ns:data /> 
      </ns:extendedField>
      <ns:extendedField>
              <ns:name>Sweet</ns:name> 
             <ns:data>Crunchie</ns:data> 
      </ns:extendedField>
    </ns:extendedFields>
    </ns:items>
</ns:Lists>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

我在下面尝试了XQuery的变体,但是我没有做对。我需要做的是Xpath相当于“选择ns:来自x的数据,其中ns:name ='Fruit'”。在过去,我能够使用单例编号指向我想要在树上的位的位置,但在这种情况下,extendedFields的数量是可变的,并且序列更改,因此唯一的方法是您想要的节点将指定您想要的名称/值对。

DECLARE @x xml 
 SET @x = 
(   SELECT xml_data_column   
   FROM dbo.Table   
 WHERE xmlFileName = 'D:\XML_list.xml'); 

;WITH XMLNAMESPACES('urn:Listing' AS ns) 
SELECT t.c.value('../ns:listRef[1]', 'varchar(20)') listRef  
, t.c.value('../ns:name[1]', 'varchar(20)') name  
, t.c.value('/.', 'varchar(30)') ext1b
, t.c.value('ns:extendedField[1]/ns:name[1]', 'varchar(30)') name1
, t.c.value('ns:extendedField[1]/ns:data[1]', 'varchar(30)') data1
, t.c.value('ns:extendedField[2]/ns:name[1]', 'varchar(30)') name2
, t.c.value('ns:extendedField[2]/ns:data[1]', 'varchar(30)') data2
, t.c.value('ns:extendedField[3]/ns:name[1]', 'varchar(30)') name3
, t.c.value('ns:extendedField[3]/ns:data[1]', 'varchar(30)') data3
FROM  @x.nodes('//ns:Lists/ns:items/ns:extendedFields[1]') AS t(c)

所以如果我想看看这个人选择了什么水果项目,那么我希望输出看起来像:

listRef, name,                Fruit 
List1,   Test list items,   Apple

1 个答案:

答案 0 :(得分:0)

with xmlnamespaces('urn:Listing' AS ns)
select L.X.value('ns:listRef[1]', 'varchar(20)') as listRef,
       L.X.value('ns:name[1]', 'varchar(20)') as name,
       E.X.value('ns:data[1]', 'varchar(30)') as Fruit
from @x.nodes('//ns:Lists/ns:items') as L(X)
  cross apply L.X.nodes('ns:extendedFields/ns:extendedField[ns:name = "Fruit"]') as E(X)