C# Rechercher Et Remplacer des Nœuds XML
Edit: j'ai décidé de prendre le LINQ to XML (voir la réponse ci-dessous) qui a été recommandé et tout fonctionne SAUF que je ne peux pas remplacer les enregistrements modifiés avec les enregistrements de l'augmentation de fichier. J'ai réussi à faire fonctionner le programme en supprimant simplement le fichier complet du nœud, puis en ajoutant à l'augmentation de nœud. Est-il un moyen de les échanger à la place? Aussi, alors que cette solution est très agréable, est-il possible de rétrécir l'utilisation de la mémoire sans perdre le code LINQ? Cette solution peut fonctionner, mais je serais prêt à sacrifier de temps pour abaisser l'utilisation de la mémoire.
Je suis en train de prendre deux fichiers XML (un fichier complet et un différentiel de fichier) et les fusionner ensemble. Le fichier XML ressemble à ceci:
<List>
<Records>
<Person id="001" recordaction="add">
...
</Person>
</Records>
</List>
La recordaction attribut peut aussi être "chg" pour les modifications ou "del" pour les suppressions. La logique de base de mon programme est:
1) Lire le dossier complet dans un XmlDocument.
2) Lire le fichier incrémentiel dans un XmlDocument, sélectionnez les nœuds à l'aide de XmlDocument.SelectNodes(), place de ces nœuds dans un dictionnaire pour la recherche plus facile.
3) Sélectionner tous les nœuds dans le fichier, parcourir et vérifier chaque contre le dictionnaire contenant les différentiels des dossiers. Si recordaction="chg" ou "del" ajouter le nœud de la liste, puis supprimez tous les nœuds de la XmlNodeList qui sont dans cette liste. Enfin, ajouter recordaction="chg" ou "ajouter" les dossiers de l'augmentation de fichier dans le fichier.
4) Enregistrer le fichier XML.
Je vais avoir des problèmes sérieux avec l'étape 3. Voici le code de cette fonction:
private void ProcessChanges(XmlNodeList nodeList, Dictionary<string, XmlNode> dictNodes)
{
XmlNode lastNode = null;
XmlNode currentNode = null;
List<XmlNode> nodesToBeDeleted = new List<XmlNode>();
//If node from full file matches to incremental record and is change or delete,
//mark full record to be deleted.
foreach (XmlNode fullNode in fullDocument.SelectNodes("/List/Records/Person"))
{
dictNodes.TryGetValue(fullNode.Attributes[0].Value, out currentNode);
if (currentNode != null)
{
if (currentNode.Attributes["recordaction"].Value == "chg"
|| currentNode.Attributes["recordaction"].Value == "del")
{
nodesToBeDeleted.Add(currentNode);
}
}
lastNode = fullNode;
}
//Delete marked records
for (int i = nodeList.Count - 1; i >= 0; i--)
{
if(nodesToBeDeleted.Contains(nodeList[i]))
{
nodeList[i].ParentNode.RemoveChild(nodesToBeDeleted[i]);
}
}
//Add in the incremental records to the new full file for records marked add or change.
foreach (XmlNode weeklyNode in nodeList)
{
if (weeklyNode.Attributes["recordaction"].Value == "add"
|| weeklyNode.Attributes["recordaction"].Value == "chg")
{
fullDocument.InsertAfter(weeklyNode, lastNode);
lastNode = weeklyNode;
}
}
}
La XmlNodeList transmis est juste totalité de l'augmentation de documents qui ont été sélectionnés à partir du fichier incrémentiel, et le dictionnaire est juste ces mêmes nœuds, mais les principales avais sur l'id, donc je n'ai pas à parcourir l'ensemble de l'augmentation de la dossiers à chaque fois. Maintenant le programme est en train de mourir à l' "Supprimer les enregistrements marqués" stade en raison de l'indexation en dehors des limites. Je suis sûr que le "Ajouter à l'augmentation des dossiers" ne fonctionne pas non plus. Des idées? Également quelques suggestions pour faire de ce plus efficace, ce serait bien. Je risque de les exécuter dans un problème, parce que c'est la lecture dans un fichier de 250 mo qui les ballons jusqu'à 750 MO de mémoire, donc je me demandais si il y avait un moyen plus facile d'aller nœud par nœud dans le fichier complet. Merci!
Je vais regarder dans LINQ. Merci pour les conseils!!!
OriginalL'auteur Tony Trozzo | 2011-07-22
Vous devez vous connecter pour publier un commentaire.
Voici un exemple de comment vous pouvez accomplir avec LINQ-to-XML. Aucun dictionnaire n'est nécessaire:
S'il vous plaît laissez-moi savoir si vous avez des problèmes de fonctionnement et je vais le modifier et de le corriger. Je suis sûr que c'est correct, mais n'ont pas VS disponible pour le moment.
EDIT: correction de la
"chg"
cas d'utilisationpersonToChange.ReplaceWith(person)
plutôt quepersonToChange = person
. Ce dernier ne remplace rien, car il déplace simplement la référence, loin de le document sous-jacent.Oups, je viens de remarquer que j'ai été absent de la "Liste" de l'élément. J'ai édité le code de la corriger. J'espère que vous verrez le changement avant de l'essayer.
J'ai reçu votre modifier et il semble que l'ajout et de suppression d'enregistrements se trouvent dans le nouveau fichier, mais il semble que il peut y avoir un problème avec le remplacement de la les enregistrements modifiés. J'ai regardé un "chg" l'augmentation de fichier qui était une "ajouter" dans le fichier complet, et c'est encore une "ajouter" dans le nouveau fichier. Êtes-vous sûr que tout simplement la mise en personToChange = personne à synchroniser avec le fichier? Je suppose que je peux essayer de retirer puis de l'ajout.
Juste une petite mise à jour (j'ai édité le post original et j'ai l'intention de marquer ce que la réponse mais je voulais voir si quelqu'un d'autre a eu des commentaires sur le nouveau premier problème). La solution de contournement avec la suppression, puis ajouter travaillé.
Bonjour Tony, merci pour calculer l'ajout/suppression de solution de contournement pour changer une Personne. Une autre option serait d'utiliser: personToChange.Remplaceavec(personne); je vais modifier le post si ça fonctionne.
OriginalL'auteur Kevin D.