0
votes

I'm a newbie to Xpath and can't solve this for a few hours now. I've got an xml response from maps.googleapis.com/maps/api/geocode/xml?latlng=51,0 which contains multiple "results", and each "result" may contain multiple "address_component". Response is parsed in specific prog, and it can't use concatenations like

/GeocodeResponse[1]/status[text()='OK'] | /GeocodeResponse[1]/result[1]/type | /GeocodeResponse[1]/result[1]/address_component[1]...

and it can be done only through one request like

/GeocodeResponse[1]/[self::status[text()='OK'] or self::result[1]/type or self::result[1]/address_component[1]] 

but this path returns all "results", while I need only the first one and nodes inside it("type", "formatted_address") and sub-nodes ("long_name","short_name") of a certain "address_component"'s nodes in it. Output example:

GeocodeResponse[1]/status
GeocodeResponse[1]/result[1]/type[1]
GeocodeResponse[1]/result[1]/formatted_address[1]
GeocodeResponse[1]/result[1]/address_component/short_name - where "address_component" contains "types" with text ('street_number', 'route', 'locality', 'administrative_area_level_1', 'postal_code')

Source xml response looks like:

`<GeocodeResponse>
<status>OK</status>
<result>
<type>establishment</type>
<type>point_of_interest</type>
<formatted_address>2 Hazel Grove, Radcliffe, Uckfield M26 1DD, UK</formatted_address>
<address_component>
<long_name>2</long_name>
<short_name>2</short_name>
<type>street_number</type>
</address_component>
<address_component>
<long_name>Hazel Grove</long_name>
<short_name>Hazel Grove</short_name>
<type>route</type>
</address_component>
<address_component>
<long_name>Radcliffe</long_name>
<short_name>Radcliffe</short_name>
<type>locality</type>
<type>political</type>
</address_component>
<address_component>
<long_name>Uckfield</long_name>
<short_name>Uckfield</short_name>
<type>postal_town</type>
</address_component>
<address_component>
<long_name>East Sussex</long_name>
<short_name>East Sussex</short_name>
<type>administrative_area_level_2</type>
<type>political</type>
</address_component>
<address_component>
<long_name>England</long_name>
<short_name>England</short_name>
<type>administrative_area_level_1</type>
<type>political</type>
</address_component>
<address_component>
<long_name>United Kingdom</long_name>
<short_name>GB</short_name>
<type>country</type>
<type>political</type>
</address_component>
<address_component>
<long_name>M26 1DD</long_name>
<short_name>M26 1DD</short_name>
<type>postal_code</type>
</address_component>
<geometry>
<location>
<lat>51.0000000</lat>
<lng>0.0000000</lng>
</location>
<location_type>ROOFTOP</location_type>
<viewport>
<southwest>
<lat>50.9986510</lat>
<lng>-0.0013490</lng>
</southwest>
<northeast>
<lat>51.0013490</lat>
<lng>0.0013490</lng>
</northeast>
</viewport>
</geometry>
<place_id>ChIJ_8dXPfiLdUgR9wQihY2gsgk</place_id>
<plus_code>
<global_code>9F322222+22</global_code>
<compound_code>2222+22 Sheffield Green, United Kingdom</compound_code>
</plus_code>
</result>
<result>
<type>postal_code</type>
<formatted_address>Uckfield TN22 3QS, UK</formatted_address>
<address_component>
<long_name>TN22 3QS</long_name>
<short_name>TN22 3QS</short_name>
<type>postal_code</type>
</address_component>
<address_component>
<long_name>Uckfield</long_name>
<short_name>Uckfield</short_name>
<type>postal_town</type>
</address_component>
<address_component>
<long_name>East Sussex</long_name>
<short_name>East Sussex</short_name>
<type>administrative_area_level_2</type>
<type>political</type>
</address_component>
<address_component>
<long_name>England</long_name>
<short_name>England</short_name>
<type>administrative_area_level_1</type>
<type>political</type>
</address_component>
<address_component>
<long_name>United Kingdom</long_name>
<short_name>GB</short_name>
<type>country</type>
<type>political</type>
</address_component>
<geometry>
<location>
<lat>50.9973315</lat>
<lng>0.0079172</lng>
</location>
<location_type>APPROXIMATE</location_type>
<viewport>
<southwest>
<lat>50.9959291</lat>
<lng>-0.0003802</lng>
</southwest>
<northeast>
<lat>51.0023266</lat>
<lng>0.0087596</lng>
</northeast>
</viewport>
<bounds>
<southwest>
<lat>50.9959291</lat>
<lng>-0.0003802</lng>
</southwest>
<northeast>
<lat>51.0023266</lat>
<lng>0.0087596</lng>
</northeast>
</bounds>
</geometry>
<place_id>ChIJqWgEbhpg30cRL6VL5HVT3NI</place_id>
</result>
<result>...</result>
<result>...</result>
<result>...</result>
<result>...</result>
<result>...</result>
<result>...</result>
<result>...</result>
<plus_code>
<global_code>9F322222+22</global_code>
<compound_code>2222+22 Sheffield Green, UK</compound_code>
</plus_code>
</GeocodeResponse>

can anyone suggest me how to achieve this please?

e.g.: vals to grab

1
Can you share current and expected result explicitly? - Andersson
Please show what is your expected output. Your Xpath and description is not fully clear to understand. - Amrendra Kumar
I need to garb: GeocodeResponse[1]/status; GeocodeResponse[1]/result[1]/type[1]; GeocodeResponse[1]/result[1]/formatted_address[1]; GeocodeResponse[1]/result[1]/address_component/short_name - where address_component contains types in ('street_number', 'route', 'locality', 'administrative_area_level_1', 'postal_code'). - user241841
fail example is xpath /GeocodeResponse[1]/[self::status[text()='OK']/text() or self::result/address_component/long_name[text()='Hazel Grove']] returns "status" and only first "result". But I want to explicitly result[1] and not the whole "result" node, but only matched "address_component/long_name" - user241841

1 Answers

0
votes

Based from what I can understand from your question including your comments, is this what you want?

//GeocodeResponse[status='OK']/result[address_component/long_name[.='Hazel Grove']][1]

It gets the first result child node of GeocodeResponse node (which has a child status = OK). With the result node having a descendant long_name (which has a value of 'Hazel Grove').

EDIT

Please have this xpath instead:

//GeocodeResponse[status='OK']/result[address_component/long_name[.='Hazel Grove']][1]/(preceding-sibling::status|type[1]|formatted_address[1]|address_component/short_name[../type='street_number' or ../type='route' or ../type='locality' or ../type='administrative_area_level_1' or ../type='postal_code'])

base on my testing on your XML, it outputs

OK
establishment
2 Hazel Grove, Radcliffe, Uckfield M26 1DD, UK
2
Hazel Grove
Radcliffe
England
M26 1DD