Je voulais voir laquelle de ces solutions suggérées fonctionnait le mieux, j'ai donc effectué des tests comparatifs. Par intérêt, j'ai également comparé les méthodes LINQ à l'ancienne méthode System.Xml suggérée par Greg. La variation était intéressante et pas ce à quoi je m'attendais, les méthodes les plus lentes étant plus de 3 fois plus lentes que les plus rapides .
Les résultats classés du plus rapide au plus lent:
- CreateReader - Instance Hunter (0,113 seconde)
- Plain old System.Xml - Greg Hurlman (0,134 secondes)
- Agrégat avec concaténation de chaînes - Mike Powell (0,324 seconde)
- StringBuilder - Vin (0,333 seconde)
- String.Join on array - Terry (0,360 seconde)
- String.Concat sur tableau - Marcin Kosieradzki (0.364)
Méthode
J'ai utilisé un seul document XML avec 20 nœuds identiques (appelé `` indice ''):
<hint>
<strong>Thinking of using a fake address?</strong>
<br />
Please don't. If we can't verify your address we might just
have to reject your application.
</hint>
Les nombres indiqués en secondes ci-dessus sont le résultat de l'extraction du "XML interne" des 20 nœuds, 1000 fois de suite, et de la moyenne (moyenne) de 5 exécutions. Je n'ai pas inclus le temps XmlDocument
nécessaire pour charger et analyser le XML dans un (pour la méthode System.Xml ) ou XDocument
(pour tous les autres).
Les algorithmes LINQ que j'ai utilisés étaient: (C # - tous prennent un XElement
"parent" et renvoient la chaîne XML interne)
CreateReader:
var reader = parent.CreateReader();
reader.MoveToContent();
return reader.ReadInnerXml();
Agréger avec concaténation de chaînes:
return parent.Nodes().Aggregate("", (b, node) => b += node.ToString());
StringBuilder:
StringBuilder sb = new StringBuilder();
foreach(var node in parent.Nodes()) {
sb.Append(node.ToString());
}
return sb.ToString();
String.Join sur le tableau:
return String.Join("", parent.Nodes().Select(x => x.ToString()).ToArray());
String.Concat sur tableau:
return String.Concat(parent.Nodes().Select(x => x.ToString()).ToArray());
Je n'ai pas montré ici l'algorithme "Plain old System.Xml" car il appelle simplement .InnerXml sur les nœuds.
Conclusion
Si les performances sont importantes (par exemple, beaucoup de XML, analysé fréquemment), j'utiliserais la CreateReader
méthode de Daniel à chaque fois . Si vous ne faites que quelques requêtes, vous voudrez peut-être utiliser la méthode Aggregate plus concise de Mike.
Si vous utilisez XML sur des éléments volumineux avec beaucoup de nœuds (peut-être des centaines), vous commencerez probablement à voir l'avantage d'utiliser StringBuilder
la méthode Aggregate, mais pas plus CreateReader
. Je ne pense pas que les méthodes Join
et Concat
seraient jamais plus efficaces dans ces conditions en raison de la pénalité de convertir une grande liste en un grand tableau (même évident ici avec des listes plus petites).
parent.CreateNavigator().InnerXml
(besoinusing System.Xml.XPath
de la méthode d'extension)..ToArray()
intérieur.Concat
, mais cela semble le rendre plus rapide.ToString()
par cette réponse . Semble encore plus rapide ...var reader = parent.CreateReader();
dans une instruction using.Je pense que c'est une bien meilleure méthode (en VB, ne devrait pas être difficile à traduire):
Étant donné un XElement x:
la source
Que diriez-vous d'utiliser cette méthode "d'extension" sur XElement? travaillé pour moi!
OU utilisez un peu de Linq
Remarque : le code ci-dessus doit utiliser
element.Nodes()
par opposition àelement.Elements()
. Chose très importante pour se rappeler la différence entre les deux.element.Nodes()
vous donne tout commeXText
,XAttribute
etc., maisXElement
seulement un élément.la source
Avec tout le mérite de ceux qui ont découvert et prouvé la meilleure approche (merci!), La voici résumée dans une méthode d'extension:
la source
Restez simple et efficace:
la source
J'ai fini par utiliser ceci:
la source
Personnellement, j'ai fini par écrire une
InnerXml
méthode d'extension en utilisant la méthode Aggregate:Mon code client est alors aussi laconique qu'il le serait avec l'ancien espace de noms System.Xml:
la source
@Greg: Il semble que vous ayez modifié votre réponse pour être une réponse complètement différente. Ce à quoi ma réponse est oui, je pourrais le faire en utilisant System.Xml mais j'espérais me mouiller les pieds avec LINQ to XML.
Je laisserai ma réponse originale ci-dessous au cas où quelqu'un d'autre se demanderait pourquoi je ne peux pas simplement utiliser la propriété .Value de XElement pour obtenir ce dont j'ai besoin:
@Greg: la propriété Value concatène tout le contenu texte de tous les nœuds enfants. Donc, si l'élément body ne contient que du texte, cela fonctionne, mais s'il contient du XHTML, je récupère tout le texte concaténé mais aucune des balises.
la source
<root>random text <sub1>child</sub1> <sub2>child</sub2></root>
) qui est devenurandom text childchild
viaXElement.Parse(...).Value
// l'utilisation de Regex peut être plus rapide pour simplement couper la balise d'élément de début et de fin
la source
IndexOf
:var xml = root.ToString(); var begin = xml.IndexOf('>')+1; var end = xml.LastIndexOf('<'); return xml.Substring(begin, end-begin);
doc.ToString () ou doc.ToString (SaveOptions) fait le travail. Voir http://msdn.microsoft.com/en-us/library/system.xml.linq.xelement.tostring(v=vs.110).aspx
la source
Est-il possible d'utiliser les objets d'espace de noms System.Xml pour effectuer le travail ici au lieu d'utiliser LINQ? Comme vous l'avez déjà mentionné, XmlNode.InnerXml est exactement ce dont vous avez besoin.
la source
Je me demande si (remarquez que je me suis débarrassé du b + = et que j'ai juste b +)
pourrait être légèrement moins efficace que
Pas sûr à 100% ... mais en regardant Aggregate () et string.Join () in Reflector ... Je pense je l'ai lu comme Aggregate en ajoutant simplement une valeur de retour, donc vous obtenez essentiellement:
chaîne = chaîne + chaîne
versus string.Join, il y a une mention de FastStringAllocation ou quelque chose du genre, ce qui me fait penser que les gens de Microsoft ont peut-être amélioré les performances. Bien sûr, mon .ToArray () appelle mon nier cela, mais je voulais juste proposer une autre suggestion.
la source
tu sais? la meilleure chose à faire est de revenir à CDATA: (je cherche des solutions ici mais je pense que CDATA est de loin le plus simple et le moins cher, pas le plus pratique à développer avec tho
la source
Fera le travail pour vous
la source
la source