Вопрос

Я использую 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; 

Полный пример доступен здесь:

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top