Quería ver cuál de estas soluciones sugeridas funcionaba mejor, así que realicé algunas pruebas comparativas. Por interés, también comparé los métodos LINQ con el antiguo método System.Xml sugerido por Greg. La variación fue interesante y no era lo que esperaba, ya que los métodos más lentos son más de 3 veces más lentos que los más rápidos .
Los resultados ordenados por más rápido a más lento:
- CreateReader - Instance Hunter (0.113 segundos)
- System.Xml simple y antiguo - Greg Hurlman (0.134 segundos)
- Agregado con concatenación de cadenas - Mike Powell (0.324 segundos)
- StringBuilder - Vin (0.333 segundos)
- String.Join on array - Terry (0.360 segundos)
- String.Concat on array - Marcin Kosieradzki (0.364)
Método
Usé un solo documento XML con 20 nodos idénticos (llamado 'sugerencia'):
<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>
Los números que se muestran como segundos arriba son el resultado de extraer el "XML interno" de los 20 nodos, 1000 veces seguidas, y tomar el promedio (media) de 5 ejecuciones. No incluí el tiempo que tardó en cargar y analizar el XML en un XmlDocument
(para el método System.Xml ) oXDocument
(para todos los demás).
Los algoritmos LINQ que utilicé fueron: (C #: todos toman un XElement
"padre" y devuelven la cadena XML interna)
CreateReader:
var reader = parent.CreateReader();
reader.MoveToContent();
return reader.ReadInnerXml();
Agregado con concatenación de cadenas:
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 en matriz:
return String.Join("", parent.Nodes().Select(x => x.ToString()).ToArray());
String.Concat en la matriz:
return String.Concat(parent.Nodes().Select(x => x.ToString()).ToArray());
No he mostrado el algoritmo "Plain old System.Xml" aquí, ya que solo está llamando a .InnerXml en los nodos.
Conclusión
Si el rendimiento es importante (por ejemplo, mucho XML, analizado con frecuencia), usaría el CreateReader
método de Daniel cada vez . Si solo está haciendo algunas consultas, es posible que desee utilizar el método agregado más conciso de Mike.
Si está utilizando XML en elementos grandes con muchos nodos (tal vez 100), probablemente comenzará a ver el beneficio de usar StringBuilder
sobre el método Aggregate, pero no más CreateReader
. No creo que los métodos Join
y Concat
sean más eficientes en estas condiciones debido a la penalidad de convertir una lista grande en una gran matriz (incluso obvio aquí con listas más pequeñas).
parent.CreateNavigator().InnerXml
(necesitasusing System.Xml.XPath
el método de extensión)..ToArray()
interior.Concat
, pero parece que lo hace más rápido.ToString()
por esta respuesta . Parece aún más rápido ...var reader = parent.CreateReader();
en una declaración de uso.Creo que este es un método mucho mejor (en VB, no debería ser difícil de traducir):
Dado un XElement x:
fuente
¿Qué tal usar este método de "extensión" en XElement? trabajó para mi !
O use un poco de Linq
Nota : El código anterior tiene que usarse
element.Nodes()
en lugar deelement.Elements()
. Algo muy importante para recordar la diferencia entre los dos.element.Nodes()
te da todoXText
,XAttribute
etc., peroXElement
solo un elemento.fuente
Con todo el crédito debido a aquellos que descubrieron y probaron el mejor enfoque (¡gracias!), Aquí está envuelto en un método de extensión:
fuente
Mantenlo simple y eficiente:
fuente
Terminé usando esto:
fuente
Personalmente, terminé escribiendo un
InnerXml
método de extensión usando el método Agregado:Mi código de cliente es tan breve como lo sería con el antiguo espacio de nombres System.Xml:
fuente
@ Greg: Parece que has editado tu respuesta para que sea una respuesta completamente diferente. A lo que mi respuesta es sí, podría hacer esto usando System.Xml pero esperaba mojarme los pies con LINQ to XML.
Dejaré mi respuesta original a continuación en caso de que alguien más se pregunte por qué no puedo usar la propiedad .Value de XElement para obtener lo que necesito:
@Greg: la propiedad Value concatena todo el contenido de texto de cualquier nodo secundario. Entonces, si el elemento del cuerpo contiene solo texto, funciona, pero si contiene XHTML obtengo todo el texto concatenado pero ninguna de las etiquetas.
fuente
<root>random text <sub1>child</sub1> <sub2>child</sub2></root>
) que se convirtiórandom text childchild
enXElement.Parse(...).Value
// el uso de Regex podría ser más rápido para simplemente recortar la etiqueta de elemento de inicio y fin
fuente
IndexOf
:var xml = root.ToString(); var begin = xml.IndexOf('>')+1; var end = xml.LastIndexOf('<'); return xml.Substring(begin, end-begin);
doc.ToString () o doc.ToString (SaveOptions) hace el trabajo. Ver http://msdn.microsoft.com/en-us/library/system.xml.linq.xelement.tostring(v=vs.110).aspx
fuente
¿Es posible usar los objetos de espacio de nombres System.Xml para hacer el trabajo aquí en lugar de usar LINQ? Como ya mencionó, XmlNode.InnerXml es exactamente lo que necesita.
fuente
Preguntándome si (observe que me deshice de b + = y solo tengo b +)
podría ser un poco menos eficiente que
No estoy 100% seguro ... pero mirando Aggregate () y string.Join () en Reflector ... creo lo leí como Aggregate solo agregando un valor de retorno, así que esencialmente obtienes:
cadena = cadena + cadena
versus string.Join, tiene alguna mención allí de FastStringAllocation o algo así, lo que me hace pensar que la gente de Microsoft podría haber puesto un aumento de rendimiento adicional allí. Por supuesto, mi .ToArray () llama a mi negado eso, pero solo quería ofrecer otra sugerencia.
fuente
¿ya sabes? Lo mejor que puede hacer es volver a CDATA :( Estoy buscando soluciones aquí, pero creo que CDATA es, con mucho, el más simple y barato, no el más conveniente para desarrollar con
fuente
Hará el trabajo por ti
fuente
fuente