Ich wollte sehen, welche dieser Lösungsvorschläge am besten funktioniert, und führte daher einige Vergleichstests durch. Aus Interesse habe ich auch die LINQ-Methoden mit der von Greg vorgeschlagenen einfachen System.Xml- Methode verglichen . Die Variation war interessant und nicht das, was ich erwartet hatte. Die langsamsten Methoden waren mehr als dreimal langsamer als die schnellsten .
Die Ergebnisse sortiert nach schnellsten bis langsamsten:
- CreateReader - Instance Hunter (0,113 Sekunden)
- Einfache alte System.Xml - Greg Hurlman (0,134 Sekunden)
- Aggregat mit String-Verkettung - Mike Powell (0,324 Sekunden)
- StringBuilder - Vin (0,333 Sekunden)
- String.Join on Array - Terry (0,360 Sekunden)
- String.Concat auf Array - Marcin Kosieradzki (0.364)
Methode
Ich habe ein einzelnes XML-Dokument mit 20 identischen Knoten verwendet (als "Hinweis" bezeichnet):
<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>
Die oben als Sekunden angezeigten Zahlen sind das Ergebnis des Extrahierens des "inneren XML" der 20 Knoten, 1000 Mal hintereinander, und des Durchschnitts (Mittelwerts) von 5 Läufen. Ich habe nicht die Zeit angegeben, die zum Laden und Parsen des XML in eine XmlDocument
(für die System.Xml- Methode) oder XDocument
(für alle anderen) benötigt wurde.
Die von mir verwendeten LINQ-Algorithmen waren: (C # - alle nehmen ein XElement
"übergeordnetes Element" und geben die innere XML-Zeichenfolge zurück)
CreateReader:
var reader = parent.CreateReader();
reader.MoveToContent();
return reader.ReadInnerXml();
Aggregat mit Zeichenfolgenverkettung:
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 on Array:
return String.Join("", parent.Nodes().Select(x => x.ToString()).ToArray());
String.Concat auf Array:
return String.Concat(parent.Nodes().Select(x => x.ToString()).ToArray());
Ich habe den Algorithmus "Plain old System.Xml" hier nicht gezeigt, da er nur .InnerXml auf Knoten aufruft.
Fazit
Wenn die Leistung wichtig ist (z. B. viel XML, häufig analysiert), würde ich jedes Mal Daniels CreateReader
Methode verwenden . Wenn Sie nur ein paar Abfragen durchführen, möchten Sie möglicherweise Mikes präzisere Aggregatmethode verwenden.
Wenn Sie XML für große Elemente mit vielen Knoten (möglicherweise 100) verwenden, werden Sie wahrscheinlich den Vorteil der Verwendung StringBuilder
gegenüber der Aggregatmethode erkennen, jedoch nicht über CreateReader
. Ich denke nicht, dass die Methoden Join
und unter Concat
diesen Bedingungen jemals effizienter wären, da die Konvertierung einer großen Liste in ein großes Array die Strafe darstellt (auch hier bei kleineren Listen offensichtlich).
parent.CreateNavigator().InnerXml
(Notwendigkeitusing System.Xml.XPath
für die Erweiterungsmethode)..ToArray()
Innere brauchen.Concat
, aber es scheint es schneller zu machen.ToString()
gemäß dieser Antwort zu entfernen . Scheint noch schneller ...var reader = parent.CreateReader();
in eine using-Anweisung einschließen.Ich denke, dies ist eine viel bessere Methode (in VB sollte es nicht schwer sein, sie zu übersetzen):
Bei einem XElement x:
quelle
Wie wäre es mit dieser "Erweiterungs" -Methode auf XElement? hat für mich gearbeitet!
ODER verwenden Sie ein wenig Linq
Hinweis : Der obige Code muss
element.Nodes()
im Gegensatz zu verwendet werdenelement.Elements()
. Sehr wichtig, um sich an den Unterschied zwischen den beiden zu erinnern.element.Nodes()
gibt Ihnen alles , wieXText
,XAttribute
etc, aberXElement
nur ein Element.quelle
Bei aller Anerkennung für diejenigen, die den besten Ansatz entdeckt und bewiesen haben (danke!), Wird er hier in eine Erweiterungsmethode eingepackt:
quelle
Halten Sie es einfach und effizient:
quelle
Am Ende habe ich Folgendes verwendet:
quelle
Persönlich habe ich eine
InnerXml
Erweiterungsmethode mit der Aggregatmethode geschrieben:Mein Client-Code ist dann genauso knapp wie beim alten System.Xml-Namespace:
quelle
@ Greg: Anscheinend haben Sie Ihre Antwort so bearbeitet, dass sie eine völlig andere Antwort ist. Auf die ich mit Ja antworte, könnte ich dies mit System.Xml tun, hatte aber gehofft, meine Füße mit LINQ to XML nass zu machen.
Ich werde meine ursprüngliche Antwort unten hinterlassen, falls sich jemand fragt, warum ich nicht einfach die .Value-Eigenschaft des XElement verwenden kann, um das zu erhalten, was ich brauche:
@Greg: Die Value-Eigenschaft verkettet den gesamten Textinhalt aller untergeordneten Knoten. Wenn das body-Element nur Text enthält, funktioniert es, aber wenn es XHTML enthält, wird der gesamte Text verkettet, aber keines der Tags.
quelle
<root>random text <sub1>child</sub1> <sub2>child</sub2></root>
random text childchild
XElement.Parse(...).Value
// Die Verwendung von Regex ist möglicherweise schneller, um das Anfangs- und Endelement-Tag einfach zu kürzen
quelle
IndexOf
:var xml = root.ToString(); var begin = xml.IndexOf('>')+1; var end = xml.LastIndexOf('<'); return xml.Substring(begin, end-begin);
doc.ToString () oder doc.ToString (SaveOptions) erledigt die Arbeit. Siehe http://msdn.microsoft.com/en-us/library/system.xml.linq.xelement.tostring(v=vs.110).aspx
quelle
Ist es möglich, die System.Xml-Namespace-Objekte zu verwenden, um den Job hier zu erledigen, anstatt LINQ zu verwenden? Wie Sie bereits erwähnt haben, ist XmlNode.InnerXml genau das, was Sie brauchen.
quelle
Ich frage mich, ob (beachte, dass ich das b + = losgeworden bin und nur b + habe)
könnte etwas weniger effizient sein als
Nicht 100% sicher ... aber ein Blick auf Aggregate () und string.Join () in Reflector ... Ich glaube, ich habe es als Aggregat gelesen, indem ich nur einen Rückgabewert anhänge , also erhalten Sie im Wesentlichen:
string = string + string
versus string.Join, es gibt dort einige Erwähnungen von FastStringAllocation oder so, was mich dazu bringt, dass die Leute bei Microsoft dort möglicherweise einen zusätzlichen Leistungsschub eingebracht haben. Natürlich nennt mein .ToArray () mein Negieren so, aber ich wollte nur einen weiteren Vorschlag machen.
quelle
Wissen Sie? Das Beste, was Sie tun können, ist, zu CDATA zurückzukehren :( Ich suche hier nach Lösungen, aber ich denke, CDATA ist bei weitem die einfachste und billigste, nicht die bequemste, die man mit tho entwickeln kann
quelle
Erledigt den Job für Sie
quelle
quelle