Domanda

I am running the following in SSMS 2008 to try to get data out of the nodes for ease of searching and limiting values. This is XML sent to us by vendors and we often need to search to find messages sent and currently, it is not optimized to split the data out at a table level. (this is not possible at this time). MessageStringXML is a field of XML datatype. I get no results from the following query.

;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)

Below is an example of an XML message that I am trying to parse:

<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:

That works amazingly well!!! Thank you! I haven't found very many sources of good documentation on this, so I appreciate it. If I try to go down further into another 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>

There are the "LengthsOfStay" nodes that I am trying to hit now, my SQL is below. I think it may have to do with not all messages having the "LengthsOfStay" nodes

;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)
È stato utile?

Soluzione

Change this

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

to this

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

or indeed

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

and you should get rows. The bare initial / makes it go back to the document root to look for the node you name. By using ./ or no prefix, you say 'search from the current context'.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top