2009-06-17 103 views
36

Tengo un código como este. ¿Hay alguna forma de facilitar la escritura y el mantenimiento? Utilizando C# .NET 3,5Escribir html en C#

string header(string title) 
{ 
    StringWriter s = new StringWriter(); 
    s.WriteLine("{0}","<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">"); 
    s.WriteLine("{0}", "<html>"); 
    s.WriteLine("<title>{0}</title>", title); 
    s.WriteLine("{0}","<link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\">"); 
    s.WriteLine("{0}", "</head>"); 
    s.WriteLine("{0}", "<body>"); 
    s.WriteLine("{0}", ""); 
} 

operación -Editar- que no sabía entonces, pero que podría escribir

s.WriteLine("{0}", @"blah blah 

many 
new 
lines 
blah UHY#$&_#$_*@Y KSDSD<>\t\t\t\t\t\tt\t\t\\\t\t\t\t\\\h\th'\h't\th 
hi 
done"); 

y funcionará pero que tenga que reemplazar todos "con ''

+14

Es bueno que relize esto es una mala manera de hacer un archivo HTML utilizando un programa. – Kredns

+1

duplicado: http://stackoverflow.com/questions/937201 http://stackoverflow.com/questions/897226 http://stackoverflow.com/questions/340095 http://stackoverflow.com/questions/346449 –

+0

por qué usar el '{0}' en absoluto? Excepto por el título, no lo necesitas. Puedes simplemente poner tu cadena como primer argumento y no usar un segundo argumento. –

Respuesta

68

Usted Probablemente sea mejor usar un HtmlTextWriter o un XMLWriter que un simple StringWriter. Se encargarán de escaparse por usted, así como de asegurarse de que el documento esté bien formado.

This page muestra el uso básico de la clase HtmlTextWriter, la esencia de la cual el ser:

using (HtmlTextWriter writer = new HtmlTextWriter(stringWriter)) 
{ 
    writer.AddAttribute(HtmlTextWriterAttribute.Class, classValue); 
    writer.RenderBeginTag(HtmlTextWriterTag.Div); // Begin #1 

    writer.AddAttribute(HtmlTextWriterAttribute.Href, urlValue); 
    writer.RenderBeginTag(HtmlTextWriterTag.A); // Begin #2 

    writer.AddAttribute(HtmlTextWriterAttribute.Src, imageValue); 
    writer.AddAttribute(HtmlTextWriterAttribute.Width, "60"); 
    writer.AddAttribute(HtmlTextWriterAttribute.Height, "60"); 
    writer.AddAttribute(HtmlTextWriterAttribute.Alt, ""); 

    writer.RenderBeginTag(HtmlTextWriterTag.Img); // Begin #3 
    writer.RenderEndTag(); // End #3 

    writer.Write(word); 

    writer.RenderEndTag(); // End #2 
    writer.RenderEndTag(); // End #1 
} 
// Return the result. 
return stringWriter.ToString(); 
+0

+1 como buena respuesta + enlace a una página de ejemplo – xr280xr

22

Cuando me ocupo de este problema en otros idiomas que voy para la separación de código y HTML. Algo como:

1.) Cree una plantilla HTML. use los marcadores de posición [varname] para marcar el contenido reemplazado/insertado.
2.) Llene sus variables de plantilla a partir de una matriz o estructura/mapeo/Diccionario

Write(FillTemplate(myHTMLTemplate, myVariables)) # pseudo-code 
+0

¿puedo obtener un enlace a un ejemplo de cómo crear una plantilla HTML? en cualquier idioma? (Puedo tratar con no C# es su .NET) –

+0

Existen motores de plantillas existentes que pueden ayudar a hacer esto más fácil. Ver wikipedia para una lista: http://en.wikipedia.org/wiki/Template_engine_(web) – iammichael

+0

La clase Parser aquí es simple/fácil de usar: http://www.codeproject.com/KB/dotnet/mailtemplates .aspx – russau

4
return string.Format(@"<!DOCTYPE HTML PUBLIC ""-//W3C//DTD HTML 4.01//EN""  ""http://www.w3.org/TR/html4/strict.dtd""> 
<html> 
<title>{0}</title> 
<link rel=""stylesheet"" type=""text/css"" href=""style.css""> 
</head> 
<body> 
", title); 
+2

Dependiendo de dónde proviene el título, es probable que desee codificar el título HTML antes de insertarlo ciegamente en una cadena. – Jacob

+0

¿Eso mantendría líneas nuevas? –

+0

Cuando usaba un método tan torpe, separaba cada línea al agregar un 'Environment.NewLine' entre líneas html donde quería mantener los saltos. – ProfK

2

Puede utilizar ASP.NET para generar el código HTML fuera del contexto de las páginas web. Here's an article que muestra cómo se puede hacer.

+1

Podría usarse para generar un correo electrónico HTML u otra cosa que no sea un sitio web. Además, esta no es una respuesta. – llamaoo7

+2

Puede usar ASP.NET para imprimir HTML fuera del contexto de un sitio web. – Jacob

+0

No iría tan lejos como la votación negativa, ya que es una pregunta válida, pero debería haber sido un comentario para el OP en lugar de un aswer –

0

Se puede escribir sus propias clases con su método Render, y otros atributos, para evitar un gran desastre si lo usa mucho, y luego usar el HTMLWriter o la xmlwriter así . Esta lógica se usa en las páginas asp.net, puede heredar de webControl y anular render method, lo cual es excelente si está desarrollando controles del lado del servidor.
This podría ser un buen ejemplo.

Saludos

0

Realmente depende de lo que usted va para, y en concreto, qué tipo de rendimiento que realmente necesita para ofrecer.

He visto soluciones admirables para el desarrollo de HTML fuertemente tipado (modelos de control completos, ya sean ASP.NET Web Controls, o similares) que simplemente agregan complejidad increíble a un proyecto. En otras situaciones, es perfecto.

En orden de preferencia en el mundo C#,

  • Web ASP.NET Controles
  • ASP.primitivas NET y HTML controla
  • XmlWriter y/o HtmlWriter
  • Si hacer el desarrollo de Silverlight con la interoperabilidad HTML, consideran algo inflexible como link text
  • StringBuilder y otras primitivas súper
4

Usted podría utilizar System.Xml.Linq objetos. Fueron totalmente rediseñados a partir de los antiguos System.Xml días, lo que hizo que construir XML desde cero fuera realmente molesto.

Aparte del tipo de documento que supongo, fácilmente se podría hacer algo como:

var html = new XElement("html", 
    new XElement("head", 
     new XElement("title", "My Page") 
    ), 
    new XElement("body", 
     "this is some text" 
    ) 
); 
12

Sé que preguntó acerca de C#, pero si usted está dispuesto a utilizar cualquier lenguaje .Net entonces le recomiendo Visual Basic para este problema exacto. Visual Basic tiene una característica llamada XML Literals que le permitirá escribir código como este.

Module Module1 

    Sub Main() 

     Dim myTitle = "Hello HTML" 
     Dim myHTML = <html> 
         <head> 
          <title><%= myTitle %></title> 
         </head> 
         <body> 
          <h1>Welcome</h1> 
          <table> 
           <tr><th>ID</th><th>Name</th></tr> 
           <tr><td>1</td><td>CouldBeAVariable</td></tr> 
          </table> 
         </body> 
        </html> 

     Console.WriteLine(myHTML) 
    End Sub 

End Module 

Esto le permite escribir HTML directamente con los agujeros de expresión en el estilo ASP de edad y hace que su código muy legible. Lamentablemente, esta característica no está en C#, pero podría escribir un único módulo en VB y agregarlo como referencia a su proyecto de C#.

Escribir en Visual Studio también permite la sangría adecuada para la mayoría de XML Literals y total de expresión. La sangría para los agujeros de expresión es mejor en VS2010.

+1

Me olvidé por completo de eso. Buena llamada. – Josh

+1

Esta es una característica realmente impresionante de VB. Creé una esencia que convierte cualquier DataTable en una etiqueta de tabla HTML de forma genérica: https://gist.github.com/sergkr/13d57dca75b385f0a359 –

2

Si está buscando crear un documento HTML similar a cómo crearía un documento XML en C#, podría probar la biblioteca de código abierto de Microsoft, Html Agility Pack.

Proporciona un objeto HtmlDocument que tiene una API muy similar a la clase System.Xml.XmlDocument.

+1

Html Agility Pack no fue escrito por Microsoft. –

+1

Probablemente no fue patrocinado oficialmente por Microsoft, pero al menos fue escrito por un empleado de Microsoft, o al menos alguien con una dirección de correo electrónico de @ microsoft.com ... –

+4

Sí, fue escrito por Simon Mourier, quien en ese tiempo estaba funcionando en Microsoft ... aunque no lo llamaría "biblioteca de código abierto de Microsoft". –

1

Esto no es una solución genérica, sin embargo, si su pupose debe tener o mantener plantillas de correo electrónico entonces System.Web tiene una clase incorporada llamada MailDefinition. Los controles de membresía de ASP.NET utilizan esta clase para crear correos electrónicos HTML.

Hace el mismo tipo de cosas 'cadena reemplazar' como se mencionó anteriormente, pero lo empaqueta todo en un MailMessage para usted.

Aquí se muestra un ejemplo de MSDN:

ListDictionary replacements = new ListDictionary(); 
replacements.Add("<%To%>",sourceTo.Text); 
replacements.Add("<%From%>", md.From); 
System.Net.Mail.MailMessage fileMsg; 
fileMsg = md.CreateMailMessage(toAddresses, replacements, emailTemplate, this); 
return fileMsg; 
2

Se podía utilizar algunas bibliotecas de código abierto de terceras partes a verificada (X) HTML generado tipos fuertes, tales como CityLizard Framework o agudo DOM.

actualización Por ejemplo

html 
    [head 
     [title["Title of the page"]] 
     [meta_(
      content: "text/html;charset=UTF-8", 
      http_equiv: "Content-Type") 
     ] 
     [link_(href: "css/style.css", rel: "stylesheet", type: "text/css")] 
     [script_(type: "text/javascript", src: "/JavaScript/jquery-1.4.2.min.js")] 
    ] 
    [body 
     [div 
      [h1["Test Form to Test"]] 
      [form_(action: "post", id: "Form1") 
       [div 
        [label["Parameter"]] 
        [input_(type: "text", value: "Enter value")] 
        [input_(type: "submit", value: "Submit!")] 
       ] 
      ] 
      [div 
       [p["Textual description of the footer"]] 
       [a_(href: "http://google.com/") 
        [span["You can find us here"]] 
       ] 
       [div["Another nested container"]] 
      ] 
     ] 
    ]; 
0

me escribió estas clases que me sirvió de mucho. Es simple pero pragmático.

public class HtmlAttribute 
{ 
    public string Name { get; set; } 
    public string Value { get; set; } 

    public HtmlAttribute(string name) : this(name, null) { } 

    public HtmlAttribute(
     string name, 
     string @value) 
    { 
     this.Name = name; 
     this.Value = @value; 
    } 

    public override string ToString() 
    { 
     if (string.IsNullOrEmpty(this.Value)) 
      return this.Name; 

     if (this.Value.Contains('"')) 
      return string.Format("{0}='{1}'", this.Name, this.Value); 

     return string.Format("{0}=\"{1}\"", this.Name, this.Value); 
    } 
} 

public class HtmlElement 
{ 
    protected List<HtmlAttribute> Attributes { get; set; } 
    protected List<object> Childs { get; set; } 
    public string Name { get; set; } 
    protected HtmlElement Parent { get; set; } 

    public HtmlElement() : this(null) { } 

    public HtmlElement(string name, params object[] childs) 
    { 
     this.Name = name; 
     this.Attributes = new List<HtmlAttribute>(); 
     this.Childs = new List<object>(); 

     if (childs != null && childs.Length > 0) 
     { 
      foreach (var c in childs) 
      { 
       Add(c); 
      } 
     } 
    } 

    public void Add(object o) 
    { 
     var a = o as HtmlAttribute; 
     if (a != null) 
      this.Attributes.Add(a); 
     else 
     { 
      var h = o as HtmlElement; 
      if (h != null && !string.IsNullOrEmpty(this.Name)) 
      { 
       h.Parent = this; 
       this.Childs.Add(h); 
      } 
      else 
       this.Childs.Add(o); 
     } 
    } 

    public override string ToString() 
    { 
     var result = new StringBuilder(); 

     if (!string.IsNullOrEmpty(this.Name)) 
     { 
      result.Append(string.Format("<{0}", this.Name)); 
      if (this.Attributes.Count > 0) 
      { 
       result.Append(" "); 
       foreach (var attr in this.Attributes) 
       { 
        result.Append(attr.ToString()); 
        result.Append(" "); 
       } 

       result = new StringBuilder(result.ToString().TrimEnd(' ')); 
      } 

      if (this.Childs.Count == 0) 
      { 
       result.Append(" />"); 
      } 
      else 
      { 
       result.AppendLine(">"); 

       foreach (var c in this.Childs) 
       { 
        var cParts = c.ToString().Split('\n'); 

        foreach (var p in cParts) 
        { 
         result.AppendLine(string.Format("{0}", p)); 
        } 
       } 

       result.Append(string.Format("</{0}>", this.Name)); 
      } 
     } 
     else 
     { 
      foreach (var c in this.Childs) 
      { 
       var cParts = c.ToString().Split('\n'); 

       foreach (var p in cParts) 
       { 
        result.AppendLine(string.Format("{0}", p)); 
       } 
      } 
     } 

     var head = GetHeading(this); 

     var ps = result.ToString().Split('\n'); 
     return string.Join("\r\n", (from p in ps select head + p.TrimEnd('\r')).ToArray()); 
    } 

    string GetHeading(HtmlElement h) 
    { 
     if (h.Parent != null) 
      return " "; 
     else 
      return string.Empty; 
    } 
} 
4

Puede utilizar plantillas T4 para la generación de HTML (o cualquier otro) desde el código. vea esto: http://msdn.microsoft.com/en-us/library/ee844259.aspx

+0

Este es un método realmente genial. Es probable que haya obtenido más votos si hubiera incluido más detalles. – oldegreyg

+0

Esto. Tenga en cuenta que T4 se puede ejecutar tanto en tiempo de compilación como en tiempo de ejecución. –

4

Use XDocument para crear el DOM, luego escríbalo usando XmlWriter.Esto le dará una notación maravillosamente conciso y legible, así como una salida muy formateada.

Tome este programa de ejemplo:

using System.Xml; 
using System.Xml.Linq; 

class Program { 
    static void Main() { 
     var xDocument = new XDocument(
      new XDocumentType("html", null, null, null), 
      new XElement("html", 
       new XElement("head"), 
       new XElement("body", 
        new XElement("p", 
         "This paragraph contains ", new XElement("b", "bold"), " text." 
        ), 
        new XElement("p", 
         "This paragraph has just plain text." 
        ) 
       ) 
      ) 
     ); 

     var settings = new XmlWriterSettings { 
      OmitXmlDeclaration = true, Indent = true, IndentChars = "\t" 
     }; 
     using (var writer = XmlWriter.Create(@"C:\Users\wolf\Desktop\test.html", settings)) { 
      xDocument.WriteTo(writer); 
     } 
    } 
} 

Esto genera el siguiente resultado:

<!DOCTYPE html > 
<html> 
    <head /> 
    <body> 
     <p>This paragraph contains <b>bold</b> text.</p> 
     <p>This paragraph has just plain text.</p> 
    </body> 
</html> 
+0

Me encanta esta opción. ¿Has encontrado una manera de agregar atributos en línea con este formato? – oldegreyg

+0

¡Claro! Simplemente agregue un XAttribute dentro de un XElement. –

0

HSharp es una biblioteca usada para analizar el lenguaje de marcado como HTML fácil y rápidamente. Instalar: PM> Install-Package Obisoft.HSharp

 var Document = new HDoc(DocumentOptions.BasicHTML); 
     Document["html"]["body"].AddChild("div"); 
     Document["html"]["body"]["div"].AddChild("a", new HProp("href", "/#")); 
     Document["html"]["body"]["div"].AddChild("table"); 
     Document["html"]["body"]["div"]["table"].AddChildren(
     new HTag("tr"), 
     new HTag("tr", "SomeText"), 
     new HTag("tr", new HTag("td"))); 
     var Result = Document.GenerateHTML(); 
     Console.WriteLine(Result); 

y de salida:

<html> 
<head> 
<meta charset="utf-8"></meta><title> 
Example </title> 
</head> 
<body> 
<div> 
<a href="/#"></a><table> 
<tr></tr><tr> 
SomeText </tr> 
<tr> 
<td></td></tr> 
</table> 
</div> 
</body> 
</html> 
0

Con la introducción de la maquinilla de afeitar en ASP.net MVC, la mejor manera de escribir HTML en C# es con la maquinilla de afeitar del motor.

string templatePath = [email protected]"{Directory.GetCurrentDirectory()}\EmailTemplates"; 

IRazorLightEngine engine = EngineFactory.CreatePhysical(templatePath); 

var model = new Notification 
{ 
     Name = "Jone", 
     Title = "Test Email", 
     Content = "This is a test" 
}; 

string result = engine.Parse("template.cshtml", model); 

Plantilla:

<h2>Dear @Model.Name, you have a notification.</h2> 

<h1>@Model.Title</h1> 
<p>@Model.Content</p> 

<p>Date:@DateTime.Now</p> 

Para una muestra completa, ver here

Cuestiones relacionadas