2009-05-25 5 views
2

Ich benutze Java und XStream, um eine Google Geocode-Anfrage über http zu parsen. Meine Idee ist, eine Address-Klasse mit allen Geocode-Attribs zu haben (zB lat/long, city, provice/state usw.), aber ich habe Probleme beim Parsing des xml mit xstream.parse Google Geocode mit Xstream

Die Google-Antwort ist ähnlich wie diese:

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

Das zeigt nicht sehr gut, aber das Fleisch des Codes ist in dem AddressDetails-Tag.

Wie auch immer, ich bin neu in Java und XStream, daher ist die API-Terminologie für mich etwas verwirrend. Ich muss nur in der Lage sein, einen Mapper zu schreiben, der all diese Tags (dh CountryName) auf ein Attribut innerhalb meines Address-Objekts abbildet (zB address.country = blah). Das Adressobjekt wird ziemlich einfach sein, hauptsächlich nur Strings für Land Name usw. und schwebt für lat/lang.

Die Dokumentation und das Beispiel zeigen nur ein geradliniges Mapping, bei dem jede XML-Tag direkt dem Attribut mit dem gleichen Namen des Objekts zugeordnet wird. In meinem Fall werden die Tags jedoch anders als die Objektattribute benannt. Ein schneller Punkt in die richtige Richtung ist alles was ich wirklich suche.

Antwort

2

Ich habe XStream in mehreren Projekten verwendet. Leider ist Ihr Problem nicht wirklich das, was XStream lösen soll. Möglicherweise können Sie den Konvertierungsmechanismus verwenden, um Ihr unmittelbares Ziel zu erreichen, aber Sie stoßen auf Einschränkungen. Kurz gesagt, XStream ist nicht dafür ausgelegt, die Umwandlung von Baumstruktur A in Baumstruktur B vorzunehmen - es ist der Zweck, von einem Java-Domänenmodell in ein vernünftiges XML zu konvertieren. XStream ist ein großartiges Werkzeug, wenn Sie sich nicht viel um die Details des erzeugten XML kümmern. Wenn Sie sich mehr für XML interessieren als für Java-Objekte, schauen Sie sich XMLBeans an - Java ist hässlich, aber es ist unglaublich schemafähig.

Für Ihr Projekt würde ich das Google-XML-Schema über XML-Beans ausführen, um Java zu generieren, das Ihnen eine bessere Möglichkeit bietet, einen Konverter manuell zu codieren. Sie könnten einen rohen DOM-Baum verwenden, aber Sie hätten Code wie myAddress.setStreet (root.getFirstChild(). GetAttribute ("addr1"))). Mit XML-Bohnen, sagen Sie Dinge wie myAddress.setStreet (googleResult.getAddress() getStreetName();.

würde ich JAXB ignorieren, wie es versucht, Schnittstelle zu trennen ist von der Implementierung unnötige Komplexität fügt Castor könnte ein gutes Werkzeug sein. bedenken Sie auch, aber ich habe es nicht in Jahren verwendet.

Kurz gesagt, es gibt nicht viele gute Object-to-Object oder XML-zu-Objekt-Konverter, die Struktur-Konvertierung gut handhaben Ich habe gesehen, dass Versuch deklarative Lösungen, alle von ihnen erschien viel komplizierter (und nicht wartungsfreundlicher) als die Verwendung XStream/XmlBeans zusammen mit handcodierten Struktur-Konvertierungen

+0

+1, XStream funktioniert am besten, wenn Sie mit den Java-Objekten beginnen und das XML bestimmen lassen, das von ihnen generiert werden soll. JAXB ist das Gegenteil, aber könnte Overkill sein. Ich würde wahrscheinlich nur den standardmäßigen XML-XML-DOM-Parser verwenden: schreibe eine Methode, die ihn verwendet, um das XML in eine DOM-Baumdatenstruktur zu zerlegen, und gehe durch den Baum, um die Informationen herauszufiltern, die du brauchst, um ein Adressobjekt zu erstellen. –

+0

JAXB kann mit Objekten oder XML beginnen. In meinem Beitrag erfahren Sie, wie eine MOXy JAXB-Erweiterung verwendet werden kann, um diesen Anwendungsfall einfach abzubilden. –

0

Wäre es möglich, eine separate Klasse speziell für den Umgang mit XStream Mapping zu definieren? Sie könnten dann einfach Ihr AddressDetails Objekt auffüllen, indem Sie Werte aus diesem anderen Objekt abfragen.

+0

Ich dachte darüber nach. Ich denke, es gibt tatsächlich eine bessere Methode. Ich lese gerade jetzt über Konverter. Es scheint, dass ich in der Lage sein sollte, die Konverterschnittstelle zu implementieren und eine Möglichkeit anzugeben, die XML zu analysieren und die entsprechenden Felder zu setzen. Ich werde meine Ergebnisse veröffentlichen. – brad

0

Ich habe am Ende nur mit xpath und p mein eigenes Adressobjekt manuell zu optieren. Scheint gut zu funktionieren.

0

Haben Sie versucht mit JSON-Format? Es sollte dasselbe sein, aber Sie müssen eine com.thoughtworks.xstream.io.json setzen.JettisonMappedXmlDriver als Treiber für XStream

0

Sie EclipseLink JAXB (MOXy) verwenden könnte, dies zu tun:

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

} 

und

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

Ein vollständiges Beispiel finden Sie hier: