2 votes

Voie pythonique pour corriger du XML cassé

Je travaille avec un serveur XML-RPC cassé, et bien que j'aie soumis une demande de support pour le faire réparer, il y a un bug lorsque le serveur signale la longueur en octets d'une réponse utf-8 comme le nombre de caractères, ce qui entraîne la troncation du XML que je reçois.

Je m'attends à ce que cela soit corrigé à un moment donné, cependant j'enquête actuellement sur cela dans le cadre d'un ensemble d'outils, et j'ai vraiment besoin que cela fonctionne. Actuellement, j'ai effectué un correctif temporaire sur xmlrpclib pour inverser l'analyse en cas d'exception et me permettre de fournir manuellement la version corrigée de la réponse au parseur, mais étant donné la nature du XML, il doit y avoir un moyen de le faire de manière programmatique et donc me permettre d'utiliser le serveur XML-RPC comme s'il n'avait pas ce bug.

La quantité de troncature est seulement une partie des balises de fermeture, donc s'il y avait un moyen intégré d'obtenir l'arborescence XML cassée, de la sauvegarder avec toutes les balises fermées, puis de l'analyser à la place, cela me permettrait de continuer mon travail - je regarde actuellement la possibilité de créer le mien, mais toute aide serait grandement appréciée, je ne peux pas imaginer être la première personne à vouloir effectuer une correction d'erreur sur du xml, mais si je ne trouve pas de solution prête à l'emploi, je publierai la mienne sur git et la lierai à partir d'ici.

4voto

Alex Anderson Points 56

Voici un petit extrait - la clé est que les analyseurs sax génèrent des événements au fur et à mesure qu'ils avancent, ce qui vous permet de traiter le contenu jusqu'à ce qu'il se casse.

#!/usr/bin/env python

import sys
from xml.sax import handler, make_parser

class TagHandler(handler.ContentHandler):
    def __init__(self):
        handler.ContentHandler.__init__(self)

        self.stack = []

    def startElement(self, name, attrs):
        self.stack.append(name)

    def endElement(self, name):
        # TODO: peut-être juste confirmer que l'élément correspond au sommet de la pile ici
        self.stack.pop()

    def finish_document(self):
        return "\n".join(["" % tag for tag in reversed(self.stack)])

parser = make_parser()
handler = TagHandler()
parser.setContentHandler(handler)

try:
    parser.parse(sys.argv[1])

except:
    # TODO: quelque chose de plus intelligent que simplement imprimer
    # la fin du document. Comme l'ajouter à la source et répéter
    # ce que vous avez fait pour rendre ce traitement nécessaire.
    print handler.finish_document()

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X