2010-11-22 6 views
6

no he encontrado una manera de utilizar XmlWriter de .NET y XmlWriterSettings asociados para dar formato a una cadena XML en forma de sangría exactamente la forma en que Visual Studio lo hace con su auto comando de formato (Ctrl-E Ctrl-D, o, dependiendo de la asignación del teclado, Ctrl-K Ctrl-D).programación formato XML en forma de sangría tal como auto-formato de Visual Studio

me gustaría hacer esto porque habitualmente auto-formato de todos mis archivos en VS, el código y los archivos .config. Tengo una aplicación de instalación que actualiza los archivos .config, y me gustaría ver diferencias reales en lugar de cambiar todo el documento.

No he explorado todas las diferentes opciones de formato para el auto-formato, pero me gusta que cada atributo XML esté en una línea separada, con el primero en la misma línea que la etiqueta de apertura y los posteriores alineados con el en primer lugar, como esto:

<asset assetId="12345" 
     bucket="default" 
     owner="nobody"> 
    <file path="\\localhost\share\assetA.mov"/> 
    <metadata metadataId="23456" 
      key="asset_type" 
      value="video"/> 
</asset> 

he intentado formatear con propiedades XmlWriterSettings 'NewLineHandling = NewLineHandling.None' y 'NewLineOnAttributes = true', pero que pone el primer atributo debajo de la etiqueta de apertura y todos los atributos tienen el mismo muesca independientemente del # de caracteres en el nombre del elemento, así:

<asset 
    assetId="12345" 
    bucket="default" 
    owner="nobody"> 
    <file 
    path="\\localhost\share\assetA.mov" /> 
    <metadata metadataId="23456" 
    key="asset_type" 
    value="video" /> 
</asset> 

en cuenta que la norma también XmlWriter termina elementos de atributo de sólo con "> /" (espacio adicional antes de la barra), que me gusta, pero no estoy seguro si eso es el estándar XML. Creo que Visual Studio usa las mismas opciones de API disponibles para los desarrolladores, pero aún no he encontrado esas configuraciones mágicas. De todos modos, aquí está mi método de formato:

public static string FormatXml(string xmlString, bool indented) 
{ 
    using (TextReader textReader = new StringReader(xmlString)) 
    using (XmlReader xmlReader = new XmlTextReader(textReader)) 
    { 
     using (TextWriter textWriter = new StringWriter()) 
     { 
      var settings = new XmlWriterSettings(); 
      if (indented) 
      { 
       settings.Indent = true; 
       settings.IndentChars = " "; 
       settings.NewLineOnAttributes = true; 
       settings.NewLineHandling = NewLineHandling.None; 
      } 
      using (var xmlWriter = XmlWriter.Create(textWriter, settings)) 
      { 
       while (xmlReader.Read()) 
        xmlWriter.WriteNode(xmlReader, false); 
      } 
      return textWriter.ToString(); 
     } 
    } 
} 
+1

No está ahí. –

Respuesta

1

No entendí la pregunta. En realidad, no sé si hay una forma de alinear los atributos de la manera que se muestra. Se podría tratar de aplicar por sí mismo, algo como esto:

public static string FormatXml(string xmlString, bool indented) 
    { 
     using (TextReader textReader = new StringReader(xmlString)) 
     using (XmlReader xmlReader = new XmlTextReader(textReader)) 
     { 
      using (TextWriter textWriter = new StringWriter()) 
      { 
       string indent = ""; 
       string attributeIndent = ""; 

       while (xmlReader.Read()) 
       { 
        if (xmlReader.NodeType == XmlNodeType.Element) 
        { 
         attributeIndent = ""; 
         string element = xmlReader.Name; 
         textWriter.Write("{0}<{1}", indent, element); 

         if (!xmlReader.HasAttributes) 
          textWriter.WriteLine(">"); 
         else 
         { 
          int actual = 1; 
          while (xmlReader.MoveToNextAttribute()) 
          { 
           string content = String.Format("{0} {1}={2}", attributeIndent, xmlReader.Name, xmlReader.Value); 
           if (actual != xmlReader.AttributeCount) 
            textWriter.WriteLine(content); 
           else 
            textWriter.Write(content); 

           if (string.IsNullOrEmpty(attributeIndent)) 
            attributeIndent = indent + Enumerable.Repeat<string>(" ", element.Length + 1).Aggregate((a, b) => a + b); 

           actual++; 
          } 
          xmlReader.MoveToElement(); 
          textWriter.WriteLine(">"); 
          attributeIndent = ""; 
         } 
         if (!xmlReader.IsEmptyElement) 
         { 
          indent += " "; 
          textWriter.WriteLine(">"); 
         } 
         else 
          textWriter.WriteLine("/>"); 
        } 
        else if (xmlReader.NodeType == XmlNodeType.EndElement) 
        { 
         indent = indent.Substring(0, indent.Length - 2); 
         textWriter.WriteLine("{0}</{1}>", indent, xmlReader.Name); 
        } 
        else if (xmlReader.NodeType == XmlNodeType.Text) 
        { 
         textWriter.WriteLine(xmlReader.Value); 
        } 
       } 

       return textWriter.ToString(); 
      } 
     } 
    } 
+0

Gracias por el ejemplo. Todavía no lo he probado, pero sabía que siempre podía sacar los elementos manualmente y lidiar con los diferentes tipos de nodos, pero esperaba que Microsoft no ocultara su implementación de Visual Studio. – Erhhung

+0

Bueno, en realidad no sé si hay algo; Google no encontré nada. Espero que lo que publique pueda ayudarte. –

0

creo que citas son XML no válido, lo que puede dar al lector/escritor de cierta acidez. Aparte de eso, ¿por qué no le dices a tu aplicación de diferencias que ignore el espacio en blanco?

Cuestiones relacionadas