Question

Je recherche la meilleure méthode pour analyser divers documents XML à l'aide d'une application Java.Je fais actuellement cela avec SAX et un gestionnaire de contenu personnalisé et cela fonctionne très bien – rapide et stable.

J'ai décidé d'explorer l'option permettant au même programme, qui reçoit actuellement un document XML au format unique, de recevoir deux formats de document XML supplémentaires, avec diverses modifications d'éléments XML.J'espérais simplement remplacer le ContentHandler par un autre approprié basé sur le premier "startElement" du document...mais, euh-duh, le ContentHandler est défini et alors le document est analysé !

... constructor ...
{
SAXParserFactory spf = SAXParserFactory.newInstance();

try {
SAXParser sp = spf.newSAXParser();
parser = sp.getXMLReader();
parser.setErrorHandler(new MyErrorHandler());
} catch (Exception e) {} 

... parse StringBuffer ...
try {
parser.setContentHandler(pP);
parser.parse(new InputSource(new StringReader(xml.toString())));
return true;
} catch (IOException e) {
    e.printStackTrace();
} catch (SAXException e) {
    e.printStackTrace();
}
...

Il ne semble donc pas que je puisse faire cela comme je le pensais au départ.

Cela étant dit, est-ce que je vois tout à fait mal ?Quelle est la meilleure méthode pour analyser plusieurs documents XML discrets avec le même code de gestion XML ? J'ai essayé de demander dans un post plus général plus tôt...mais je pense que j'étais trop vague.Pour des raisons de rapidité et d'efficacité, je n'ai jamais vraiment regardé DOM car ces documents XML sont assez volumineux et le système en reçoit environ 1 200 toutes les quelques minutes.C'est juste un envoi d'informations à sens unique

Pour rendre cette question trop longue et ajouter à ma confusion ;Voici une maquette de divers documents XML que j'aimerais avoir dans un seul SAX, StAX ou ??l'analyseur traite proprement.

produits.xml :

<products>
<product>
  <id>1</id>
  <name>Foo</name>
<product>
  <id>2</id>
  <name>bar</name>
</product>
</products>

magasins.xml :

<stores>
<store>
  <id>1</id>
  <name>S1A</name>
  <location>CA</location>
</store>
<store>
  <id>2</id>
  <name>A1S</name>
  <location>NY</location>
</store>
</stores>

managers.xml :

<managers>
<manager>
  <id>1</id>
  <name>Fen</name>
  <store>1</store>
</manager>
<manager>
  <id>2</id>
  <name>Diz</name>
  <store>2</store>
</manager>
</managers>
Était-ce utile?

La solution

Si je comprends bien, le problème est que vous ne savez pas quel est le format du document avant l'analyse.Vous pouvez utiliser un modèle de délégué.Je suppose que vous ne validez pas par rapport à un DTD/XSD/etcetera et qu'il est acceptable que DefaultHandler ait un état.

public class DelegatingHandler extends DefaultHandler {

    private Map<String, DefaultHandler> saxHandlers;
    private DefaultHandler delegate = null;

    public DelegatingHandler(Map<String, DefaultHandler> delegates) {
        saxHandlers = delegates;
    }

    @Override
    public void startElement(String uri, String localName, String name,
            Attributes attributes) throws SAXException {
       if(delegate == null) {
           delegate = saxHandlers.get(name);
       }
       delegate.startElement(uri, localName, name, attributes);
    }

    @Override
    public void endElement(String uri, String localName, String name)
            throws SAXException {
        delegate.endElement(uri, localName, name);
    }

//etcetera...

Autres conseils

Vous avez fait du bon travail en expliquant ce que vous voulez faire mais pas pourquoi.Il existe plusieurs frameworks XML qui simplifient le marshalling et le démarshalling des objets Java vers/depuis XML.

Le plus simple est Digesteur des Communes que j'utilise généralement pour analyser les fichiers de configuration.Mais si vous souhaitez gérer des objets Java, vous devriez regarder Castor, JiBX, JAXB, Beans XML, XStream, ou quelque chose de similaire.Castor ou JiBX sont mes deux préférés.

J'ai essayé le SAXParser une fois, mais une fois que j'ai trouvé XStream Je n'y suis jamais revenu.Avec XStream, vous pouvez créer des objets Java et les convertir en XML.Envoyez-les et utilisez XStream pour recréer l'objet.Très facile à utiliser, rapide et crée du XML propre.

Quoi qu'il en soit, vous devez savoir quelles données vous allez recevoir du fichier XML.Vous pouvez les envoyer de différentes manières pour savoir quel analyseur utiliser.Ou avoir un objet de données qui peut tout contenir mais une seule structure est renseignée (produit/magasin/gestionnaires).Peut-être quelque chose comme :

public class DataStructure {

    List<ProductStructure> products;

    List<StoreStructure> stors;

    List<ManagerStructure> managers;

    ...

    public int getProductCount() {
        return products.lenght();
    }

    ...
}

Et avec XStream, convertissez en XML, envoyez puis recréez l'objet.Ensuite, faites-en ce que vous voulez.

Voir la documentation pour XMLReader.setContentHandler(), ça dit:

Les applications peuvent enregistrer un gestionnaire nouveau ou différent au milieu d'une analyse, et l'analyseur SAX doit commencer à utiliser le nouveau gestionnaire immédiatement.

Ainsi, vous devriez pouvoir créer un SelectorContentHandler qui consomme des événements jusqu'au premier startElement événement, basé sur cela change le ContentHandler sur le lecteur XML et transmet le premier événement d'élément de démarrage au nouveau gestionnaire de contenu.Il vous suffit de passer le XMLReader au SelectorContentHandler dans le constructeur.Si tu as besoin tous les événements à transmettre au gestionnaire de contenu spécifique au vocabulaire, SelectorContentHandler doit mettre en cache les événements puis les transmettre, mais dans la plupart des cas, cela n'est pas nécessaire.

En passant, j'ai récemment utilisé XOM dans presque tous mes projets pour gérer XML et jusqu'à présent, les performances n'ont pas été le problème.

JAXB.L'architecture Java pour la liaison XML.Fondamentalement, vous créez un fichier XSD définissant votre mise en page XML (je pense que vous pouvez également utiliser une DTD).Ensuite, vous transmettez le XSD au compilateur JAXB et le compilateur crée des classes Java pour marshaler et démarshaler votre document XML en objets Java.C'est vraiment simple.

BTW, il existe des options de ligne de commande pour jaxb pour spécifier le nom du package dans lequel vous souhaitez placer les classes résultantes, etc.

Si vous souhaitez une gestion plus dynamique, l'approche Stax fonctionnerait probablement mieux que Sax.C'est quand même un niveau assez bas ;si vous souhaitez une approche plus simple, XStream et JAXB sont mes favoris.Mais ils nécessitent des objets assez rigides sur lesquels mapper.

D'accord avec StaxMan, qui, chose intéressante, souhaite que vous utilisiez Stax.Il s'agit d'un analyseur basé sur l'extraction au lieu du push que vous utilisez actuellement.Cela nécessiterait cependant des modifications importantes à votre code.

:-)

Oui, j'ai un certain parti pris en faveur de Stax.Mais comme je l'ai dit, la liaison de données est souvent plus pratique que la solution de streaming.Mais si vous souhaitez diffuser du streaming et que vous n'avez pas besoin de pipeline (de plusieurs étapes de filtrage), Stax est plus simple que SAX.

Encore une chose :aussi bon que soit XOM (par rapport aux alternatives), le modèle d'arbre n'est souvent pas la bonne chose à utiliser si vous n'avez pas affaire à du XML "centré sur le document" (~= pages xhtml, docbook, documents open office).Pour l'échange de données, les fichiers de configuration, etc., la liaison de données est plus pratique, plus efficace, plus naturelle.Dites simplement non aux modèles d'arborescence comme DOM pour ces cas d'utilisation.Donc, JAXB, XStream, JibX sont bons.Ou, pour un goût plus acquis, digesteur, ricin, xmlbeans.

VTD-XML est connu pour être la meilleure technologie de traitement XML pour le traitement XML intensif.Voir la référence ci-dessous pour une preuve

http://sdiwc.us/digitlib/journal_paper.php?paper=00000582.pdf

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top