2012-06-12 2 views
1

기존 요소와 특성이 아니라 "xml 형식의 목록"형식으로 배열되기 때문에 비정상적인 레이아웃을 가진 XML 파일을 파쇄하려고합니다. :XML 노드 내에서 xsql where tsql where 절

<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 : name = 'Fruit'과 같이"ns : data from x에서 선택 "과 같습니다. 과거에는 트리에서 원했던 비트의 위치를 ​​가리키는 싱글 톤 번호 매기기를 사용하여이 작업을 수행 할 수있었습니다. 그러나이 경우 확장 된 필드의 수는 가변적이며 시퀀스가 ​​변경되므로 얻을 수있는 유일한 방법은 원하는 노드는 원하는 이름/값 쌍을 지정하는 것입니다.

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 

답변

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) 
+0

브릴리언트! 고마워요. 미카엘. 그것은 100 % 효과가 있으며 바닥에 교차 적용을 추가하여 필드 목록을 확장 할 수 있음을 알았습니다. 정확히 내가 필요로하는 것. – brynn

+0

후속 질문 : 나는 1 년 이상 위의 내용을 한 번도 사용하지 않고 있습니다. 그러나 이제는 SQL2008 R2로 업그레이드하고 SSIS의 스크립트를 테스트하는 동안 오류가 발생합니다. "쿼리 프로세서에 내부 리소스가 부족하여 쿼리 계획을 생성 할 수 없었습니다. 이것은 매우 드문 경우이며 매우 복잡한 쿼리 나 쿼리에만 필요합니다. 매우 많은 수의 테이블 또는 파티션을 참조합니다. 쿼리를 단순화하십시오. " 나는 12 개의 십자가가 적용되는 셀렉트 중 하나에 그것을 찾아 냈다. 그래서 나는 그것에 만족하지 않는다. 이 문제를 해결할 수있는 아이디어가 있습니까? – brynn

+0

... 그 동안 나는 위의 두 개의 배치로 분할 했으므로 교차 적용이 적습니다. – brynn