0

我正在尝试//ns2:Point/ns2:pos使用 Nokogiri XML 解析器解析以下 XML 以提取 Lat Long 组合,但运气不佳。

<?xml version="1.0" encoding="UTF-8"?>
<ns1:XLS ns1:lang="en" rel="5.2.sp03" version="1.0" xmlns:ns1="http://www.opengis.net/xls">
    <ns1:ResponseHeader sessionID="wrx-rails1370997540"/>
    <ns1:Response numberOfResponses="1" requestID="10" version="1.0">
        <ns1:GeocodeResponse>
            <ns1:GeocodeResponseList numberOfGeocodedAddresses="1">
                <ns1:GeocodedAddress>
                    <ns2:Point xmlns:ns2="http://www.opengis.net/gml">
                        <ns2:pos>38.898331 -77.117273</ns2:pos>
                    </ns2:Point>
                    <ns1:Address countryCode="US">
                        <ns1:StreetAddress>
                            <ns1:Building number="4400"/>
                            <ns1:Street>Lee Hwy</ns1:Street>
                        </ns1:StreetAddress>
                        <ns1:Place type="CountrySubdivision">VA</ns1:Place>
                        <ns1:Place type="CountrySecondarySubdivision">Arlington</ns1:Place>
                        <ns1:Place type="MunicipalitySubdivision">Arlington</ns1:Place>
                        <ns1:PostalCode>22207</ns1:PostalCode>
                    </ns1:Address>
                    <ns1:GeocodeMatchCode accuracy="1.0" matchType="ADDRESS POINT LOOKUP"/>
                    <ns1:SpatialKeys>
                        <ns1:SpatialKey priority="0" val="1663355010"/>
                        <ns1:SpatialKey priority="1" val="2563322400"/>
                        <ns1:SpatialKey priority="2" val="3325185160"/>
                        <ns1:SpatialKey priority="3" val="3784086306"/>
                        <ns1:SpatialKey priority="4" val="4033029320"/>
                        <ns1:SpatialKey priority="5" val="4162373938"/>
                        <ns1:SpatialKey priority="6" val="4228264524"/>
                        <ns1:SpatialKey priority="7" val="4261514387"/>
                        <ns1:SpatialKey priority="8" val="4278215460"/>
                        <ns1:SpatialKey priority="9" val="4286585033"/>
                        <ns1:SpatialKey priority="10" val="4290774578"/>
                        <ns1:SpatialKey priority="11" val="4292870540"/>
                        <ns1:SpatialKey priority="12" val="4293918819"/>
                        <ns1:SpatialKey priority="13" val="4294443032"/>
                        <ns1:SpatialKey priority="14" val="4294705158"/>
                        <ns1:SpatialKey priority="15" val="4294836224"/>
                    </ns1:SpatialKeys>
                </ns1:GeocodedAddress>
            </ns1:GeocodeResponseList>
        </ns1:GeocodeResponse>
    </ns1:Response>
</ns1:XLS>

当我尝试以下操作时,我得到一个空数组:

doc = Nokogiri::XML(response.body);
pos = doc.xpath('//ns2:Point/ns2:pos');

我可以访问地理编码的地址元素,但是可以使用:

doc.xpath('//ns1:GeocodeResponseList/ns1:GeocodedAddress')

关于我在这里缺少什么的任何线索。由于某种原因它不喜欢名称空间的变化吗?

我的环境如下: Nokogiri 1.5.9 Java Rails 3.2.11 jRuby 1.7.4 Windows 7 Box

4

1 回答 1

0

您可以找到第一个表达式,因为 Nokogiri 在它所期望的位置找到了 XML 命名空间。命名空间不是我们通常会找到的ns2地方,所以 Nokogiri 不知道该怎么做。

有多种方法可以解决这个问题。第一个是收集文档中的命名空间,并在您进行搜索时将它们传递给 Nokogiri。Nokogiri 会自动为 XML 根目录中的命名空间执行此操作,但如果它们散布在整个文档中,则不会这样做,因此我们必须告诉它到处搜索,然后将它们传入:

namespaces = doc.collect_namespaces
namespaces # => {"xmlns:ns1"=>"http://www.opengis.net/xls", "xmlns:ns2"=>"http://www.opengis.net/gml"}
pos = doc.xpath('//ns2:Point/ns2:pos', namespaces);
pos # => [#<Nokogiri::XML::Element:0x3fe8c608ab30 name="pos" namespace=#<Nokogiri::XML::Namespace:0x3fe8c608aacc prefix="ns2" href="http://www.opengis.net/gml"> children=[#<Nokogiri::XML::Text:0x3fe8c608e1b8 "38.898331 -77.117273">]>]

另一种方法是告诉 Nokogiri 从文档中删除所有命名空间。如果您确定在文档中的各种命名空间中找到的标签名称之间没有冲突,您只想这样做:

doc.remove_namespaces!
pos = doc.xpath('//Point/pos', namespaces);
pos # => [#<Nokogiri::XML::Element:0x3fe8c608ab30 name="pos" children=[#<Nokogiri::XML::Text:0x3fe8c608e1b8 "38.898331 -77.117273">]>]

Nokogiri文档有这样的说法remove_namespaces!

但我很懒,不想处理命名空间!

懒惰==高效,所以没有判断力。:)

如果您有一个带有命名空间的 XML 文档,但更愿意完全忽略它们(并像 Tim Bray 从未发明过它们一样进行查询),那么您可以在 XML::Document 上调用 remove_namespaces 来删除所有命名空间。当然,如果文档有名称相同但名称空间不同的节点,它们现在将是模棱两可的。但是你很懒!你不在乎!

于 2013-06-16T01:17:45.993 回答