2015-08-20 2 views
1

В Excel:Получить информацию о узле XML?

У меня есть сценарий, который принимает адрес, который у меня есть (в A1), и просматривает этот адрес через GoogleAPI, который возвращает XML-документ.

Например, при использовании в качестве "123 Fake Street" адрес возвращает следующий XML-документ:

http://maps.googleapis.com/maps/api/geocode/xml?address=123%20fake%20street&sensor=false

Как вы можете видеть (возможно удивительно), есть больше чем один "123 fake street" там. У меня есть макрос, получающий координаты GPS от узлов Lat/Long. Как бы я захватил графство каждого? Я думал, что я мог бы использовать узел "address_component", но, как вы можете видеть, есть больше чем один такой узел на адрес:

enter image description here

Вот мой код:

Sub getXMLInfo() 
    ' Adapted from http://excel-macro.tutorialhorizon.com/vba-excel-read-data-from-xml-file/ 
    If Len(Cells(1, 1).Value) < 10 Then 
    MsgBox ("Put an address in Cell A1!!") 
    Exit Sub 
    Else 
    Call fnReadXMLByTags(Range("A1")) 
    End If 
    End Sub 

...

Function fnReadXMLByTags(address As String) As String 
    ' Part of of adapted from http://excel-macro.tutorialhorizon.com/vba-excel-read-data-from-xml-file/ 
    Dim mainWorkBook As Workbook 
    Dim mainWS As Worksheet 
    Dim altAddress As String 
    Set mainWorkBook = ActiveWorkbook 
    Set mainWS = Sheets("Sheet1") 
    mainWS.Range("A:A").Clear 
    Set oXMLFile = CreateObject("Microsoft.XMLDOM") 

    strAddress = address ' URLEncode(Address) 
    'Assemble the query string 
    strQuery = "http://maps.googleapis.com/maps/api/geocode/xml?" 
    strQuery = strQuery & "address=" & strAddress 
    strQuery = strQuery & "&sensor=false" 
    Debug.Print strQuery 
    XMLFileName = strQuery 

    oXMLFile.Load (XMLFileName) 
    Set LatitudeNodes = oXMLFile.SelectNodes("/GeocodeResponse/result/geometry/location/lat/text()") 
    Set LongitudeNodes = oXMLFile.SelectNodes("/GeocodeResponse/result/geometry/location/lng/text()") 
    Set addressNodes = oXMLFile.SelectNodes("/GeocodeResponse/result/formatted_address/text()") 
    Set countyNodes = oXMLFile.SelectNodes("/GeocodeResponse/result/address_component[1]/long_name/text()") 
    Set misc1 = oXMLFile.SelectNodes("/GeocodeResponse/result/address_component[0]/long_name/text()") 

With mainWS 
    .Range("A1,B1,C1").Interior.ColorIndex = 40 
    .Range("A1,B1,C1").Borders.Value = 1 
    .Range("A" & 1).Value = "Lookup Address: " & address 
    .Range("B" & 1).Value = "Latitude" 
    .Range("C" & 1).Value = "Longitude" 
    .Range("D1").Value = "Total Coordinates: " & LatitudeNodes.Length 

     For i = 0 To (LatitudeNodes.Length - 1) 
      Title = LatitudeNodes(i).NodeValue 
      Price = LongitudeNodes(i).NodeValue 
      altAddress = addressNodes(i).NodeValue 


     .Range("B" & i + 2).Borders.Value = 1 
     .Range("C" & i + 2).Borders.Value = 1 
     .Range("B" & i + 2).Value = Title 
     .Range("C" & i + 2).Value = Price 
     .Range("A" & i + 2).Value = altAddress 
     .Range("E" & i + 2).Value = countyNodes(i).NodeValue 
     .Range("F" & i + 2).Value = "component[0] = " & misc1(i).NodeValue 

    Next 
    'Reading the Attributes 
    Set Nodes_Attribute = oXMLFile.SelectNodes("/catalog/book") 
    For i = 0 To (Nodes_Attribute.Length - 1) 
     Attributes = Nodes_Attribute(i).getAttribute("id") 
     .Range("A" & i + 2).Borders.Value = 1 
     .Range("A" & i + 2).Value = Attributes 
    Next 

    Dim lastRow As Integer 
    lastRow = .Cells(1, 1).End(xlDown).Row 
    'https://www.google.com/maps/place//@42.8795926,-78.8762132,16z 
    .Range(.Cells(2, 4), .Cells(2, 4)).Resize(lastRow - 1, 1).FormulaR1C1 = _ 
     "=HYPERLINK(""https://www.google.com/maps/place//@""&RC[-2]&"",""&RC[-1]&"",16z/data=!3m1!4b1!4m2!3m1!1s0x0:0x0"",""Link"")" 
End With 'End the With mainWS 

End Function 

Как вы можете видеть, я пытался делать "address_component[0]" в моем misc1 узел. Это, похоже, не захватывает первый "address_component". Я новичок в XML, поэтому извиняюсь за отсутствие надлежащих соглашений об именах (так что если вы знаете, что я должен искать в XML, сообщите мне!).

Спасибо за любые идеи или советы!

Edit: Вот что результат выглядит, когда я пытаюсь получить информацию от:

Set misc1 = oXMLFile.SelectNodes("/GeocodeResponse/result/address_component[0]/long_name/text()") 
Set misc2 = oXMLFile.SelectNodes("/GeocodeResponse/result/address_component[1]/long_name/text()") 
Set misc3 = oXMLFile.SelectNodes("/GeocodeResponse/result/address_component[2]/long_name/text()") 
Set misc4 = oXMLFile.SelectNodes("/GeocodeResponse/result/address_component[3]/long_name/text()") 
Set misc5 = oXMLFile.SelectNodes("/GeocodeResponse/result/address_component[4]/long_name/text()") 
     .Range("F" & i + 2).Value = misc1(i).NodeValue 
    .Range("G" & i + 2).Value = misc2(i).NodeValue 
    .Range("H" & i + 2).Value = misc3(i).NodeValue 
    .Range("I" & i + 2).Value = misc4(i).NodeValue 
    .Range("J" & i + 2).Value = misc5(i).NodeValue 

enter image description here

Так как вы можете видеть округ не всегда в том же «узел» - Есть ли способ объяснить это?

ответ

1

Вы близко. Если вы хотите получить доступ к определенному индексу узла, вы должны поместить круглые скобки вокруг имени узла, а затем указать индекс после. В вашем случае, это было бы:

Set misc1 = oXMLFile.SelectSingleNode("(/GeocodeResponse/result/address_component)[5]/long_name/text()") 

Edit:

Чтобы выбрать long_name узел из address_component, который также имеет type узел со значением administrative_area_level_2, вы можете использовать следующие XPath:

/GeocodeResponse/result/address_component[type='administrative_area_level_2']/long_name 
+0

Ага, спасибо! Теперь, когда я могу захватить определенный индекс узла, остальная часть материала подходит ко мне, нет? Значит, похоже, что nodeIndex 5 не всегда будет округом ... Я полагаю, что нет метода «XML»/способа его определения? Я полагаю, что просто использовал VB, чтобы сделать что-то вроде: «Если в тексте nodeIndex есть * not * есть« County », тогда продолжайте искать. Else, используйте этот индекс'. – BruceWayne

+0

Hm, я получаю ошибку' Run-time error '438' - Объект не поддерживает это свойство или метод' в строке 'county = countyNodes (i) .NodeValue' после того, как я' Set countyNodes' 'Установить countyNodes = oXMLFile.SelectSingleNode ("(/ GeocodeResponse/result/address_component) [5]/long_name/text()") ' – BruceWayne

+1

Если графство всегда' administrator_area_level_2', вы можете искать 'address_component', который имеет этот тип, и возвращать' long_name 'от него. – Bond

Смежные вопросы