<p>考虑使用<a href="https://www.w3.org/Style/XSL/" rel="nofollow">XSLT</a>简化XML,这是一种专门用于转换XML文档的声明性编程语言。Python可以使用<code>lxml</code>模块运行xslt1.0。从那里将转换后的树解析为一个带有<code>xmltodict</code>的字典,该字典可以进一步解析为<code>json</code>。所有三个输出包括以下内容:</p>
<p><strong>XSLT</strong>脚本<em>(另存为.xsl文件,在下面的.py脚本中引用)</em></p>
<pre><code><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>
</code></pre>
<p><strong>Python</strong>Script<em>(输出到xml、dict和json类型)</em></p>
^{pr2}$
<p>转换的XML输出</p>
<pre><code><?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>
</code></pre>
<p>Python字典</p>
<pre><code>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)])])])])]))])
</code></pre>
<p>JSON输出</p>
<pre><code>{
"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
}
]
}
]
}
}
</code></pre>