从SOAP xml响应中获取详细信息

时间:2016-05-04 05:58:42

标签: python xml soap xml-parsing

我正在使用xmltodict库解析SOAP响应。

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
    <ns2:MultiAvailabilityResponse xmlns:ns2="http://www.derbysoft.com/doorway" Status="Successful" Token="187be58c62c2f2515b5d78ee">
        <ns2:Availabilities>
            <ns2:Availability CurrencyCode="GBP" HotelCode="HY-LONGE">
                <ns2:GuestCount AdultCount="1" ChildCount="0"/>
                <ns2:RoomTypes>
                    <ns2:RoomType RoomTypeCode="KING" RoomTypeName="Andaz King">
                        <ns2:RoomTypeDescription>A 29-square-metre room ,Modern furnishings include oversized work desk, plus bathroom with fast-fill tub and heated towel rail.</ns2:RoomTypeDescription>
                    </ns2:RoomType>
                    <ns2:RoomType RoomTypeCode="TWIN" RoomTypeName="Andaz Twin">
                        <ns2:RoomTypeDescription>A 29-square-metre room ,Modern furnishings include oversized work desk, plus bathroom with fast-fill tub and heated towel rail.</ns2:RoomTypeDescription>
                    </ns2:RoomType>
                    <ns2:RoomType RoomTypeCode="QUEN" RoomTypeName="Andaz Queen">
                        <ns2:RoomTypeDescription>A 26-square-metre room ,Modern furnishings include oversized work desk, plus bathroom with fast-fill tub and heated towel rail.</ns2:RoomTypeDescription>
                    </ns2:RoomType>
                </ns2:RoomTypes>
                <ns2:RatePlans>
                    <ns2:RatePlan RatePlanCode="49584WADPF2" RatePlanName="Advance Purchase">
                        <ns2:RatePlanDescription>Advance Purchase</ns2:RatePlanDescription>
                    </ns2:RatePlan>
                    <ns2:RatePlan RatePlanCode="49584WADPF" RatePlanName="Advance Purchase">
                        <ns2:RatePlanDescription>Advance Purchase</ns2:RatePlanDescription>
                    </ns2:RatePlan>
                    <ns2:RatePlan RatePlanCode="49584IPRTF" RatePlanName="Partner Rate">
                        <ns2:RatePlanDescription>Partner Rate</ns2:RatePlanDescription>
                    </ns2:RatePlan>
                </ns2:RatePlans>
                <ns2:RoomRates>
                    <ns2:RoomRate RatePlanCode="49584WADPF2" RoomTypeCode="KING">
                        <ns2:Rates>
                            <ns2:Rate AmountAfterTax="249.900" AmountBeforeTax="249.900" EffectiveDate="2016-05-05" ExpireDate="2016-05-06"/>
                        </ns2:Rates>
                        <ns2:Fees>
                            <ns2:Fee Amount="0.000" ChargeType="Tax" Type="Exclusive" Unit="PER_ROOM_PER_NIGHT"/>
                        </ns2:Fees>
                    </ns2:RoomRate>
                    <ns2:RoomRate RatePlanCode="49584WADPF2" RoomTypeCode="TWIN">
                        <ns2:Rates>
                            <ns2:Rate AmountAfterTax="249.900" AmountBeforeTax="249.900" EffectiveDate="2016-05-05" ExpireDate="2016-05-06"/>
                        </ns2:Rates>
                        <ns2:Fees>
                            <ns2:Fee Amount="0.000" ChargeType="Tax" Type="Exclusive" Unit="PER_ROOM_PER_NIGHT"/>
                        </ns2:Fees>
                    </ns2:RoomRate>
                    <ns2:RoomRate RatePlanCode="49584WADPF" RoomTypeCode="QUEN">
                        <ns2:Rates>
                            <ns2:Rate AmountAfterTax="249.900" AmountBeforeTax="249.900" EffectiveDate="2016-05-05" ExpireDate="2016-05-06"/>
                        </ns2:Rates>
                        <ns2:Fees>
                            <ns2:Fee Amount="0.000" ChargeType="Tax" Type="Exclusive" Unit="PER_ROOM_PER_NIGHT"/>
                        </ns2:Fees>
                    </ns2:RoomRate>
                </ns2:RoomRates>
            </ns2:Availability>
            <ns2:Availability CurrencyCode="USD" HotelCode="HY-CHIRC">
                <ns2:GuestCount AdultCount="1" ChildCount="0"/>
                <ns2:RoomTypes>
                    <ns2:RoomType RoomTypeCode="JRSQ" RoomTypeName="JR SUITE 2 QUEEN BEDS">
                        <ns2:RoomTypeDescription>Rest in sublime comfort on one of two queen signature Hyatt Grand Beds®, fitted with fine linens, down blanket and plump pillows.</ns2:RoomTypeDescription>
                    </ns2:RoomType>
                    <ns2:RoomType RoomTypeCode="CLBD" RoomTypeName="REG CLUB 2 DOUBLE BEDS">
                        <ns2:RoomTypeDescription>one King or two double-sized Hyatt Grand Beds, fitted with luxurious linens, a down blanket and plush pillows</ns2:RoomTypeDescription>
                    </ns2:RoomType>
                </ns2:RoomTypes>
                <ns2:RatePlans>
                    <ns2:RatePlan RatePlanCode="49584IPRTF" RatePlanName="Partner Rate">
                        <ns2:RatePlanDescription>Partner Rate</ns2:RatePlanDescription>
                        <ns2:CancelPolicy NonRefundable="true">
                            <ns2:CancelPenalties/>
                        </ns2:CancelPolicy>
                    </ns2:RatePlan>
                    <ns2:RatePlan RatePlanCode="49584WPAWAF" RatePlanName="Bed and Breakfast">
                        <ns2:RatePlanDescription>Bed and Breakfast</ns2:RatePlanDescription>
                        <ns2:CancelPolicy NonRefundable="true">
                            <ns2:CancelPenalties/>
                        </ns2:CancelPolicy>
                    </ns2:RatePlan>
                </ns2:RatePlans>
                <ns2:RoomRates>
                    <ns2:RoomRate RatePlanCode="49584IPRTF" RoomTypeCode="JRSQ">
                        <ns2:Rates>
                            <ns2:Rate AmountAfterTax="543.134" AmountBeforeTax="466.650" EffectiveDate="2016-05-05" ExpireDate="2016-05-06"/>
                        </ns2:Rates>
                        <ns2:Fees>
                            <ns2:Fee ChargeType="Tax" Percent="16.390" Type="Exclusive"/>
                        </ns2:Fees>
                    </ns2:RoomRate>
                    <ns2:RoomRate RatePlanCode="49584IPRTF" RoomTypeCode="CLBD">
                        <ns2:Rates>
                            <ns2:Rate AmountAfterTax="370.004" AmountBeforeTax="317.900" EffectiveDate="2016-05-05" ExpireDate="2016-05-06"/>
                        </ns2:Rates>
                        <ns2:Fees>
                            <ns2:Fee ChargeType="Tax" Percent="16.390" Type="Exclusive"/>
                        </ns2:Fees>
                    </ns2:RoomRate>
                    <ns2:RoomRate RatePlanCode="49584IPRTF" RoomTypeCode="VW2Q">
                        <ns2:Rates>
                            <ns2:Rate AmountAfterTax="325.485" AmountBeforeTax="279.650" EffectiveDate="2016-05-05" ExpireDate="2016-05-06"/>
                        </ns2:Rates>
                        <ns2:Fees>
                            <ns2:Fee ChargeType="Tax" Percent="16.390" Type="Exclusive"/>
                        </ns2:Fees>
                    </ns2:RoomRate>
                </ns2:RoomRates>
            </ns2:Availability>
        </ns2:Availabilities>
    </ns2:MultiAvailabilityResponse>
</SOAP-ENV:Body>

以下是我从SOAP响应中获取所需详细信息的代码:

def listify(obj):
"""To convert each element of SOAP into a list, so processing of response would be easy."""
if isinstance(obj, list):
    return obj
return [obj]


def search_hotels_formatted_response(soap):
    """Parse the response."""
    soap = xmltodict.parse(soap, process_namespaces=True)

    # Deal with namespaces
    env = 'http://schemas.xmlsoap.org/soap/envelope/:'
    doorway = 'http://www.derbysoft.com/doorway:'

    availability = listify(
    soap[env + 'Envelope']
        [env + 'Body']
        [doorway + 'MultiAvailabilityResponse']
        [doorway + 'Availabilities']
        [doorway + 'Availability'])

    # Intermediate data structure to hold room names
    names = {
    roomtype['@RoomTypeCode']: roomtype['@RoomTypeName']
    for _availability in availability
    for roomtype in listify(_availability
                            [doorway + 'RoomTypes']
                            [doorway + 'RoomType'])
}

    return_dict = {
    'ibp': 'dbs',
    'rL': sorted([
        {
            'rtc': roomrate['@RoomTypeCode'],
            'rpc': roomrate['@RatePlanCode'],
            'rtn': names[roomrate['@RoomTypeCode']],
            'rmt': rate['@AmountBeforeTax'],
            'cur': _availability['@CurrencyCode'],
            'ttc': float(rate['@AmountAfterTax']) - float(rate['@AmountBeforeTax']),
            'egc': 0,
            'long': ''

        }
        for _availability in availability
        for roomrate in listify(_availability
                                [doorway + 'RoomRates']
                                [doorway + 'RoomRate'])
        for rate in listify(roomrate
                            [doorway + 'Rates']
                            [doorway + 'Rate'])],
        key=lambda x: float(x['rmt'])),
    'hc': _availability['@HotelCode'],
    'hn': ''
}

    return return_dict

我能够将SOAP消息中所需的详细信息转换为所需的Dictionary格式。但是,我在获取上面共享的此特定SOAP消息的详细信息时遇到了问题。在所有其他情况下,我只是得到了具有不同组合数量的单个酒店的响应,但在这个SOAP响应中我有两个酒店,我的解析代码同时从两个酒店获取房间的价格并对其进行排序。但是,我想在第一家酒店选择排序,然后在第二家酒店选择。酒店的数量可能会有所不同,因此尽量提供通用的解决方案,无论酒店数量多少都可以使用。

任何帮助都会受到重视。谢谢!

2 个答案:

答案 0 :(得分:1)

考虑使用XSLT简化XML,这是专门用于转换XML文档的声明性编程语言。 Python可以使用lxml模块运行XSLT 1.0。从那里将变换后的树解析为带有xmltodict的字典,可以进一步解析为json。所有三个输出都包含在下面:

XSLT 脚本(另存为.xsl文件,在.py脚本中引用)

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
               xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
               xmlns:ns2="http://www.derbysoft.com/doorway">
<xsl:output version="1.0" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*"/>

  <!-- Response Level -->
  <xsl:template match="ns2:MultiAvailabilityResponse">
    <Responses>      
      <xsl:apply-templates select="ns2:Availabilities"/>
    </Responses>
  </xsl:template>

  <xsl:template match="ns2:Availabilities">
    <xsl:apply-templates select="ns2:Availability">
      <xsl:sort select="@CurrencyCode" order="descending"/>
    </xsl:apply-templates>      
  </xsl:template>

  <!-- Hotel Level -->
  <xsl:template match="ns2:Availability">    
    <Hotel>      
      <xsl:apply-templates select="ns2:RoomRates"/>
    </Hotel>
  </xsl:template>

  <!-- Room Rates Level -->
  <xsl:template match="ns2:RoomRates">        
    <xsl:apply-templates select="ns2:RoomRate">          
      <xsl:sort select="descendant::ns2:Rate/@AmountBeforeTax"
                order="ascending" data-type="number"/>
    </xsl:apply-templates>    
  </xsl:template>

  <!-- Room Rate Level -->
  <xsl:template match="ns2:RoomRate">
    <RoomRate>      
      <ibp>dbs</ibp>
      <rL><xsl:apply-templates select="ns2:Rates"/></rL>
      <hc><xsl:value-of select="ancestor::ns2:Availability/@HotelCode"/></hc>
      <hn></hn>
    </RoomRate>
  </xsl:template>  

  <!-- Rates Level -->
  <xsl:template match="ns2:Rates/*">    
    <xsl:variable name="rtc" select="ancestor::ns2:RoomRate/@RoomTypeCode"/>
    <rtc><xsl:value-of select="$rtc"/></rtc>
    <rpc><xsl:value-of select="ancestor::ns2:RoomRate/@RatePlanCode"/></rpc>
    <rtn><xsl:value-of select="ancestor::ns2:Availability/ns2:RoomTypes/
                               ns2:RoomType[@RoomTypeCode=$rtc]/@RoomTypeName"/></rtn>
    <rmt><xsl:value-of select="@AmountBeforeTax"/></rmt>
    <cur><xsl:value-of select="ancestor::ns2:Availability/@CurrencyCode"/></cur>
    <ttc><xsl:value-of select="@AmountAfterTax - @AmountBeforeTax"/></ttc>
    <egc>0</egc>
    <long></long>
  </xsl:template>

</xsl:transform>

Python 脚本(输出到xml,dict和json类型)

import lxml.etree as ET
import xmltodict
import json   

# LOAD XML AND XSL
dom = ET.parse('soap.xml')
xslt = ET.parse('XSLTScript.xsl')

# TRANSFORM
transform = ET.XSLT(xslt)
newdom = transform(dom)

# NEW TREE OUTPUT
return_xml = ET.tostring(newdom, encoding='UTF-8', pretty_print=True, xml_declaration=True)
print(return_xml.decode("utf-8"))

return_dict = xmltodict.parse(return_xml)
print(return_dict)

return_json = json.dumps(return_dict, indent=4)
print(return_json)

转换的XML输出

<?xml version='1.0' encoding='UTF-8'?>
<Responses xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns2="http://www.derbysoft.com/doorway">
  <Hotel>
    <RoomRate>
      <ibp>dbs</ibp>
      <rL>
        <rtc>VW2Q</rtc>
        <rpc>49584IPRTF</rpc>
        <rtn/>
        <rmt>279.650</rmt>
        <cur>USD</cur>
        <ttc>45.835</ttc>
        <egc>0</egc>
        <long/>
      </rL>
      <hc>HY-CHIRC</hc>
      <hn/>
    </RoomRate>
    <RoomRate>
      <ibp>dbs</ibp>
      <rL>
        <rtc>CLBD</rtc>
        <rpc>49584IPRTF</rpc>
        <rtn>REG CLUB 2 DOUBLE BEDS</rtn>
        <rmt>317.900</rmt>
        <cur>USD</cur>
        <ttc>52.104</ttc>
        <egc>0</egc>
        <long/>
      </rL>
      <hc>HY-CHIRC</hc>
      <hn/>
    </RoomRate>
    <RoomRate>
      <ibp>dbs</ibp>
      <rL>
        <rtc>JRSQ</rtc>
        <rpc>49584IPRTF</rpc>
        <rtn>JR SUITE 2 QUEEN BEDS</rtn>
        <rmt>466.650</rmt>
        <cur>USD</cur>
        <ttc>76.484</ttc>
        <egc>0</egc>
        <long/>
      </rL>
      <hc>HY-CHIRC</hc>
      <hn/>
    </RoomRate>
  </Hotel>
  <Hotel>
    <RoomRate>
      <ibp>dbs</ibp>
      <rL>
        <rtc>KING</rtc>
        <rpc>49584WADPF2</rpc>
        <rtn>Andaz King</rtn>
        <rmt>249.900</rmt>
        <cur>GBP</cur>
        <ttc>0</ttc>
        <egc>0</egc>
        <long/>
      </rL>
      <hc>HY-LONGE</hc>
      <hn/>
    </RoomRate>
    <RoomRate>
      <ibp>dbs</ibp>
      <rL>
        <rtc>TWIN</rtc>
        <rpc>49584WADPF2</rpc>
        <rtn>Andaz Twin</rtn>
        <rmt>249.900</rmt>
        <cur>GBP</cur>
        <ttc>0</ttc>
        <egc>0</egc>
        <long/>
      </rL>
      <hc>HY-LONGE</hc>
      <hn/>
    </RoomRate>
    <RoomRate>
      <ibp>dbs</ibp>
      <rL>
        <rtc>QUEEN</rtc>
        <rpc>49584WADPF</rpc>
        <rtn>Andaz Queen</rtn>
        <rmt>249.900</rmt>
        <cur>GBP</cur>
        <ttc>0</ttc>
        <egc>0</egc>
        <long/>
      </rL>
      <hc>HY-LONGE</hc>
      <hn/>
    </RoomRate>
  </Hotel>
</Responses>

Python Dictionary

OrderedDict([('Responses', OrderedDict([('@xmlns:SOAP-ENV', 'http://schemas.xmlsoap.org/soap/envelope/'), 
('@xmlns:ns2', 'http://www.derbysoft.com/doorway'), ('Hotel', [OrderedDict([('RoomRate', [OrderedDict([('ibp', 'dbs'), 
('rL', OrderedDict([('rtc', 'VW2Q'), ('rpc', '49584IPRTF'), ('rtn', None), ('rmt', '279.650'), ('cur', 'USD'), 
('ttc', '45.835'), ('egc', '0'), ('long', None)])), ('hc', 'HY-CHIRC'), ('hn', None)]), OrderedDict([('ibp', 'dbs'), 
('rL', OrderedDict([('rtc', 'CLBD'), ('rpc', '49584IPRTF'), ('rtn', 'REG CLUB 2 DOUBLE BEDS'), ('rmt', '317.900'), 
('cur', 'USD'), ('ttc', '52.104'), ('egc', '0'), ('long', None)])), ('hc', 'HY-CHIRC'), ('hn', None)]), 
OrderedDict([('ibp', 'dbs'), ('rL', OrderedDict([('rtc', 'JRSQ'), ('rpc', '49584IPRTF'), ('rtn', 'JR SUITE 2 QUEEN BEDS'), 
('rmt', '466.650'), ('cur', 'USD'), ('ttc', '76.484'), ('egc', '0'), ('long', None)])), ('hc', 'HY-CHIRC'), 
('hn', None)])])]), OrderedDict([('RoomRate', [OrderedDict([('ibp', 'dbs'), ('rL', OrderedDict([('rtc', 'KING'), 
('rpc', '49584WADPF2'), ('rtn', 'Andaz King'), ('rmt', '249.900'), ('cur', 'GBP'), ('ttc', '0'), ('egc', '0'), 
('long', None)])), ('hc', 'HY-LONGE'), ('hn', None)]), OrderedDict([('ibp', 'dbs'), ('rL', OrderedDict([('rtc', 'TWIN'), 
('rpc', '49584WADPF2'), ('rtn', 'Andaz Twin'), ('rmt', '249.900'), ('cur', 'GBP'), ('ttc', '0'), ('egc', '0'), 
('long', None)])), ('hc', 'HY-LONGE'), ('hn', None)]), OrderedDict([('ibp', 'dbs'), ('rL', OrderedDict([('rtc', 'QUEEN'), 
('rpc', '49584WADPF'), ('rtn', 'Andaz Queen'), ('rmt', '249.900'), ('cur', 'GBP'), ('ttc', '0'), ('egc', '0'), 
('long', None)])), ('hc', 'HY-LONGE'), ('hn', None)])])])])]))])

JSON输出

{
     "Responses": {
          "@xmlns:SOAP-ENV": "http://schemas.xmlsoap.org/soap/envelope/",
          "@xmlns:ns2": "http://www.derbysoft.com/doorway",
          "Hotel": [
               {
                    "RoomRate": [
                         {
                              "ibp": "dbs",
                              "rL": {
                                   "rtc": "VW2Q",
                                   "rpc": "49584IPRTF",
                                   "rtn": null,
                                   "rmt": "279.650",
                                   "cur": "USD",
                                   "ttc": "45.835",
                                   "egc": "0",
                                   "long": null
                              },
                              "hc": "HY-CHIRC",
                              "hn": null
                         },
                         {
                              "ibp": "dbs",
                              "rL": {
                                   "rtc": "CLBD",
                                   "rpc": "49584IPRTF",
                                   "rtn": "REG CLUB 2 DOUBLE BEDS",
                                   "rmt": "317.900",
                                   "cur": "USD",
                                   "ttc": "52.104",
                                   "egc": "0",
                                   "long": null
                              },
                              "hc": "HY-CHIRC",
                              "hn": null
                         },
                         {
                              "ibp": "dbs",
                              "rL": {
                                   "rtc": "JRSQ",
                                   "rpc": "49584IPRTF",
                                   "rtn": "JR SUITE 2 QUEEN BEDS",
                                   "rmt": "466.650",
                                   "cur": "USD",
                                   "ttc": "76.484",
                                   "egc": "0",
                                   "long": null
                              },
                              "hc": "HY-CHIRC",
                              "hn": null
                         }
                    ]
               },
               {
                    "RoomRate": [
                         {
                              "ibp": "dbs",
                              "rL": {
                                   "rtc": "KING",
                                   "rpc": "49584WADPF2",
                                   "rtn": "Andaz King",
                                   "rmt": "249.900",
                                   "cur": "GBP",
                                   "ttc": "0",
                                   "egc": "0",
                                   "long": null
                              },
                              "hc": "HY-LONGE",
                              "hn": null
                         },
                         {
                              "ibp": "dbs",
                              "rL": {
                                   "rtc": "TWIN",
                                   "rpc": "49584WADPF2",
                                   "rtn": "Andaz Twin",
                                   "rmt": "249.900",
                                   "cur": "GBP",
                                   "ttc": "0",
                                   "egc": "0",
                                   "long": null
                              },
                              "hc": "HY-LONGE",
                              "hn": null
                         },
                         {
                              "ibp": "dbs",
                              "rL": {
                                   "rtc": "QUEEN",
                                   "rpc": "49584WADPF",
                                   "rtn": "Andaz Queen",
                                   "rmt": "249.900",
                                   "cur": "GBP",
                                   "ttc": "0",
                                   "egc": "0",
                                   "long": null
                              },
                              "hc": "HY-LONGE",
                              "hn": null
                         }
                    ]
               }
          ]
     }
}

答案 1 :(得分:0)

您正在从所有房价结果(尽管所有酒店)创建列表理解,但酒店代码不在任何类型的循环之内,与列表位于同一级别。 所以,你总会得到一家(最后一家)酒店。

在代码中:

 'hc': _availability['@HotelCode'],

变量_可用性是前一循环的最后一次出现&#34;对于可用性的#availability&#34;。循环是正常的&#39;对于块,它甚至不会在那里定义。

在我看来,这种复杂的数据结构非常难以阅读和使用,也许您应该考虑OOP方法与对象属性中的数据。

如果你坚持使用这样的数据结构,你可以这样做:

def search_hotels_formatted_response(soap):
    """Parse the response."""
    soap = xmltodict.parse(soap, process_namespaces=True)

    # Deal with namespaces
    env = 'http://schemas.xmlsoap.org/soap/envelope/:'
    doorway = 'http://www.derbysoft.com/doorway:'

    availability = listify(
    soap[env + 'Envelope']
        [env + 'Body']
        [doorway + 'MultiAvailabilityResponse']
        [doorway + 'Availabilities']
        [doorway + 'Availability'])

    # Intermediate data structure to hold room names
    names = {
    roomtype['@RoomTypeCode']: roomtype['@RoomTypeName']
    for _availability in availability
    for roomtype in listify(_availability
                            [doorway + 'RoomTypes']
                            [doorway + 'RoomType'])
}

    # Intermediate data structure to hold rates
    rates = {
    rate['@RoomTypeCode']: rate
    for _availability in availability
    for rate in listify(_availability
                            [doorway + 'RoomRates']
                            [doorway + 'RoomRate'])
}

    return_list = []
    for _availability in availability:
        return_list.append({
    'ibp': 'dbs',
    'rL': sorted([
        {
            'rtc': rates[roomtype['@RoomTypeCode']]['@RoomTypeCode'],
            'rpc': rates[roomtype['@RoomTypeCode']]['@RatePlanCode'],
            'rtn': names[rates[roomtype['@RoomTypeCode']]['@RoomTypeCode']],
            'rmt': rates[roomtype['@RoomTypeCode']][doorway + 'Rates'][doorway + 'Rate']['@AmountBeforeTax'],
            'cur': _availability['@CurrencyCode'],
            'ttc': float(rates[roomtype['@RoomTypeCode']][doorway + 'Rates'][doorway + 'Rate']['@AmountAfterTax']) - float(rates[roomtype['@RoomTypeCode']][doorway + 'Rates'][doorway + 'Rate']['@AmountBeforeTax']),
            'egc': 0,
            'long': '',
        }
        for roomtype in listify(_availability
                            [doorway + 'RoomTypes']
                            [doorway + 'RoomType'])],
        key=lambda x: float(x['rmt'])),
    'hc': _availability['@HotelCode'],
    'hn': ''
})

    return return_list