-->

How to avoid System.Xml.Linq.XElement escaping HTM

2020-03-03 08:10发布

问题:

I'm using the XElement object to build some HTML in the code-behind on an ASP.NET page.

I may or may not add some XAttributes to this XElement as I go along, in the following fashion:

var elmnt = new XElement("div",
     new XAttribute("id", "myDiv"),
     );

Now, if I want to add some content into myDiv which contains HTML, the XElement automatically escapes this which, in my situation, is undesirable.

So if I have:

var elmnt = new XElement("div",
     new XAttribute("id", "myDiv"),
     "<span id='content'>hello world</span>"
     );

And then I render this into a Placeholder object using the following code:

myPlaceholder.Controls.Add(new System.Web.UI.WebControls.Literal { Text = elmnt.CreateNavigator().OuterXml });

When the page loads, the source reveals that the inner content inside elmnt has been escaped, and has the following format in the page's source:

&lt;span id='content'&gt;hello world&lt;/span&gt;

Given that the XML I'm compiling here is valid HTML, and the inner content is also valid HTML, how can I tell the XElement parent object to not escape the inner content? How can I leave it in its native format?

回答1:

 var elmnt = new XElement("div",
   new XAttribute("id", "myDiv"),
   new XRaw("<span id='content'>hello world</span>")
 );


public class XRaw : XText
{
  public XRaw(string text):base(text){}
  public XRaw(XText text): base(text){}

  public override void WriteTo(System.Xml.XmlWriter writer)
  {
    writer.WriteRaw(this.Value);
  }
}


回答2:

If you are treating the HTML as XML then when you add to it you have to add XML

Thus you would make a new xmlelement (span), add an attribute (for attribute id, value content) and then set it's contents to "hello world". Take this xmlelement and add it to the tree in the right spot.

All of this seems to be heading in the wrong direction to me. If you want to be able to have "dynamic" content in the code behind I would suggest: adding a asp:label or aps:placeholder control to the page and then setting the content of that control to the html in the code behind. This is the standard way of adding dynamic content.



回答3:

I resolved this by using the HtmlAgilitypack to convert the string of HTML into a hierarchical object.

I then looped through each HTML element in this object and created a nested XElement for each.

There's a little bit of checking that needs done on every element, but it works perfectly and has fewer lines of code than I expected when I started building it.



回答4:

Why wouldn't you use HtmlTextWriter?

StringWriter stringWriter = new StringWriter();

HtmlTextWriter htmlWriter = new HtmlTextWriter(stringWriter);
htmlWriter.RenderBeginTag(HtmlTextWriterTag.Span);
htmlWriter.AddAttribute(HtmlTextWriterAttribute.Id, "content");
htmlWriter.Write("hello world");
htmlWriter.RenderEndTag();

htmlWriter.Flush();

stringWriter.ToString(); //<span id='content'>hello world</span>