2013-09-12 2 views
0

В SSMS 2008 я запускаю следующее, чтобы попытаться получить данные из узлов для удобства поиска и ограничения значений. Это XML, отправленный нам поставщиками, и нам часто нужно искать, чтобы найти отправленные сообщения и в настоящее время, он не оптимизирован для разделения данных на уровне таблицы. (это невозможно в это время). MessageStringXML - это поле типа данных XML. Я не получаю результатов из следующего запроса.Использование XQuery для анализа XML в столбце таблицы

;WITH XMLNAMESPACES(DEFAULT 'http://www.opentravel.org/OTA/2003/05') 
Select Case When MessageStringXML.value('(/OTA_HotelAvailNotifRQ/@EchoToken)[1]','varchar(255)') IS Not Null Then MessageStringXML.value('(/OTA_HotelAvailNotifRQ/@EchoToken)[1]','varchar(255)') 
      When MessageStringXML.value('(/OTA_HotelAvailNotifRS/@EchoToken)[1]','varchar(255)') IS Not Null Then MessageStringXML.value('(/OTA_HotelAvailNotifRS/@EchoToken)[1]','varchar(255)') 
      When MessageStringXML.value('(/OTA_HotelRateAmountNotifRQ/@EchoToken)[1]','varchar(255)') IS Not Null Then MessageStringXML.value('(/OTA_HotelRateAmountNotifRQ/@EchoToken)[1]','varchar(255)') 
      When MessageStringXML.value('(/OTA_HotelRateAmountNotifRS/@EchoToken)[1]','varchar(255)') IS Not Null Then MessageStringXML.value('(/OTA_HotelRateAmountNotifRS/@EchoToken)[1]','varchar(255)') 
     End as EchoToken 
     ,Toddler.value('@InvCode','varchar(255)') as RoomTypeCode 
     ,Toddler.value('@RatePlanCode','varchar(255)') as RateCode 
     ,Infant.value('@Status','varchar(255)') as 'Status' 
From #Gamma 
    Cross Apply MessageStringXML.nodes('/OTA_HotelAvailNotifRQ/AvailStatusMessages/AvailStatusMessage') AS N(Child) 
    Cross Apply Child.nodes('/StatusApplicationControl') AS O(Toddler) 
    Cross Apply Child.nodes('/RestrictionStatus') AS P(Infant) 

Ниже приведен пример сообщения XML, что я пытаюсь разобрать:

<OTA_HotelAvailNotifRQ xmlns="http://www.opentravel.org/OTA/2003/05" EchoToken="123456789" TimeStamp="2013-08-13T10:56:25.32-05:00" Target="Production" Version="1.001" PrimaryLangID="en-us"> 
    <POS> 
    <Source> 
     <RequestorID Type="18" ID="AAAAAA" /> 
    </Source> 
    </POS> 
    <AvailStatusMessages ChainCode="BB" BrandCode="CC" HotelCode="12345"> 
    <AvailStatusMessage> 
     <StatusApplicationControl Start="2014-05-11" End="2014-07-09" InvCodeApplication="InvCode" InvCode="DDD" RatePlanCodeType="RatePlanCode" RatePlanCode="EEE" RateTier="8" IsRoom="1" Override="1" /> 
     <RestrictionStatus Restriction="Master" Status="Open" /> 
    </AvailStatusMessage> 
    <AvailStatusMessage> 
     <StatusApplicationControl Start="2014-05-11" End="2014-07-09" InvCodeApplication="InvCode" InvCode="FFF" RatePlanCodeType="RatePlanCode" RatePlanCode="GGG" RateTier="9" IsRoom="1" Override="1" /> 
     <RestrictionStatus Restriction="Master" Status="Close" /> 
    </AvailStatusMessage> 
    </AvailStatusMessages> 
</OTA_HotelAvailNotifRQ> 

EDIT:

Это работает удивительно хорошо !!! Спасибо! Я не нашел очень много источников хорошей документации по этому поводу, поэтому я ценю это. Если я пытаюсь идти дальше вниз в другой XML,

<OTA_HotelAvailNotifRQ xmlns="http://www.opentravel.org/OTA/2003/05" EchoToken="34496481-1" PrimaryLangID="en-us" Target="Production" TimeStamp="2013-09-06T05:50:37.01+00:00" Version="1.002"> 
    <POS> 
    <Source> 
     <RequestorID ID="R_GoldenTulip" Type="18" /> 
    </Source> 
    </POS> 
    <AvailStatusMessages BrandCode="GT" ChainCode="GT" HotelCode="040510"> 
    <AvailStatusMessage> 
     <StatusApplicationControl End="2013-10-06" Fri="true" InvCode="ROH" InvCodeApplication="InvCode" Mon="true" RatePlanCode="EXPED1" RatePlanCodeType="RatePlanCode" Sat="true" Start="2013-10-04" Sun="true" Thur="true" Tue="true" Weds="true" /> 
     <RestrictionStatus Restriction="Master" Status="Open" /> 
    </AvailStatusMessage> 
    <AvailStatusMessage> 
     <StatusApplicationControl End="2013-10-06" Fri="true" InvCode="ROH" InvCodeApplication="InvCode" Mon="true" RatePlanCode="EXPED1" RatePlanCodeType="RatePlanCode" Sat="true" Start="2013-10-04" Sun="true" Thur="true" Tue="true" Weds="true" /> 
     <LengthsOfStay ArrivalDateBased="true" FixedPatternLength="1"> 
     <LengthOfStay MinMaxMessageType="FullPatternLOS" Time="1" TimeUnit="Day" /> 
     </LengthsOfStay> 
    </AvailStatusMessage> 
    <AvailStatusMessage> 
     <StatusApplicationControl End="2013-10-06" Fri="true" InvCode="ROH" InvCodeApplication="InvCode" Mon="true" RatePlanCode="EXPED1" RatePlanCodeType="RatePlanCode" Sat="true" Start="2013-10-04" Sun="true" Thur="true" Tue="true" Weds="true" /> 
     <LengthsOfStay ArrivalDateBased="false" FixedPatternLength="1"> 
     <LengthOfStay MinMaxMessageType="FullPatternLOS" Time="1" TimeUnit="Day" /> 
     </LengthsOfStay> 
    </AvailStatusMessage> 
    </AvailStatusMessages> 
</OTA_HotelAvailNotifRQ> 

Есть в «LengthsOfStay» узлы, которые я пытаюсь ударить теперь, мой SQL ниже. Я думаю, что это, возможно, придется делать с не все сообщения, обозначенные буквой "LengthsOfStay" узлы

;WITH XMLNAMESPACES(DEFAULT 'http://www.opentravel.org/OTA/2003/05') 

Select 
[MessageBodyID], 
Case When MessageStringXML.value('(/OTA_HotelAvailNotifRQ/@EchoToken)[1]','varchar(255)') IS Not Null Then MessageStringXML.value('(/OTA_HotelAvailNotifRQ/@EchoToken)[1]','varchar(255)') 
      When MessageStringXML.value('(/OTA_HotelAvailNotifRS/@EchoToken)[1]','varchar(255)') IS Not Null Then MessageStringXML.value('(/OTA_HotelAvailNotifRS/@EchoToken)[1]','varchar(255)') 
      When MessageStringXML.value('(/OTA_HotelRateAmountNotifRQ/@EchoToken)[1]','varchar(255)') IS Not Null Then MessageStringXML.value('(/OTA_HotelRateAmountNotifRQ/@EchoToken)[1]','varchar(255)') 
      When MessageStringXML.value('(/OTA_HotelRateAmountNotifRS/@EchoToken)[1]','varchar(255)') IS Not Null Then MessageStringXML.value('(/OTA_HotelRateAmountNotifRS/@EchoToken)[1]','varchar(255)') 
     End as EchoToken 
     ,Toddler.value('@InvCode','varchar(255)') as RoomTypeCode 
     ,Toddler.value('@Start','varchar(255)') as FromDate 
     ,Toddler.value('@End','varchar(255)') as ToDate 
     ,Toddler.value('@RatePlanCode','varchar(255)') as RateCode 
     ,Infant.value('@Status','varchar(255)') as 'Status' 
     ,Fetus.value('@ArrivalDateBased','varchar(255)') as 'FPLOS' 

From #Alpha 
    Cross Apply MessageStringXML.nodes('OTA_HotelAvailNotifRQ/AvailStatusMessages') AS N(Tween) 
    Cross Apply Tween.nodes('AvailStatusMessage') AS Q(Child) 
    Cross Apply Child.nodes('StatusApplicationControl') AS O(Toddler) 
    Cross Apply Child.nodes('RestrictionStatus') AS P(Infant) 
    Cross Apply Child.nodes('LengthsOfStay') AS R(Fetus) 
    --Cross Apply Fetus.nodes('Lengthofstay') AS S(Embryo) 

ответ

1

Изменить этот

Cross Apply Child.nodes('/StatusApplicationControl') AS O(Toddler) 
Cross Apply Child.nodes('/RestrictionStatus') AS P(Infant) 

к этому

Cross Apply Child.nodes('StatusApplicationControl') AS O(Toddler) 
Cross Apply Child.nodes('RestrictionStatus') AS P(Infant) 

или в самом деле

Cross Apply Child.nodes('./StatusApplicationControl') AS O(Toddler) 
Cross Apply Child.nodes('./RestrictionStatus') AS P(Infant) 

, и вы должны получить строки. Голый начальный / заставляет его вернуться к корню документа, чтобы найти названный вами узел. Используя ./ или без префикса, вы говорите «поиск из текущего контекста».

+0

см. Выше для редактирования. – Jacrys

+0

Это работает удивительно хорошо !!! Спасибо! Я не нашел очень много источников хорошей документации по этому поводу, поэтому я ценю это: – Jacrys

+0

@kclewis мои обычные первые две ресурсы xpath - это [эта страница MSDN] (http://msdn.microsoft.com/en-us/library/ ms256086.aspx) и [этот инструмент] (http://xpathvisualizer.codeplex.com/), но см. также [страницу с информацией о теге xpath] (http://stackoverflow.com/tags/xpath/info) и [ссылки от резидента xpath SOAP] (http://stackoverflow.com/users/36305/dimitre-novatchev) – AakashM