2009-05-25 12 views
2

J'utilise Java et XStream pour analyser une requête de géocodage google sur http. Mon idée est d'avoir une classe Address avec tous les attributs du géocode (c'est-à-dire lat/long, ville, provice/état, etc.) mais j'ai des problèmes pour analyser le xml avec xstream.analyser google geocode avec xstream

La réponse Google est similaire à ceci:

<?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> 

Cela ne se présente pas très bien, mais la viande du code est dans la balise addressdetails.

Quoi qu'il en soit, je suis nouveau sur Java et XStream, donc la terminologie de l'API est un peu confuse pour moi. Je dois juste être en mesure d'écrire un mappeur qui mappe tous ces tags (ie CountryName) à un attribut dans mon objet Address, (par exemple, address.country = blah) L'objet d'adresse sera assez simple, principalement juste des cordes pour le pays nom etc et flotte pour lat/long.

Les documents et l'exemple montrent juste le mappage direct où chaque balise xml est mappée directement à l'attribut du même nom de l'objet. Dans mon cas cependant, les tags sont nommés différemment de l'objet attr. Un point rapide dans la bonne direction est tout ce que je cherche vraiment.

Répondre

2

J'ai utilisé XStream dans plusieurs projets. Malheureusement, votre problème n'est pas vraiment ce que XStream est conçu pour résoudre. Vous pourriez être en mesure d'utiliser son mécanisme de conversion pour atteindre votre objectif immédiat, mais vous rencontrerez des limites. En un mot, XStream n'est pas conçu pour faire la conversion de Tree Structure A en Tree Structure B - son but est de convertir un modèle de domaine Java en un XML raisonnable. XStream est un excellent outil lorsque vous ne vous souciez pas des détails du XML produit. Si vous vous souciez plus du XML que des objets Java, regardez XMLBeans - le Java est moche, mais il est incroyablement compatible avec le schéma.

Pour votre projet, j'utiliserais le schéma XML de XML via des beans XML, je générerais du Java qui vous donnerait un moyen plus simple de coder manuellement un convertisseur. Vous pourriez utiliser un arbre DOM brut, mais vous auriez un code comme myAddress.setStreet (root.getFirstChild(). GetAttribute ("addr1"))). Avec les beans XML, vous dites des choses comme myAddress.setStreet (googleResult.getAddress(). GetStreetName();

J'ignorerais JAXB car il essaie de séparer l'interface de l'implémentation ajoute une complexité inutile. Considérons aussi, mais je ne l'ai pas utilisé depuis des années

En résumé, il n'y a pas beaucoup de bons convertisseurs Object-to-Object ou XML-to-Object qui gèrent bien la conversion de structure. J'ai vu que tenter des solutions déclaratives, tout cela semblait beaucoup plus compliqué (et pas plus facile à maintenir) que d'utiliser XStream/XmlBeans avec des conversions de structure codées à la main

+0

+1, XStream fonctionne mieux si vous commencez avec les objets Java et laissez-le déterminer le XML à générer à partir d'eux. JAXB est l'inverse, mais pourrait être exagéré. J'utiliserais probablement l'analyseur XML XML DOM standard: écrivez une méthode qui l'utilise pour analyser le XML dans une structure de données d'arborescence DOM, et parcourez l'arborescence pour sélectionner les informations dont vous avez besoin pour créer un objet Address. –

+0

JAXB peut commencer avec des objets ou XML. Voir mon article sur la façon dont une extension MOXy JAXB pourrait être utilisée pour mapper facilement ce cas d'utilisation. –

0

Serait-il possible de définir une classe distincte spécifiquement pour gérer le mappage de XStream? Vous pouvez alors simplement remplir votre objet AddressDetails en interrogeant les valeurs de cet autre objet.

+0

J'ai réfléchi à ça. Je pense qu'il existe une meilleure méthode. Je lis juste à propos des convertisseurs. Il semble que je devrais être en mesure d'implémenter l'interface du convertisseur et de spécifier un moyen d'analyser le fichier XML et de définir les champs appropriés. Je posterai mes conclusions. – brad

0

J'ai fini par utiliser xpath et p opuler manuellement mon propre objet d'adresse. Ça semble fonctionner correctement.

0

Avez-vous essayé avec le format json? Cela devrait être pareil, mais vous devrez définir un com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver comme pilote pour Xstream

0

Vous pouvez utiliser EclipseLink JAXB (MOXy) pour ce faire:

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; 
    } 

} 

et

@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; 

Un exemple complet est disponible ici:

Questions connexes