Validation et extraction d'un enregistrement XML par enregistrement dans la base de données

StackOverflow https://stackoverflow.com/questions/225832

Question

Voici le deal. J'ai un document XML avec beaucoup d'enregistrements. Quelque chose comme ça:

print("<?xml version="1.0" encoding="utf-8" ?>
      <Orders>
       <Order>
         <Phone>1254</Phone>
         <City>City1</City>
      <State>State</State>
      </Order>
      <Order>
         <Phone>98764321</Phone>
         <City>City2</City>
        <State>State2</State>
      </Order>  
     </Orders>");

Il existe également un fichier de schéma XSD. Je voudrais extraire des données de ce fichier et insérer ces enregistrements dans une table de base de données. Tout d’abord, j’aimerais bien valider chaque enregistrement de commande. Par exemple, s'il y a 5 commandes dans le fichier et que 2 d'entre elles échouent à la validation, j'aimerais insérer les 3 qui ont passé la validation dans la base de données et laissé les 2 autres. Il peut y avoir des milliers d'enregistrements dans un fichier xml. Quelle serait la meilleure approche ici. Et comment la validation irait-elle dans la mesure où je dois supprimer les enregistrements ayant échoué et utiliser uniquement ceux qui ont réussi la validation. Pour le moment, j'utilise XmlReaderSettings pour valider les enregistrements de document XML. Devrais-je extraire ces enregistrements dans un autre fichier XML ou un ensemble de données ou un objet personnalisé avant de les insérer dans une base de données? J'utilise .Net 3.5. Tout code ou lien est le bienvenu.

Était-ce utile?

La solution

Vous avez plusieurs options:

  1. XmlDataDocument a> ou XmlDocument . L'inconvénient de cette approche est que les données seront mises en cache dans la mémoire, ce qui est grave si vous en avez beaucoup. D'autre part, DataSet vous offre de bonnes fonctionnalités d'interrogation en mémoire. XmlDocument nécessite que vous utilisiez des requêtes XPath pour travailler sur les données, alors que XmlDataDocument vous donne une expérience plus proche de la fonctionnalité DataSet.

  2. XmlReader . C'est une bonne approche rapide car les données ne sont pas mises en cache. vous le lisez peu à peu sous forme de flux. Vous passez d'un élément à l'autre et vous interrogez les informations relatives à cet élément dans votre application pour décider quoi faire avec. Cela signifie que vous maintenez dans la mémoire de votre application le niveau d'arborescence auquel vous vous trouvez, mais avec une structure de fichier XML simple comme la vôtre, cela devrait être très simple.

Je recommande l'option 2 dans votre cas. Il devrait évoluer correctement en termes d’utilisation de la mémoire et fournir la mise en oeuvre la plus simple pour traiter un fichier.

Autres conseils

Si les données correspondent assez proprement à un modèle objet, vous pouvez utiliser xsd.exe pour générer des classes à partir du fichier .xsd et les traiter dans le DAL de votre choix. Le problème est que si le volume est élevé (vous mentionnez des milliers d'enregistrements), vous aurez très probablement beaucoup d'allers-retours.

Une autre option pourrait consister à transmettre les données "telles quelles". jusqu’à la base de données et utilisez SQL / XML pour traiter les données dans TSQL - vraisemblablement comme une procédure stockée acceptant un paramètre de type xml (SQL Server 2005, etc.).

Je suis d'accord avec l'idée d'utiliser un XmlReader, mais je pensais essayer quelque chose de différent.

En gros, je commence par valider l’ensemble du XDocument, puis, s’il ya des erreurs, j’énumère les ordres et les classe au besoin. Ce n'est pas joli, mais peut-être que ça vous donnera des idées.

        XDocument doc = XDocument.Load("sample.xml");
        XmlSchemaSet schemas = new XmlSchemaSet();
        schemas.Add("", "sample.xsd");

        bool errors = false;
        doc.Validate(schemas, (sender, e) =>
        {
            errors = true;
        });

        List<XElement> good = new List<XElement>();
        List<XElement> bad = new List<XElement>();
        var orders = doc.Descendants("Order");
        if (errors)
        {
            foreach (var order in orders)
            {
                errors = false;
                order.Validate(order.GetSchemaInfo().SchemaElement, schemas, (sender, e) =>
                {
                    errors = true;
                });

                if (errors)
                    bad.Add(order);
                else
                    good.Add(order);
            }
        }
        else
        {
            good = orders.ToList();
        }

Au lieu des expressions lambda, vous pouvez utiliser une fonction commune, mais je viens de regrouper cela. En outre, vous pouvez créer deux XDocuments au lieu de déplacer les éléments de commande dans une liste. Je suis sûr qu'il y a une tonne d'autres problèmes ici aussi, mais peut-être que cela va déclencher quelque chose.

Cela dépend en grande partie de la "validation". signifie dans votre scénario. Je suppose que puisque vous utilisez un fichier .xsd, vous validez déjà que les données sont syntaxiquement correctes. Ainsi, la validation signifie probablement que vous appelez d’autres services ou procédures pour déterminer si une commande est valide?

Vous voudrez peut-être consulter SQL Server Integration Services. La tâche XML dans SSIS vous permet d'effectuer des tâches telles que les requêtes XPath, la fusion, probablement tout ce que vous devez faire avec ce document. Vous pouvez également l'utiliser pour toutes vos validations initiales avec un fichier de schéma.

L'option de Marc de transmettre ces données à une procédure stockée peut également fonctionner dans ce scénario, mais SSIS (ou même DTS mais vous allez abandonner trop de choses liées à XML pour le rendre aussi agréable qu'une option) vous permettent d'orchestrer visuellement tout ce travail. De plus, cela facilitera la tâche de ces choses en fin de processus et vous obtiendrez une solution beaucoup plus évolutive.

Par validation, je veux dire valider chaque nœud. Les nœuds qui ont au moins une erreur doivent être insérés dans un nouveau document XML. En fin de compte, je devrais avoir 2 documents XML. L'un contenant les noeuds réussis et l'autre contenant les noeuds défaillants. Est-ce que je peux y arriver? J'utilise LINQ.

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