【问题标题】:Write HTML to string将 HTML 写入字符串
【发布时间】:2010-11-03 12:52:45
【问题描述】:

我有这样的代码。有没有办法让它更容易编写和维护? 使用 C# .NET 3.5。

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}", "");
}

我也可以写:

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"); 

它会起作用,但我需要将所有" 替换为""

【问题讨论】:

标签: c# html


【解决方案1】:

使用HtmlTextWriterXMLWriter 可能比使用普通的StringWriter 更好。他们会为您处理转义,并确保文档格式正确。

This page 展示了使用HtmlTextWriter 类的基础知识,其要点是:

StringWriter stringWriter = new StringWriter();

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();

【讨论】:

  • 参考系统.Web
【解决方案2】:

当我用其他语言处理这个问题时,我会分离代码和 HTML。比如:

1.) 创建一个 HTML 模板。使用 [varname] 占位符来标记替换/插入的内容。
2.) 从数组或结构/映射/字典中填充模板变量

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

【讨论】:

  • 我可以获得一个如何制作 HTML 模板的示例的链接吗?用什么语言? (我可以处理非 C# 是它的 .NET)
  • 现有的模板引擎可能有助于简化此操作。有关列表,请参见维基百科:en.wikipedia.org/wiki/Template_engine_(web)
  • 这里的 Parser 类很简单/易于使用:codeproject.com/KB/dotnet/mailtemplates.aspx
  • @SpliFF - 您能否在模板中多次使用相同的 [varname] 来处理相同信息的多个位置?
【解决方案3】:

使用 XDocument 创建 DOM,然后使用 XmlWriter 将其写出。这将为您提供非常简洁易读的符号以及格式良好的输出。

以这个示例程序为例:

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);
        }
    }
}

这会生成以下输出:

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

【讨论】:

  • 我喜欢这个选项。您是否遇到过一种方法来添加与这种格式内联的属性?
  • 当然!只需在 XElement 中添加一个 XAttribute。
  • 这比使用HtmlTextWriter好多了。
  • 使用这种风格的时候可以加一些For循环吗?
【解决方案4】:

我知道你问过 C#,但如果你愿意使用任何 .Net 语言,那么我强烈推荐 Visual Basic 来解决这个确切的问题。 Visual Basic 有一个称为 XML Literals 的功能,它允许您编写这样的代码。

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

这允许您以旧的 ASP 样式编写带有表达式漏洞的直接 HTML,并使您的代码具有超级可读性。不幸的是,C# 中没有此功能,但您可以在 VB 中编写单个模块并将其添加为对您的 C# 项目的引用。

在 Visual Studio 中编写还允许对大多数 XML 文字和表达式整体进行适当的缩进。 VS2010中表达式孔的缩进效果更好。

【讨论】:

  • 我完全忘记了这一点。好电话。
  • 这是 VB 的一个非常棒的特性。我创建了一个以通用方式将任何 DataTable 转换为 HTML 表格标记的要点:gist.github.com/sergkr/13d57dca75b385f0a359
  • 希望我们在 C# 中有这个:(
【解决方案5】:
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);

【讨论】:

  • 根据标题的来源,您可能希望在盲目地将标题插入字符串之前对其进行 HTML 编码。
  • 回到当我使用这种笨拙的方法时,我会通过在我想要保留中断的html行之间添加Environment.NewLine来分隔每一行。
【解决方案6】:

您可以使用System.Xml.Linq 对象。它们是从旧的 System.Xml 时代完全重新设计的,这使得从头开始构建 XML 真的很烦人。

除了我猜的 doctype 之外,您还可以轻松地执行以下操作:

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

【讨论】:

  • 这很好,您也可以使用new XElement("div", new XAttribute("class", "container")) 为任何想知道的人创建属性。
【解决方案7】:

最直接的方法是使用 XmlWriter 对象。这可用于生成有效的 HTML,并为您处理所有讨厌的转义序列。

【讨论】:

    【解决方案8】:

    您可以使用 T4 模板 从您的代码生成 Html(或任何)。 看到这个:http://msdn.microsoft.com/en-us/library/ee844259.aspx

    【讨论】:

    • 这是一个非常酷的方法。如果您提供更多详细信息,您可能会获得更多选票。
    • 这个。请注意,T4 可以在编译时和运行时运行。
    【解决方案9】:

    如果您希望创建类似于在 C# 中创建 XML 文档的 HTML 文档,您可以尝试使用 Microsoft 的开源库 Html Agility Pack

    它提供了一个 HtmlDocument 对象,该对象的 API 与 System.Xml.XmlDocument 类非常相似。

    【讨论】:

    • Html Agility Pack 不是 Microsoft 编写的。
    • 它可能不是由微软官方赞助的,但至少它是由微软员工编写的,或者至少是一个拥有@microsoft.com 电子邮件地址的人......
    • 是的,它是由当时在微软工作的 Simon Mourier 编写的……不过我不会称它为“微软的开源库”。
    【解决方案10】:

    您可以使用 ASP.NET 在网页上下文之外生成 HTML。 Here's an article 展示了它是如何完成的。

    【讨论】:

    • 它可以用来生成 HTML 电子邮件或其他不是网站的东西。此外,这不是答案。
    • 您可以使用 ASP.NET 在网站上下文之外输出 HTML。
    • 我不会去投票反对这个,因为它是一个有效的问题,但它应该是对 OP 的评论而不是 aswer
    • Jacob 是正确的......你可以使用 ASP.NET 渲染引擎......虽然它显然不仅仅是说你可以使用它。
    • 我没有投赞成票或反对票,但我将如何使用渲染引擎?链接到任何示例的页面都可以。
    【解决方案11】:

    随着在 ASP.net MVC 中引入 Razor,在 C# 中编写 HTML 的最佳方式是使用 Razor 引擎。

    string templatePath = $@"{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); 
    

    模板:

    <h2>Dear @Model.Name, you have a notification.</h2> 
    
    <h1>@Model.Title</h1> 
    <p>@Model.Content</p> 
    
    <p>Date:@DateTime.Now</p> 
    

    如需完整示例,请参阅here

    【讨论】:

    • 这是正确的答案。虽然我建议在示例中使用最新版本的软件包。
    【解决方案12】:

    您可以使用一些第三方开源库来生成强类型验证 (X)HTML,例如 CityLizard Framework 或 Sharp DOM。

    更新例如

    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"]]
                ]
            ]
        ];
    

    【讨论】:

      【解决方案13】:

      这不是一个通用的解决方案,但是,如果您的目的是拥有或维护电子邮件模板,那么 System.Web 有一个名为 MailDefinition 的内置类。 ASP.NET 成员控件使用此类来创建 HTML 电子邮件。

      执行与上述相同的“字符串替换”操作,但将其全部打包到 MailMessage 中。

      这是一个来自 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;
      

      【讨论】:

        【解决方案14】:

        您可以使用其 Render 方法和其他属性编写自己的类,以避免大量使用它时造成很大的混乱,然后也使用 HTMLWriter 或 xmlwriter。 此逻辑用于 asp.net 页面,您可以从 webControl 继承并覆盖 render method,如果您正在开发服务器端控件,这非常好。
        This 可能是一个很好的例子。

        问候

        【讨论】:

          【解决方案15】:

          这真的取决于你的目标,特别是你真正需要提供什么样的性能。

          我已经看到了令人赞叹的强类型 HTML 开发解决方案(完整的控件模型,无论是 ASP.NET Web 控件,还是类似的),它们只会给项目增加惊人的复杂性。在其他情况下,它是完美的。

          按照 C# 世界中的优先顺序,

          • ASP.NET Web 控件
          • ASP.NET 基元和 HTML 控件
          • XmlWriter 和/或 HtmlWriter
          • 如果使用 HTML 互操作性进行 Silverlight 开发,请考虑使用强类型,例如 link text
          • StringBuilder 和其他超级原语

          【讨论】:

            【解决方案16】:

            我编写的这些课程对我很有帮助。简单实用。

            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;
                }
            }
            

            【讨论】:

              【解决方案17】:

              HSharp 是一个用于轻松快速地分析 HTML 等标记语言的库。 安装:PM&gt; 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);
              

              和输出:

              <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>
              

              【讨论】:

                【解决方案18】:

                我正在寻找类似于 jquery 的东西来在 C# 中生成 dom(我不需要解析)。不幸的是,没有找到一个轻量级的解决方案,所以我创建了这个继承自 System.Xml.Linq.XElement 的简单类。关键特性是您可以像在 javascript 中使用 jquery 一样链接运算符,因此它更加流畅。它功能不全,但可以满足我的需要,如果有兴趣,我可以启动一个 git。

                public class DomElement : XElement
                {
                    public DomElement(string name) : base(name)
                    {
                    }
                
                    public DomElement(string name, string value) : base(name, value)
                    {
                    }
                
                    public DomElement Css(string style, string value)
                    {
                        style = style.Trim();
                        value = value.Trim();
                        var existingStyles = new Dictionary<string, string>();
                        var xstyle = this.Attribute("style");
                        if (xstyle != null)
                        {
                            foreach (var s in xstyle.Value.Split(';'))
                            {
                                var keyValue = s.Split(':');
                                existingStyles.Add(keyValue[0], keyValue.Length < 2 ? null : keyValue[1]);
                            }
                        }
                
                        if (existingStyles.ContainsKey(style))
                        {
                            existingStyles[style] = value;
                        }
                        else
                        {
                            existingStyles.Add(style, value);
                        }
                
                        var styleString = string.Join(";", existingStyles.Select(s => $"{s.Key}:{s.Value}"));
                        this.SetAttributeValue("style", styleString);
                
                        return this;
                    }
                
                    public DomElement AddClass(string cssClass)
                    {
                        var existingClasses = new List<string>();
                        var xclass = this.Attribute("class");
                        if (xclass != null)
                        {
                            existingClasses.AddRange(xclass.Value.Split());
                        }
                
                        var addNewClasses = cssClass.Split().Where(e => !existingClasses.Contains(e));
                        existingClasses.AddRange(addNewClasses);
                
                        this.SetAttributeValue("class", string.Join(" ", existingClasses));
                        return this;
                    }
                
                    public DomElement Text(string text)
                    {
                        this.Value = text;
                        return this;
                    }
                
                    public DomElement Append(string text)
                    {
                        this.Add(text);
                        return this;
                    }
                
                    public DomElement Append(DomElement child)
                    {
                        this.Add(child);
                        return this;
                    }
                }
                

                示例:

                void Main()
                {
                    var html = new DomElement("html")
                        .Append(new DomElement("head"))
                        .Append(new DomElement("body")
                            .Append(new DomElement("p")
                                .Append("This paragraph contains")
                                .Append(new DomElement("b", "bold"))
                                .Append(" text.")
                                )
                            .Append(new DomElement("p").Text("This paragraph has just plain text"))
                            )
                        ;
                
                    html.ToString().Dump();
                
                    var table = new DomElement("table").AddClass("table table-sm").AddClass("table-striped")
                            .Append(new DomElement("thead")
                                .Append(new DomElement("tr")
                                    .Append(new DomElement("td").Css("padding-left", "15px").Css("color", "red").Css("color", "blue")
                                        .AddClass("from-now")
                                        .Append(new DomElement("div").Text("Hi there"))
                                        .Append(new DomElement("div").Text("Hey there"))
                                        .Append(new DomElement("div", "Yo there"))
                                        )
                                )
                            )
                        ;
                    table.ToString().Dump();
                }
                

                以上代码的输出:

                <html>
                  <head />
                  <body>
                    <p>This paragraph contains<b>bold</b> text.</p>
                    <p>This paragraph has just plain text</p>
                  </body>
                </html>
                <table class="table table-sm table-striped">
                  <thead>
                    <tr>
                      <td style="padding-left:15px;color:blue" class="from-now">
                        <div>Hi there</div>
                        <div>Hey there</div>
                        <div>Yo there</div>
                      </td>
                    </tr>
                  </thead>
                </table>
                

                【讨论】:

                  猜你喜欢
                  • 2017-03-04
                  • 2016-10-22
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2010-10-10
                  • 1970-01-01
                  • 1970-01-01
                  • 2015-09-29
                  相关资源
                  最近更新 更多