Pour la différence de taille c'est normal car je n'ai pas précisé d'options de formatage pour l'écriture. Par défaut pour l'indentation ce sont des espaces qui sont utilisés, cela prend donc plus de place par rapport à l'utilisation de tabulation.
Pour commenter le code alors cette partie charge le document et ajoute un attribut ViewCount sur chaque élément viewstruct. La valeur de cet attribut est le nombre de descendants view de l'élément viewstruct.
Ensuite on crée une copie du document original dont on retire tous les élément viewstruct.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12 XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load(@"d:\configuration.xml"); XmlNamespaceManager mgr = new XmlNamespaceManager(xmlDoc.NameTable); mgr.AddNamespace("x", "http://www.generix.fr/technicalframework/configuration"); foreach (XmlNode node in xmlDoc.SelectNodes("//x:viewstruct", mgr)) { XmlAttribute att = xmlDoc.CreateAttribute("ViewCount"); att.Value = node.CreateNavigator().Evaluate("count(.//x:view)", mgr).ToString(); node.Attributes.Append(att); }
Après on crée une XPathExpression qui sera utilisée pour trier les éléments viewstruct en se basant sur la valeur de l'attribut ViewCount. Le tri est configuré de manière décroissante. On récupère enfin un itérateur sur les éléments pour les parcourir dans l'ordre du tri.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 XmlDocument xmlDocCopy = new XmlDocument(); xmlDocCopy.LoadXml(xmlDoc.OuterXml); xmlDocCopy.SelectSingleNode("//x:viewstruct_def", mgr).RemoveAll();
Pour finir, on parcours chaque élément et on l'ajoute à la copie (en retirant l'attribut ViewCount au passage) et on sauvegarde le document XML ainsi généré.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 XPathNavigator navigator = xmlDoc.CreateNavigator(); XPathExpression selectExpression = navigator.Compile("//x:viewstruct_def/x:viewstruct"); selectExpression.AddSort("@ViewCount", XmlSortOrder.Descending, XmlCaseOrder.None, "", XmlDataType.Number); selectExpression.SetContext(mgr); XPathNodeIterator nodeIterator = navigator.Select(selectExpression);
En utilisant XSLT le traitement est plus rapide et moins gourmand en mémoire (ratio de 4 environ, 2.5 secondes contre 600ms et 124Mo contre 28Mo). Seul hic, la présence de l'espace de noms par défaut (xmlns) me pose problème. A priori avec XSLT 2.0 on pourrait y arriver mais .Net ne gère que XSLT 1.0. Dommage car le code est beaucoup plus simple et plus performant ^^
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 while (nodeIterator.MoveNext()) { XmlNode importedLinkNode = xmlDocCopy.ImportNode((XmlNode)nodeIterator.Current.UnderlyingObject, true); importedLinkNode.Attributes.RemoveNamedItem("ViewCount"); xmlDocCopy.SelectSingleNode("//x:viewstruct_def", mgr).AppendChild(importedLinkNode); } xmlDocCopy.Save(@"d:\Output.xml");
Partager