2010-08-26 8 views
3

version rapide:XMLReader (en Php) et traitement des erreurs

Quelle est la norme (innovante tout?) Façon d'attraper et les erreurs de manipulation lancées par XMLReader en raison de fichier malformé - en particulier les caractères un-échappé. Prepossessing avec Tidy (etc ..) n'est pas une option super attrayante, quelqu'un sait d'une manière d'ignorer simplement le nœud fautif et aller de l'avant?

Version descriptif:

Nous savons tous que ce n'est pas XML si elle est pas correctement formé, mais laisse être honnête - il arrive. Un client tire régulièrement des fichiers xml massifs (50-100 Mo +) qui doivent être lus dans mysql. XMLReader est le choix évident et nous avons écrit un emballage qui fonctionne bien pour nos besoins. De temps en temps, une erreur se produit et read() échoue en supprimant le fichier import - drat! C'est presque toujours un personnage non échappé (ex "&") qui fait tout sauter. Dans la plupart des cas, nous demandons au client d'appeler le fournisseur de données et lui demande de réparer son fichier défectueux. Malheureusement, les fournisseurs de données ne sont pas toujours obligeants et/ou opportuns. Ce serait incroyable si nous pouvions simplement attraper l'erreur et passer directement au nœud suivant.

J'ai passé un certain temps à essayer de lire/cracker celui-ci et ne trouve rien qui mérite d'être lu. Est-ce que je manque quelque chose d'évident?

This SO question semblait prometteur mais ne donnait tout simplement aucun résultat. En passant le 1 semble que cela devrait demander au lecteur de récupérer, mais nous sommes tout simplement pas voir toute tentative/différents messages d'erreur, etc .. Voici le code correspondant décrivant l'approche:

$xml->open($file, null, LIBXML_NOERROR | LIBXML_NOWARNING | 1); 

je pouvais toujours prétraiter avec Bien rangé, mais il doit y avoir un meilleur moyen.

J'ai envisagé quelques approches plus "créatives" telles que renifler la prochaine Read() avec un try/catch après la logique pour le nœud actuel a terminé, mais cela semble maladroit au mieux. Il semble également qu'il pourrait être possible d'émuler Read() avec une fonction custom/wrapper qui permet de se déplacer dans les nœuds et incorpore le traitement des erreurs, mais j'ai l'impression de simplifier à l'extrême. Donc, pour résumer: Quand read() échoue, comment puis-je attraper l'erreur et me déplacer? Y a-t-il une chance que nous puissions voir quelle erreur arrive (au moins le message que le XMLReader aurait lancé)?

$xml = new XMLReader(); 
$xml->open($file); 

while ($xml->read()) { 

} 

Répondre

1

C'est un lecteur XML, et il est fait pour lire du XML. XML non valide n'est pas XML et ne peut pas être lu avec un lecteur XML - c'est aussi simple que cela.

Exécutez xmllint sur votre fichier avant de l'importer pour vérifier s'il est valide ou faites le bon choix et demandez à votre fournisseur de données de générer un fichier XML valide.

2

A propos de la « voir l'erreur » partie de votre question:

http://php.net/manual/en/function.libxml-use-internal-errors.php Lorsque ce paramètre est la fausse valeur par défaut, un avertissement de PHP se déclenchera sur un XML non valide. En d'autres termes, vous auriez dû le voir: p Vous ne faisiez pas attention, ou avez un paramètre ou un gestionnaire d'erreur personnalisé qui vous cache les avertissements PHP.

Si vous appelez la fonction ci-dessus vrai, pas d'avertissement sera généré, et au lieu des erreurs seront accumulés dans le tableau interne retourné par cette fonction:

http://www.php.net/manual/en/function.libxml-get-errors.php

A propos de la partie « se déplacer le long » J'ai peur que cweiske ait raison et que cela ne puisse pas être fait. Vous pouvez pré-filtrer votre XML pour des erreurs avec certains outils (même en les analysant avec XMLReader) et essayer de corriger les erreurs que vous trouvez, c'est-à-dire supprimer/remplacer les caractères invalides, mais vous devrez recommencer l'analyse des données corrigées.

1

J'ai rencontré le même problème. En utilisant un stream filter, vous pouvez corriger le code XML avant de l'envoyer à XMLReader.

Ceci fait HTML to XML filter. Utilisez-le comme

$dsn = "php://filter/read=htmltoxml.entities/resource=" . $url; 
$xml = XMLReader::open($dsn);