2010-11-10 8 views
1

Je suis sûr que cela aurait été longuement discuté ou répondu avant, mais je besoin d'un peu plus d'informations sur la meilleure approche pour ma situation ...Comment désérialiser des objets Java à partir de XML?

Problème:
Nous avons quelques grandes quantités de données XML (de 100k à 5Mo) que nous devons gonfler en objets Java. Le problème est que les données ne sont pas très bien mappées sur un objet, donc nous avons seulement besoin de sortir certaines parties des données et de créer les objets. Compte tenu de cela, des solutions telles que JAXB ou XStream ne sont vraiment pas appropriées. Nous avons donc besoin d'extraire les données XML et de les placer dans des objets java aussi efficacement que possible.


Solutions possibles:
La façon dont je le vois, nous avons 3 solutions possibles:

  • SAX analyse syntaxique
  • analyse syntaxique DOM
  • XSLT

Nous pouvons charger le XML dans n'importe quelle implémentation JAXP et tirer les données en utilisant l'une des méthodes ci-dessus.


Question (s)
J'ai quelques questions/préoccupations:

  • Comment fonctionne XSLT sous le capot? Est-ce juste un analyseur DOM? Je demande parce que XSLT semble être un bon moyen d'aller, mais je ne veux pas vraiment le considérer si cela ne nous donnera pas de meilleures performances que DOM.
  • Quelles sont les bibliothèques les plus répandues qui fournissent des parseurs XML DOM, XSLT et SAX?
  • Selon votre expérience, quelles sont les raisons pour choisir DOM, SAX ou XSLT? Est-ce que la facilité d'utilisation de DOM ou XSLT domine totalement les améliorations de performance offertes par SAX?
  • Des repères là-bas? Ceux que j'ai trouvés sont vieux (comme dans, 8 ans). Donc, certains benchmarks récents seraient appréciés.
  • Existe-t-il d'autres solutions que celles décrites ci-dessus que je pourrais manquer?


Edit:
Quelques précisions ... Vous pouvez utiliser XSLT pour injecter directement des valeurs dans un objet Java ... il est normalement utilisé pour transformer XML en un autre XML, mais je Je parle du point de vue d'appeler une méthode de XSLT en Java pour injecter la valeur. Je ne suis toujours pas clair sur la façon dont un processeur XSLT fonctionne exactement ... Comment est-il nourrir le code XML dans le code XSLT que vous écrivez?

+0

est XPath une option? –

+0

Voir ma réponse ci-dessous. Le XPath pour analyser quelques champs est normalement très simple et souvent très rapide. – Fortyrunner

+1

XSLT utilise des arborescences XML, il utilise donc un fournisseur DOM. Mais ici vous devez mesurer la performance (et le temps de développement) entre votre implémentation DOM "simple" et le langage de focus pour les transformations ... XSLT peut également fonctionner avec SAX et le streaming (vérifier le processeur Saxon XSLT). Je pense que vous pouvez commencer la chaîne avec ceci et ensuite utiliser un certain pont afin que le résultat en streaming alimente directement SAX afin de travailler avec une bibliothèque bien connue pour l'objet XML-Java. –

Répondre

3

Utilisez XSLT pour transformer les gros fichiers XML en un modèle de domaine local mappé aux objets Java avec JAXB.

Commencez avec le JDK 5+ construit dans les bibliothèques XML (sauf si vous avez absolument besoin XSLT 2.0, auquel cas l'utilisation saxonne)

Ne vous concentrez pas sur la performance relative des SAX/DOM, se concentrer sur l'apprentissage à écrire Exprimez des expressions XPath et utilisez XSLT, puis vous inquiétez des performances plus tard si et seulement si vous trouvez que c'est un problème. Les éditeurs XML Eclipse sont décents, mais si vous pouvez vous le permettre, lancez le langage XML Oxygen, qui vous permettra d'effectuer une évaluation XPath en temps réel.

+0

Pourquoi, cependant, ne pouvais-je pas simplement mapper le XML à mon modèle de domaine lors du traitement du XML avec XSLT? Je ne comprends pas l'avantage d'utiliser XSLT pour le faire dans un format qui pourrait être utilisé par JAXB, seulement pour que JAXB répète le XML. – Polaris878

+1

IME, il n'y a vraiment pas beaucoup de comparaison de performances entre SAX et DOM, il se résume simplement à "sont vos documents assez petits pour analyser en-mémoire?" Si c'est le cas, alors un analyseur basé sur DOM est le chemin à parcourir. Si non, alors vous devez aller à SAX. Si vos besoins sont vraiment simples, n'ayez pas peur d'ignorer toute l'API et de traiter votre document comme un flux de texte et de l'analyser vous-même. Je le fais souvent pour les routeurs de messages, où les quelques champs que j'ai besoin d'analyser sont au début du document. – TMN

2

Nous avons eu une situation similaire et j'ai juste jeté ensemble du code XPath qui analysait les choses dont j'avais besoin.

C'était incroyablement rapide même sur des fichiers XML 100k +. Nous sommes allés aussi bas que possible. Nous traitons environ 1000 fichiers par jour de cette taille et le temps d'analyse est très faible.Nous avons pas de problèmes de mémoire, fuites etc.

Nous avons écrit un prototype rapide dans Groovy (si ma mémoire est exacte) - preuve de concept m'a pris environ 10 minutes

1

DOM, SAX et XSLT sont différents animaux. L'analyse DOM charge l'ensemble du document en mémoire, ce qui, pour les 100 Ko à 5 Mo (très faible selon les normes actuelles), fonctionnerait. SAX est un analyseur de flux qui lit le XML et délivre des événements à votre code pour chaque tag. XSLT est un système permettant de transformer un arbre XML en un autre. Même si vous avez écrit une transformation qui convertit l'entrée dans un format plus approprié, vous devez toujours écrire quelque chose en utilisant DOM ou SAX pour le convertir en objets Java.

2

JAXB, l'API Java pour XML Binding peut être ce que vous voulez. Vous l'utilisez pour gonfler un document XML dans un graphe d'objet Java constitué d '"objets de contenu Java". Ces objets de contenu sont des instances de classes générées par JAXB pour correspondre au schéma du document XML

Mais si vous avez déjà un ensemble de classes Java, ou si vous n'avez pas encore de schéma pour le document, JAXB n'est probablement pas le meilleur marche à suivre. Je suggère de faire une analyse syntaxique SAX puis de construire vos objets Java pendant l'analyse. Alternativement, vous pouvez essayer une analyse DOM et ensuite parcourir l'arbre de document résultant pour extraire les parties d'intérêt (peut-être avec XPath) - mais 5 Mo de XML peuvent se transformer en 50 Mo d'objets d'arbre DOM en Java.

+0

C'est pourquoi je pose la question à propos de XSLT cependant ... J'ai besoin de savoir comment fonctionne un processeur XSLT ... si les implémentations les plus courantes sont DOM ou SAX. Il est plus facile de travailler avec XSLT qu'avec SAX, mais si c'est trop difficile, alors il faudrait utiliser SAX. – Polaris878

+1

JAXB peut démarrer à partir de classes Java. Découvrez comment l'extension @XmlPath dans EclipseLink JAXB (MOXy) peut être utilisée pour exploiter XPath dans ce cas d'utilisation: http://stackoverflow.com/questions/4149776/how-to-deserialize-java-objects-from-xml/ 4156018 # 4156018 –

+0

@Blaise: Cool, merci! –

1

Vous pouvez utiliser l'extension @XmlPath dans EclipseLink JAXB (MOXy) pour gérer facilement ce cas d'utilisation. Pour un exemple détaillé voir:

Exemple de code:

package blog.geocode; 

import javax.xml.bind.annotation.XmlRootElement; 
import javax.xml.bind.annotation.XmlType; 

import org.eclipse.persistence.oxm.annotations.XmlPath; 

@XmlRootElement(name="kml") 
@XmlType(propOrder={"country", "state", "city", "street", "postalCode"}) 
public class Address { 

    @XmlPath("Response/Placemark/ns:AddressDetails/ns:Country/ns:AdministrativeArea/ns:SubAdministrativeArea/ns:Locality/ns:Thoroughfare/ns:ThoroughfareName/text()") 
    private String street; 

    @XmlPath("Response/Placemark/ns:AddressDetails/ns:Country/ns:AdministrativeArea/ns:SubAdministrativeArea/ns:Locality/ns:LocalityName/text()") 
    private String city; 

    @XmlPath("Response/Placemark/ns:AddressDetails/ns:Country/ns:AdministrativeArea/ns:AdministrativeAreaName/text()") 
    private String state; 

    @XmlPath("Response/Placemark/ns:AddressDetails/ns:Country/ns:CountryNameCode/text()") 
    private String country; 

    @XmlPath("Response/Placemark/ns:AddressDetails/ns:Country/ns:AdministrativeArea/ns:SubAdministrativeArea/ns:Locality/ns:PostalCode/ns:PostalCodeNumber/text()") 
    private String postalCode; 

} 
Questions connexes