使用 nokogiri(带命名空间)从 xml 文件中读取数据

Read data from xml file using nokogiri (with namespace)

我想读取xml数据(下面提供的xml数据)并放入哈希数组下面是我测试过的程序,我可以读取[=23=的节点] 但不知道如何获取

的元素
require 'nokogiri'
require 'open-uri'

doc = Nokogiri::XML(File.read("data.xml"))
status_group = doc.xpath('//source:HotelRooms/*', 'source' => 'http://example.com')
# this working and I can get the element of the xml below

从上面我可以得到 status_group 元素, 我的问题是如何读取每个元素数据并将其放入哈希数组中以便读取数据 我正在关注 的回答,但仍然收到错误

row_hash = status_group.map{ |row|
  {
    RoomTypeName:  row.at('RoomTypeName').text,
    RoomTax:       row.at('RoomTax').text,
  }
}

这个data.xml数据

    <HotelRoomAvailabilityResponse xmlns="http://example.com">
        <Status>
            <StatusCode>01</StatusCode>
            <Description>Successful: AvailableHotelRoom Successful</Description>
        </Status>
        <ResultIndex>1</ResultIndex>
        <HotelRooms>
            <HotelRoom>
                <RoomIndex>1</RoomIndex>
                <RoomTypeName>Superior - Double</RoomTypeName>
                <Inclusion/>
                <RoomTypeCode>x1</RoomTypeCode>
                <RatePlanCode>y1</RatePlanCode>
                <RoomRate IsPackageRate="false" B2CRates="false" AgentMarkUp="0.00" Currency="USD" RoomFare="87.54" RoomTax="18.36" PrefPrice="1412040.00" TotalFare="105.90" PrefCurrency="IDR">
                    <DayRates>
                        <DayRate Date="2018-12-30T00:00:00" BaseFare="29.17950000"/>
                        <DayRate Date="2018-12-31T00:00:00" BaseFare="29.17950000"/>
                        <DayRate Date="2019-01-01T00:00:00" BaseFare="29.17950000"/>
                    </DayRates>
                    <ExtraGuestCharges>0</ExtraGuestCharges>
                    <ChildCharges>0</ChildCharges>
                    <Discount>0</Discount>
                    <OtherCharges>0</OtherCharges>
                    <ServiceTax>0</ServiceTax>
                </RoomRate>
                <RoomPromtion/>
                <Amenities/>
            </HotelRoom>
            <HotelRoom>
                <RoomIndex>2</RoomIndex>
                <RoomTypeName>Superior - Double</RoomTypeName>
                <Inclusion/>
                <RoomTypeCode>x2</RoomTypeCode>
                <RatePlanCode>y2</RatePlanCode>
                <RoomRate IsPackageRate="false" B2CRates="false" AgentMarkUp="0.00" Currency="USD" RoomFare="87.54" RoomTax="18.36" PrefPrice="1412040.00" TotalFare="105.90" PrefCurrency="IDR">
                    <DayRates>
                        <DayRate Date="2018-12-30T00:00:00" BaseFare="29.17950000"/>
                        <DayRate Date="2018-12-31T00:00:00" BaseFare="29.17950000"/>
                        <DayRate Date="2019-01-01T00:00:00" BaseFare="29.17950000"/>
                    </DayRates>
                    <ExtraGuestCharges>0</ExtraGuestCharges>
                    <ChildCharges>0</ChildCharges>
                    <Discount>0</Discount>
                    <OtherCharges>0</OtherCharges>
                    <ServiceTax>0</ServiceTax>
                </RoomRate>
                <RoomPromtion/>
                <Amenities/>
            </HotelRoom>
        </HotelRooms>
    </HotelRoomAvailabilityResponse>

row.at('RoomTax').text, 更改为

row.at('RoomRate').attribute('RoomTax').text

应该可以解决问题

require 'nokogiri'
require 'open-uri'

# doc = Nokogiri::XML(File.read("data.xml"))
data_xml = <<-EOT
<HotelRoomAvailabilityResponse xmlns="http://example.com">
    <Status>
        <StatusCode>01</StatusCode>
        <Description>Successful: AvailableHotelRoom Successful</Description>
    </Status>
    <ResultIndex>1</ResultIndex>
    <HotelRooms>
        <HotelRoom>
            <RoomIndex>1</RoomIndex>
            <RoomTypeName>Superior - Double</RoomTypeName>
            <Inclusion/>
            <RoomTypeCode>x1</RoomTypeCode>
            <RatePlanCode>y1</RatePlanCode>
            <RoomRate IsPackageRate="false" B2CRates="false" AgentMarkUp="0.00" Currency="USD" RoomFare="87.54" RoomTax="18.36" PrefPrice="1412040.00" TotalFare="105.90" PrefCurrency="IDR">
                <DayRates>
                    <DayRate Date="2018-12-30T00:00:00" BaseFare="29.17950000"/>
                    <DayRate Date="2018-12-31T00:00:00" BaseFare="29.17950000"/>
                    <DayRate Date="2019-01-01T00:00:00" BaseFare="29.17950000"/>
                </DayRates>
                <ExtraGuestCharges>0</ExtraGuestCharges>
                <ChildCharges>0</ChildCharges>
                <Discount>0</Discount>
                <OtherCharges>0</OtherCharges>
                <ServiceTax>0</ServiceTax>
            </RoomRate>
            <RoomPromtion/>
            <Amenities/>
        </HotelRoom>
        <HotelRoom>
            <RoomIndex>2</RoomIndex>
            <RoomTypeName>Superior - Double</RoomTypeName>
            <Inclusion/>
            <RoomTypeCode>x2</RoomTypeCode>
            <RatePlanCode>y2</RatePlanCode>
            <RoomRate IsPackageRate="false" B2CRates="false" AgentMarkUp="0.00" Currency="USD" RoomFare="87.54" RoomTax="18.36" PrefPrice="1412040.00" TotalFare="105.90" PrefCurrency="IDR">
                <DayRates>
                    <DayRate Date="2018-12-30T00:00:00" BaseFare="29.17950000"/>
                    <DayRate Date="2018-12-31T00:00:00" BaseFare="29.17950000"/>
                    <DayRate Date="2019-01-01T00:00:00" BaseFare="29.17950000"/>
                </DayRates>
                <ExtraGuestCharges>0</ExtraGuestCharges>
                <ChildCharges>0</ChildCharges>
                <Discount>0</Discount>
                <OtherCharges>0</OtherCharges>
                <ServiceTax>0</ServiceTax>
            </RoomRate>
            <RoomPromtion/>
            <Amenities/>
        </HotelRoom>
    </HotelRooms>
</HotelRoomAvailabilityResponse>
EOT
doc = Nokogiri::XML(data_xml)
status_group = doc.xpath('//source:HotelRooms/*', 'source' => 'http://example.com')
row_hash = status_group.map{ |row|
  {
    RoomTypeName:  row.at('RoomTypeName').text,
    RoomTax:       row.at('RoomRate').attribute('RoomTax').text,
  }
}

puts row_hash


#=>
#{:RoomTypeName=>"Superior - Double", :RoomTax=>"18.36"}
#{:RoomTypeName=>"Superior - Double", :RoomTax=>"18.36"}