2011-01-03 4 views
3

address 노드가있는 소스 XML 파일이 있고 각 노드는 유효성을 검사하기 위해 zip_code 노드가 있어야합니다. 하나 이상의 노드에 zip_code (파일에 수천 개의 주소가 있음)가 없어서 스키마 유효성 검사에 실패한 파일을 받았습니다.존재하지 않는 노드에 대해 xml을 검색하는 TSQL의 더 좋은 방법

우리는 파일을 복구하고 소스로 감사 보고서를 보낼 수 있도록 우편 번호가없는 요소를 찾아야합니다.

--declare @x xml = bulkcolumn from openrowset(bulk 'x:\file.xml',single_blob) as s 
declare @x xml = N'<addresses> 
    <address><external_address_id>1</external_address_id><zip_code>53207</zip_code></address> 
    <address><external_address_id>2</external_address_id></address> 
</addresses>' 

declare @t xml = (
select @x.query('for $a in .//address 
    return 
     if ($a/zip_code) 
      then <external_address_id /> 
     else $a/external_address_id') 
) 
select x.AddressID.value('.', 'int') AddressID 
from @t.nodes('./external_address_id') x(AddressID) 
where x.AddressID.value('.', 'int') > 0 
GO 

실제로는 버그가있는 where 절입니다. 나는 null 값이 0 인 캐스팅에 의존하는 것처럼 느껴진다.하지만 제대로 작동하는지는 모르겠다. .exist 기능으로 몇 가지 변형을 시도했지만 정확한 결과를 얻을 수 없었습니다.

답변

2

당신이 그들의 <zip_code> 요소를 누락하는 노드를 찾을하려는 경우, 당신이 뭔가를 사용할 수는 :

SELECT 
    ADRS.ADR.value('(external_address_id)[1]', 'int') as 'ExtAdrID' 
FROM 
    @x.nodes('/addresses/address') as ADRS(ADR) 
WHERE 
    ADRS.ADR.exist('zip_code') = 0 

그것은 내장 된 XQuery에의 .exist() 방법 하위 노드의 존재를 확인하기 위해 사용 XML 노드 내부.

/addresses/address[zip_code] 

당신은 또한 그를 확인하려면 : 당신은 단지 당신이 zip_code 요소가 address 요소를 선택하고 있는지 확인하려면

4

, 다음 술어 필터의 기준 것을 포함하도록 XPATH를 조정

/addresses/address[zip_code[text()]] 

,536 : zip_code 요소도 값을 가지며, text() 노드가 그 사람을 선택 zip_node에 대한 조건 필터를 사용

편집 : 사실

, 나는 반대를 찾고 있어요. 지퍼가없는 노드 을 식별해야하므로 소스 데이터를 수동으로 수정할 수 있습니다. 당신이 하지을하는 address 모든 요소를 ​​식별하려면

그래서하는 zip_code을 가지고,이 같은 XPATH에 지정할 수 있습니다

/addresses/address[not(zip_code)] 
+0

+1 좋은 대답. –

+0

사실, 나는 그 반대를 찾고 있습니다. 지퍼가없는 노드를 식별해야하므로 원본 데이터를 수동으로 수정할 수 있습니다. –

+0

죄송합니다. 오해했습니다. 'zip_code '가없는'address' 요소 만 처리하는 방법에 대한 예제를 업데이트했습니다. –

관련 문제