HtmlMarkupFormatter
Represents the standard HTML5 markup formatter.
using AngleSharp.Dom;
using AngleSharp.Extensions;
using System.Text;
namespace AngleSharp.Html
{
public sealed class HtmlMarkupFormatter : IMarkupFormatter
{
public static readonly IMarkupFormatter Instance = new HtmlMarkupFormatter();
string IMarkupFormatter.Comment(IComment comment)
{
return "<!--" + comment.Data + "-->";
}
string IMarkupFormatter.Doctype(IDocumentType doctype)
{
string ids = GetIds(doctype.PublicIdentifier, doctype.SystemIdentifier);
return "<!DOCTYPE " + doctype.Name + ids + ">";
}
string IMarkupFormatter.Processing(IProcessingInstruction processing)
{
string str = processing.Target + " " + processing.Data;
return "<?" + str + ">";
}
string IMarkupFormatter.Text(string text)
{
StringBuilder stringBuilder = Pool.NewStringBuilder();
for (int i = 0; i < text.Length; i++) {
switch (text[i]) {
case '&':
stringBuilder.Append("&");
break;
case ' ':
stringBuilder.Append(" ");
break;
case '>':
stringBuilder.Append(">");
break;
case '<':
stringBuilder.Append("<");
break;
default:
stringBuilder.Append(text[i]);
break;
}
}
return stringBuilder.ToPool();
}
string IMarkupFormatter.OpenTag(IElement element, bool selfClosing)
{
StringBuilder stringBuilder = Pool.NewStringBuilder();
stringBuilder.Append('<');
if (!string.IsNullOrEmpty(element.Prefix))
stringBuilder.Append(element.Prefix).Append(':');
stringBuilder.Append(element.LocalName);
foreach (IAttr attribute in element.Attributes) {
stringBuilder.Append(" ").Append(Instance.Attribute(attribute));
}
stringBuilder.Append('>');
return stringBuilder.ToPool();
}
string IMarkupFormatter.CloseTag(IElement element, bool selfClosing)
{
string prefix = element.Prefix;
string localName = element.LocalName;
string str = (!string.IsNullOrEmpty(prefix)) ? (prefix + ":" + localName) : localName;
if (!selfClosing)
return "</" + str + ">";
return string.Empty;
}
string IMarkupFormatter.Attribute(IAttr attr)
{
string namespaceUri = attr.NamespaceUri;
string localName = attr.LocalName;
string value = attr.Value;
StringBuilder stringBuilder = Pool.NewStringBuilder();
if (string.IsNullOrEmpty(namespaceUri))
stringBuilder.Append(localName);
else if (namespaceUri.Is(NamespaceNames.XmlUri)) {
stringBuilder.Append(NamespaceNames.XmlPrefix).Append(':').Append(localName);
} else if (namespaceUri.Is(NamespaceNames.XLinkUri)) {
stringBuilder.Append(NamespaceNames.XLinkPrefix).Append(':').Append(localName);
} else if (namespaceUri.Is(NamespaceNames.XmlNsUri)) {
stringBuilder.Append(XmlNamespaceLocalName(localName));
} else {
stringBuilder.Append(attr.Name);
}
stringBuilder.Append('=').Append('"');
for (int i = 0; i < value.Length; i++) {
switch (value[i]) {
case '&':
stringBuilder.Append("&");
break;
case ' ':
stringBuilder.Append(" ");
break;
case '"':
stringBuilder.Append(""");
break;
default:
stringBuilder.Append(value[i]);
break;
}
}
return stringBuilder.Append('"').ToPool();
}
private static string GetIds(string publicId, string systemId)
{
if (string.IsNullOrEmpty(publicId) && string.IsNullOrEmpty(systemId))
return string.Empty;
if (string.IsNullOrEmpty(systemId))
return $"""{new object[1] {
publicId
}}""";
if (string.IsNullOrEmpty(publicId))
return $"""{new object[1] {
systemId
}}""";
return string.Format(" PUBLIC \"{0}\" \"{1}\"", new object[2] {
publicId,
systemId
});
}
private static string XmlNamespaceLocalName(string name)
{
if (!(name != NamespaceNames.XmlNsPrefix))
return name;
return NamespaceNames.XmlNsPrefix + ":";
}
}
}