разобрать геокод Google с помощью xstream
Вопрос
Я использую Java и XStream для анализа запроса геокода Google через http.Моя идея состоит в том, чтобы иметь класс Address со всеми атрибутами геокода (т.широта/долгота, город, провинция/штат и т. д.), но у меня возникли проблемы с анализом XML с помощью xstream.
Ответ Google примерно такой:
<?xml version="1.0" encoding="UTF-8" ?>
<kml xmlns="http://earth.google.com/kml/2.0"><Response>
<name>98 St. Patrick St, Toronto</name>
<Status>
<code>200</code>
<request>geocode</request>
</Status>
<Placemark id="p1">
<address>98 St Patrick St, Toronto, ON, Canada</address>
<AddressDetails Accuracy="8" xmlns="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0"> <Country><CountryNameCode>CA</CountryNameCode><CountryName>Canada</CountryName><AdministrativeArea><AdministrativeAreaName>ON</AdministrativeAreaName><Locality><LocalityName>Toronto</LocalityName><Thoroughfare><ThoroughfareName>98 St Patrick St</ThoroughfareName></Thoroughfare><PostalCode><PostalCodeNumber>M5T</PostalCodeNumber></PostalCode></Locality></AdministrativeArea></Country></AddressDetails>
<ExtendedData>
<LatLonBox north="43.6560378" south="43.6497426" east="-79.3864912" west="-79.3927864" />
</ExtendedData>
<Point><coordinates>-79.3896388,43.6528902,0</coordinates></Point>
</Placemark>
</Response></kml>
Это выглядит не очень хорошо, но суть кода находится в теге AddressDetails.
В любом случае, я новичок в Java и XStream, поэтому терминология API меня немного сбивает с толку.Мне просто нужно написать какой-нибудь преобразователь, который отображает все эти теги (т.CountryName) к атрибуту в моем объекте Address (т. е.адрес.страна = бла) Объект адреса будет довольно простым, в основном это просто строки для названия страны и т. д. и плавающие значения широты и долготы.
Документы и пример просто показывают прямое сопоставление, где каждый тег xml напрямую сопоставляется с одноименным атрибутом объекта.Однако в моем случае теги называются иначе, чем атрибуты объекта.Быстрый переход в правильном направлении — это все, что мне действительно нужно.
Решение
Я использовал XStream в нескольких проектах.К сожалению, ваша проблема на самом деле не является тем, для решения которой предназначен XStream.Возможно, вы сможете использовать его механизм преобразования для достижения своей непосредственной цели, но вы столкнетесь с ограничениями.Короче говоря, XStream не предназначен для преобразования древовидной структуры A в древовидную структуру B — его цель — преобразовать модель предметной области Java в некоторый разумный XML.XStream — отличный инструмент, когда вас не особо интересуют детали создаваемого XML.Если вас больше волнует XML, чем объекты Java, обратите внимание на XMLBeans — Java уродлива, но она невероятно совместима со схемами.
Для вашего проекта я бы запустил XML-схему Google через XML-компоненты, сгенерировал Java-код, который даст вам более грамотный способ ручного написания конвертера.Вы можете использовать необработанное дерево DOM, но у вас будет такой код, как myAddress.setStreet(root.getFirstChild().getAttribute("addr1"))).При использовании XML-компонентов вы говорите такие вещи, как myAddress.setStreet(googleResult.getAddress().getStreetName();
Я бы проигнорировал JAXB, поскольку его попытка отделить интерфейс от реализации добавляет ненужную сложность.Castor тоже может быть хорошим инструментом, но я не использовал его уже много лет.
Короче говоря, существует не так уж много хороших преобразователей объектов в объекты или XML в объекты, которые хорошо справляются с преобразованием структур.Из тех, которые я видел в попытках декларативных решений, все они казались намного более сложными (и не более удобными в обслуживании), чем использование XStream/XmlBeans вместе с преобразованиями структур, закодированными вручную.
Другие советы
Можно ли определить отдельный класс специально для работы с отображением XStream?Затем вы можете просто заполнить свой AddressDetails
объект, запрашивая значения из этого другого объекта.
В итоге я просто использовал xpath и вручную заполнил свой собственный адресный объект.Кажется, работает нормально.
Вы пробовали использовать формат json?Должно быть то же самое, но вам нужно будет установить com. Thoughtworks.xstream.io.json.JettisonMappedXmlDriver в качестве драйвера для XStream.
Вы могли бы использовать EclipseLink JAXB (MOXy) сделать это:
package com.example;
import javax.xml.bind.annotation.XmlRootElement;
import org.eclipse.persistence.oxm.annotations.XmlPath;
@XmlRootElement(name="kml")
public class Address {
private String country;
@XmlPath("Response/Placemark/ns:AddressDetails/ns:Country/ns:CountryName/text()")
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
}
и
@javax.xml.bind.annotation.XmlSchema(
namespace = "http://earth.google.com/kml/2.0",
xmlns = {
@javax.xml.bind.annotation.XmlNs(
prefix = "ns", namespaceURI ="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0")
},
elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package com.example;
Полный пример доступен здесь: