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

时间:2019-01-27 19:02:18

标签: ruby-on-rails xml nokogiri

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

的元素。
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元素, 我的问题是如何读取每个元素数据并将其放入哈希数组中,以便可以读取数据 我正在追踪this SO answer的回答,但仍然收到错误

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>

1 个答案:

答案 0 :(得分:2)

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"}