У меня есть фрагменты HTML, хранящиеся в таблице. Не целые страницы, без тегов и т.п., а только базовое форматирование.
Я хотел бы иметь возможность отображать этот Html только как текст, без форматирования, на данной странице (на самом деле только первые 30-50 символов, но это простой бит).
Как мне поместить «текст» в этот HTML-код в строку как обычный текст?
Итак, этот фрагмент кода.
<b>Hello World.</b><br/><p><i>Is there anyone out there?</i><p>
Становится:
Привет мир. Есть там кто-нибудь?
Есть довольно простой и понятный код для преобразования HTML в обычный текст в blackbeltcoder.com/Articles/strings/convert-html-to-text.
Это был правильный ответ на то, что мне было нужно - спасибо!
Вы можете использовать SgmlReader. code.msdn.microsoft.com/SgmlReader
Как вопрос может быть отмечен как дубликат вопроса, заданного 6 месяцев спустя? Кажется немного отсталым ...
Я написал функция, которая преобразует HTML в обычный текст. У него есть некоторые ограничения, например, не извлекает ссылки из тегов a. Мне лучше основывать свою функцию на исходный код PHP html2text.





общедоступная статическая строка StripTags2 (строка html) { return html.Replace ("<", "<"). Replace (">", ">"); }
Этим вы избегаете всех «<» и «>» в строке. Это то, что вы хотите?
... ах. Что ж, теперь ответ (вместе с толкованием двусмысленного вопроса) полностью изменился, я выберу гниды из-за отсутствия & amp; кодирование вместо этого. ;-)
Я не думаю, что изобретать велосипед - хорошая идея, особенно когда у вас квадратное колесо. Вместо этого вы должны использовать HTMLEncode.
Если у вас есть данные, содержащие теги HTML, и вы хотите отобразить их, чтобы человек мог ВИДЕТЬ теги, используйте HttpServerUtility :: HtmlEncode.
Если у вас есть данные, содержащие HTML-теги, и вы хотите, чтобы пользователь видел визуализированные теги, отобразите текст как есть. Если текст представляет собой всю веб-страницу, используйте для него IFRAME.
Если у вас есть данные, содержащие теги HTML, и вы хотите удалить теги и просто отобразить неформатированный текст, используйте регулярное выражение.
в php есть функция с названием striptags () возможно у вас есть что-то похожее
"использовать регулярное выражение" НЕТ! Это было бы занесением в черный список. Вы можете быть в безопасности только при занесении в белый список. Например, помните ли вы, что атрибут стиля может содержать "background: url ('javascript: ...');"? конечно нет, я бы тоже не стал. Вот почему черный список не работает.
Если вы говорите об удалении тегов, это относительно просто, если вам не нужно беспокоиться о таких вещах, как теги <script>. Если все, что вам нужно сделать, это отобразить текст без тегов, вы можете сделать это с помощью регулярного выражения:
<[^>]*>
Если вам действительно нужно беспокоиться о тегах <script> и т.п., тогда вам понадобится что-то более мощное, чем регулярные выражения, потому что вам нужно отслеживать состояние, что-то большее, чем контекстно-свободная грамматика (CFG). Хотя вы могли бы сделать это с помощью «слева направо» или не жадного сопоставления.
Если вы умеете использовать регулярные выражения, существует множество веб-страниц с хорошей информацией:
Если вам нужно более сложное поведение CFG, я бы посоветовал использовать сторонний инструмент, к сожалению, я не знаю хорошего, что можно порекомендовать.
Вы также должны беспокоиться о> в значениях атрибутов, комментариях, PI / CDATA в XML и различных распространенных искажениях в устаревшем HTML. В общем, [X] [HT] ML не поддается синтаксическому анализу с помощью регулярных выражений.
Вы можете разместить> в значениях атрибутов, но сделав атрибуты частью регулярного выражения. Только сложность вложенных тегов ограничивает полезность синтаксического анализа с помощью регулярных выражений.
Разве вы не имеете в виду <[^>] *>, который соответствует таким вещам, как <html>, а не <[^>]> *, который соответствует таким вещам, как <h> >>>?
Это ужасный метод. Правильный способ - проанализировать HTML с помощью библиотеки и пройти по dom, выводя только содержимое из белого списка.
@usr: Вы имеете в виду часть ответа CFG. Regex можно использовать для быстрого и грязного удаления тегов, у него есть свои недостатки, но это быстро и легко. Для более сложного анализа используйте инструмент на основе CFG (на вашем языке библиотека, которая генерирует DOM). Я не проводил тесты, но держу пари, что синтаксический анализ DOM медленнее, чем удаление регулярных выражений, если необходимо учитывать производительность.
@vfilby: НЕТ! Удаление тегов занесено в черный список. Просто в качестве примера того, что вы забыли: ваше регулярное выражение не будет удалять теги, в которых отсутствует закрывающий '>'. Вы думали об этом? Я не уверен, может ли это быть проблемой, но это, по крайней мере, доказывает, что вы пропустили этот случай. Кто знает, что еще вы пропустили. Вот еще один: вы пропускаете изображения с атрибутом src javascript. НИКОГДА не заносите в черный список, за исключением случаев, когда безопасность не важна.
@usr: Вы имеете в виду часть ответа CFG. Regex можно использовать для быстрого и грязного удаления тегов, у него есть свои недостатки, но это быстро и легко. Для более сложного анализа используйте инструмент на основе CFG (на вашем языке библиотека, которая генерирует DOM).
@vfilby, первая атака, которая приходит на ум, - это написание "<div id = \" "(строковый синтаксис C#). Обратите внимание на отсутствующие конечные кавычки и отсутствующую закрывающую скобку. Я предполагаю, что это запутает браузер и разбалансирует структуру тегов. Вы думаете об этой атаке? Можете ли вы быть уверены, что она никогда не сработает?
@usr Неправильный ввод может так же легко запутать библиотеку синтаксического анализа (то, что я называю CFG), поэтому я не уверен, что это лучшее доказательство против удаления тегов. Вложенные теги не поддерживаются разделением тегов регулярных выражений, как указано в моем ответе (т.е. теги <script>). Итак, я повторяю свою первоначальную мысль: если задача проста, вы можете удалить теги (не занесение в черный или белый список, потому что вы удаляете их все). Если вам нужен более сложный синтаксический анализ (устойчивый к ошибкам, поэтапный и т. д.), Используйте CFG (синтаксическую библиотеку).
@vfilby, неважно, запуталась ли библиотека синтаксического анализа. Все, что вам нужно сделать, это взять из него DOM (любой DOM) и вывести только компоненты из белого списка. Это всегда безопасно, не имеет значения, как выглядит проанализированная DOM. Кроме того, я рассказал вам несколько примеров, когда ваш «простой» метод не удаляет теги.
Как писал @bobince, HTML не поддается синтаксическому анализу с помощью регулярных выражений. Это приведет к взрыву в реальном HTML, который часто искажен.
не правильным образом, он только конвертирует теги, html-текст может содержать разрывы строк, табуляции и другое форматирование, которое это регулярное выражение не удаляет.
Зависит от того, что вы подразумеваете под «HTML». Самый сложный случай - это целые веб-страницы. С этим также проще всего справиться, поскольку вы можете использовать веб-браузер в текстовом режиме. См. Список веб-браузеров Статья в Википедии, включая браузеры с текстовым режимом. Lynx, вероятно, самый известный, но один из других может быть лучше для ваших нужд.
как он сказал: «У меня есть фрагменты HTML, хранящиеся в таблице».
HTTPUtility.HTMLEncode() предназначен для обработки кодирования HTML-тегов как строк. Он берет на себя всю тяжелую работу за вас. Из Документация MSDN:
If characters such as blanks and punctuation are passed in an HTTP stream, they might be misinterpreted at the receiving end. HTML encoding converts characters that are not allowed in HTML into character-entity equivalents; HTML decoding reverses the encoding. For example, when embedded in a block of text, the characters
<and>, are encoded as<and>for HTTP transmission.
Метод HTTPUtility.HTMLEncode(), подробный здесь:
public static void HtmlEncode(
string s,
TextWriter output
)
Использование:
String TestString = "This is a <Test String>.";
StringWriter writer = new StringWriter();
Server.HtmlEncode(TestString, writer);
String EncodedString = writer.ToString();
Действительно хороший ответ, Джордж, спасибо, он также подчеркнул, насколько плохо я задал вопрос в первый раз. Извиняюсь.
пакет гибкости html устарел и не поддерживает html5
Лицензированный MIT HtmlAgilityPack имеет в одном из своих образцов метод, который преобразует HTML в обычный текст.
var plainText = HtmlUtilities.ConvertToPlainText(string html);
Подайте ему строку HTML, например
<b>hello, <i>world!</i></b>
И вы получите результат в виде простого текста, например:
hello world!
Раньше я использовал HtmlAgilityPack, но я не вижу ссылки на ConvertToPlainText. Вы можете сказать мне, где я могу его найти?
Горацио, он включен в один из примеров, поставляемых с HtmlAgilityPack: htmlagilitypack.codeplex.com/sourcecontrol/changeset/view/…
Перед использованием этого метода я советую проверить, действительно ли он занесен в белый список изнутри. В противном случае это опасно.
На самом деле, в Agility Pack для этого нет встроенного метода. Вы связались с примером, в котором Agility Pack используется для обхода дерева узлов, удаления тегов script и style и записи внутреннего текста других элементов в строку вывода. Я сомневаюсь, что он прошел много испытаний с реальными данными.
Да, это есть в образцах. Он использует базовую функциональность пакета гибкости HTML для анализа документа и вывода текста узлов, пропуская стили, сценарии и комментарии. Посмотрите код сами: htmlagilitypack.codeplex.com/sourcecontrol/changeset/view/…
Вы заметите, что код помещает в черный список скриптовые блоки, комментарии и стили.
Может ли кто-нибудь предоставить код, который работает, а не ссылки на образцы, которые необходимо модифицировать для правильной работы?
Вы смотрели ссылку, которую я разместил в комментариях? htmlagilitypack.codeplex.com/sourcecontrol/changeset/view/…
Связанный образец отлично работает. Для тех, кто пытается его использовать, просто скопируйте весь класс в свой собственный проект и используйте метод ConvertHTML. Вам также потребуется загрузить в свой проект ссылку на dll HtmlAgilityPack.
Все в порядке, но когда я пытаюсь преобразовать этот текст, я получаю предупреждение xss: <p> & lt; script & gt; alert ("Ups") & lt; / script & gt; </p>, потому что метод HtmlEntity.DeEntitize () convert & lt: script в <script>
Предоставленная ссылка плохо разбирает пробелы. альтернативный ответ на вопрос SO в stackoverflow.com/questions/731649/…
Теперь образец можно найти здесь: github.com/ceee/ReadSharp/blob/master/ReadSharp/…
Чтобы добавить к ответу vfilby, вы можете просто выполнить замену RegEx в своем коде; новые классы не нужны. На случай, если другие новички, как я, наткнутся на этот вопрос.
using System.Text.RegularExpressions;
Затем...
private string StripHtml(string source)
{
string output;
//get rid of HTML tags
output = Regex.Replace(source, "<[^>]*>", string.Empty);
//get rid of multiple blank lines
output = Regex.Replace(output, @"^\s*$\n", string.Empty, RegexOptions.Multiline);
return output;
}
НЕХОРОШО! Его можно обмануть, чтобы он содержал скрипт, опуская закрывающую угловую скобку. РЕБЯТА, никогда не заносите в черный список. Вы не могу дезинфицируете ввод путем внесения в черный список. Это так неправильно.
Я думаю, что самый простой способ - создать метод расширения строки (на основе того, что предложил пользователь Ричард):
using System;
using System.Text.RegularExpressions;
public static class StringHelpers
{
public static string StripHTML(this string HTMLText)
{
var reg = new Regex("<[^>]+>", RegexOptions.IgnoreCase);
return reg.Replace(HTMLText, "");
}
}
Затем просто используйте этот метод расширения для любой строковой переменной в вашей программе:
var yourHtmlString = "<div class=\"someclass\"><h2>yourHtmlText</h2></span>";
var yourTextString = yourHtmlString.StripHTML();
Я использую этот метод расширения для преобразования комментариев в формате html в обычный текст, чтобы он правильно отображался в кристаллическом отчете, и он отлично работает!
В HtmlAgilityPack нет метода с именем ConvertToPlainText, но вы можете преобразовать строку html в строку CLEAR с помощью:
HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(htmlString);
var textString = doc.DocumentNode.InnerText;
Regex.Replace(textString , @"<(.|n)*?>", string.Empty).Replace(" ", "");
Это работает для меня. НО Я НЕ НАШЕЛ МЕТОД С ИМЯ «ConvertToPlainText» В «HtmlAgilityPack».
хорошо, это не очень хорошо - поскольку вы используете дополнительную библиотеку только для поиска корневого узла документа, а затем применяете регулярное выражение ко всему корневому узлу? Либо вы используете HtmlAgilityPack для разбора html узла за узлом, либо используете регулярное выражение для обработки всего текста в целом.
Я не мог использовать HtmlAgilityPack, поэтому написал для себя второе лучшее решение
private static string HtmlToPlainText(string html)
{
const string tagWhiteSpace = @"(>|$)(\W|\n|\r)+<";//matches one or more (white space or line breaks) between '>' and '<'
const string stripFormatting = @"<[^>]*(>|$)";//match any character between '<' and '>', even when end tag is missing
const string lineBreak = @"<(br|BR)\s{0,1}/{0,1}>";//matches: <br>,<br/>,<br />,<BR>,<BR/>,<BR />
var lineBreakRegex = new Regex(lineBreak, RegexOptions.Multiline);
var stripFormattingRegex = new Regex(stripFormatting, RegexOptions.Multiline);
var tagWhiteSpaceRegex = new Regex(tagWhiteSpace, RegexOptions.Multiline);
var text = html;
//Decode html specific characters
text = System.Net.WebUtility.HtmlDecode(text);
//Remove tag whitespace/line breaks
text = tagWhiteSpaceRegex.Replace(text, "><");
//Replace <br /> with line breaks
text = lineBreakRegex.Replace(text, Environment.NewLine);
//Strip formatting
text = stripFormattingRegex.Replace(text, string.Empty);
return text;
}
& lt; blabla & gt; был проанализирован, поэтому я переместил text = System.Net.WebUtility.HtmlDecode (text); в конец метода
Это было здорово, я также добавил конденсатор с несколькими пространствами, так как html мог быть сгенерирован из CMS: var spaceRegex = new Regex ("[] {2,}", RegexOptions.None);
Иногда в html-коде есть новая строка кодера (новую строку нельзя увидеть в комментарии, поэтому я показываю ее с помощью [новой строки], например: <br> Я [новая строка] пропускаю [новую строку] you <br >, Значит, он должен показать: «Я скучаю по тебе», но он показывает, что я [новая строка] скучаю [новая строка] по тебе. Это заставляет простой текст выглядеть болезненно. Вы знаете, как исправить?
@ 123iamking можно использовать перед текстом возврата; : text.Replace ("[новая строка]", "\ n");
Я использовал это и понял, что иногда он оставляет '>' в начале строк. Другое решение применения регулярного выражения <[^>] *> отлично работает.
Regex находится в System.Text.RegularExpressions
Самый простой способ нашел:
HtmlFilter.ConvertToPlainText(html);
Класс HtmlFilter находится в Microsoft.TeamFoundation.WorkItemTracking.Controls.dll
DLL можно найти в такой папке: % ProgramFiles% \ Common Files \ microsoft shared \ Team Foundation Server \ 14.0 \
В VS 2015 dll также требует ссылки на Microsoft.TeamFoundation.WorkItemTracking.Common.dll, расположенный в той же папке.
заботится ли он о тегах скрипта, выделяется ли он полужирным курсивом и т. д.?
Представление зависимости от основы команды для преобразования html в простой текст, очень сомнительно ...
Трехэтапный процесс преобразования HTML в простой текст
Сначала вам нужно установить пакет Nuget для HtmlAgilityPack Второй Create This class
public class HtmlToText
{
public HtmlToText()
{
}
public string Convert(string path)
{
HtmlDocument doc = new HtmlDocument();
doc.Load(path);
StringWriter sw = new StringWriter();
ConvertTo(doc.DocumentNode, sw);
sw.Flush();
return sw.ToString();
}
public string ConvertHtml(string html)
{
HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(html);
StringWriter sw = new StringWriter();
ConvertTo(doc.DocumentNode, sw);
sw.Flush();
return sw.ToString();
}
private void ConvertContentTo(HtmlNode node, TextWriter outText)
{
foreach(HtmlNode subnode in node.ChildNodes)
{
ConvertTo(subnode, outText);
}
}
public void ConvertTo(HtmlNode node, TextWriter outText)
{
string html;
switch(node.NodeType)
{
case HtmlNodeType.Comment:
// don't output comments
break;
case HtmlNodeType.Document:
ConvertContentTo(node, outText);
break;
case HtmlNodeType.Text:
// script and style must not be output
string parentName = node.ParentNode.Name;
if ((parentName == "script") || (parentName == "style"))
break;
// get text
html = ((HtmlTextNode)node).Text;
// is it in fact a special closing node output as text?
if (HtmlNode.IsOverlappedClosingElement(html))
break;
// check the text is meaningful and not a bunch of whitespaces
if (html.Trim().Length > 0)
{
outText.Write(HtmlEntity.DeEntitize(html));
}
break;
case HtmlNodeType.Element:
switch(node.Name)
{
case "p":
// treat paragraphs as crlf
outText.Write("\r\n");
break;
}
if (node.HasChildNodes)
{
ConvertContentTo(node, outText);
}
break;
}
}
}
Используя приведенный выше класс со ссылкой на ответ Иуды Химанго
В-третьих, вам нужно создать объект класса выше и использовать метод ConvertHtml(HTMLContent) для преобразования HTML в обычный текст, а не ConvertToPlainText(string html);.
HtmlToText htt=new HtmlToText();
var plainText = htt.ConvertHtml(HTMLContent);
Могу ли я пропустить преобразование ссылок в HTML. мне нужно сохранить ссылки в HTML при преобразовании в текст?
Вот мое решение:
public string StripHTML(string html)
{
if (string.IsNullOrWhiteSpace(html)) return "";
// could be stored in static variable
var regex = new Regex("<[^>]+>|\\s{2}", RegexOptions.IgnoreCase);
return System.Web.HttpUtility.HtmlDecode(regex.Replace(html, ""));
}
Пример:
StripHTML("<p class='test' style='color:red;'>Here is my solution:</p>");
// output -> Here is my solution:
У меня был тот же вопрос, только у моего html был простой заранее известный макет, например:
<DIV><P>abc</P><P>def</P></DIV>
В итоге я использовал такой простой код:
string.Join (Environment.NewLine, XDocument.Parse (html).Root.Elements ().Select (el => el.Value))
Какие выходы:
abc
def
Не писал, а использовал:
using HtmlAgilityPack;
using System;
using System.IO;
using System.Text.RegularExpressions;
namespace foo {
//small but important modification to class https://github.com/zzzprojects/html-agility-pack/blob/master/src/Samples/Html2Txt/HtmlConvert.cs
public static class HtmlToText {
public static string Convert(string path) {
HtmlDocument doc = new HtmlDocument();
doc.Load(path);
return ConvertDoc(doc);
}
public static string ConvertHtml(string html) {
HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(html);
return ConvertDoc(doc);
}
public static string ConvertDoc(HtmlDocument doc) {
using (StringWriter sw = new StringWriter()) {
ConvertTo(doc.DocumentNode, sw);
sw.Flush();
return sw.ToString();
}
}
internal static void ConvertContentTo(HtmlNode node, TextWriter outText, PreceedingDomTextInfo textInfo) {
foreach (HtmlNode subnode in node.ChildNodes) {
ConvertTo(subnode, outText, textInfo);
}
}
public static void ConvertTo(HtmlNode node, TextWriter outText) {
ConvertTo(node, outText, new PreceedingDomTextInfo(false));
}
internal static void ConvertTo(HtmlNode node, TextWriter outText, PreceedingDomTextInfo textInfo) {
string html;
switch (node.NodeType) {
case HtmlNodeType.Comment:
// don't output comments
break;
case HtmlNodeType.Document:
ConvertContentTo(node, outText, textInfo);
break;
case HtmlNodeType.Text:
// script and style must not be output
string parentName = node.ParentNode.Name;
if ((parentName == "script") || (parentName == "style")) {
break;
}
// get text
html = ((HtmlTextNode)node).Text;
// is it in fact a special closing node output as text?
if (HtmlNode.IsOverlappedClosingElement(html)) {
break;
}
// check the text is meaningful and not a bunch of whitespaces
if (html.Length == 0) {
break;
}
if (!textInfo.WritePrecedingWhiteSpace || textInfo.LastCharWasSpace) {
html = html.TrimStart();
if (html.Length == 0) { break; }
textInfo.IsFirstTextOfDocWritten.Value = textInfo.WritePrecedingWhiteSpace = true;
}
outText.Write(HtmlEntity.DeEntitize(Regex.Replace(html.TrimEnd(), @"\s{2,}", " ")));
if (textInfo.LastCharWasSpace = char.IsWhiteSpace(html[html.Length - 1])) {
outText.Write(' ');
}
break;
case HtmlNodeType.Element:
string endElementString = null;
bool isInline;
bool skip = false;
int listIndex = 0;
switch (node.Name) {
case "nav":
skip = true;
isInline = false;
break;
case "body":
case "section":
case "article":
case "aside":
case "h1":
case "h2":
case "header":
case "footer":
case "address":
case "main":
case "div":
case "p": // stylistic - adjust as you tend to use
if (textInfo.IsFirstTextOfDocWritten) {
outText.Write("\r\n");
}
endElementString = "\r\n";
isInline = false;
break;
case "br":
outText.Write("\r\n");
skip = true;
textInfo.WritePrecedingWhiteSpace = false;
isInline = true;
break;
case "a":
if (node.Attributes.Contains("href")) {
string href = node.Attributes["href"].Value.Trim();
if (node.InnerText.IndexOf(href, StringComparison.InvariantCultureIgnoreCase) == -1) {
endElementString = "<" + href + ">";
}
}
isInline = true;
break;
case "li":
if (textInfo.ListIndex > 0) {
outText.Write("\r\n{0}.\t", textInfo.ListIndex++);
} else {
outText.Write("\r\n*\t"); //using '*' as bullet char, with tab after, but whatever you want eg "\t->", if utf-8 0x2022
}
isInline = false;
break;
case "ol":
listIndex = 1;
goto case "ul";
case "ul": //not handling nested lists any differently at this stage - that is getting close to rendering problems
endElementString = "\r\n";
isInline = false;
break;
case "img": //inline-block in reality
if (node.Attributes.Contains("alt")) {
outText.Write('[' + node.Attributes["alt"].Value);
endElementString = "]";
}
if (node.Attributes.Contains("src")) {
outText.Write('<' + node.Attributes["src"].Value + '>');
}
isInline = true;
break;
default:
isInline = true;
break;
}
if (!skip && node.HasChildNodes) {
ConvertContentTo(node, outText, isInline ? textInfo : new PreceedingDomTextInfo(textInfo.IsFirstTextOfDocWritten) { ListIndex = listIndex });
}
if (endElementString != null) {
outText.Write(endElementString);
}
break;
}
}
}
internal class PreceedingDomTextInfo {
public PreceedingDomTextInfo(BoolWrapper isFirstTextOfDocWritten) {
IsFirstTextOfDocWritten = isFirstTextOfDocWritten;
}
public bool WritePrecedingWhiteSpace { get; set; }
public bool LastCharWasSpace { get; set; }
public readonly BoolWrapper IsFirstTextOfDocWritten;
public int ListIndex { get; set; }
}
internal class BoolWrapper {
public BoolWrapper() { }
public bool Value { get; set; }
public static implicit operator bool(BoolWrapper boolWrapper) {
return boolWrapper.Value;
}
public static implicit operator BoolWrapper(bool boolWrapper) {
return new BoolWrapper { Value = boolWrapper };
}
}
}
У него есть ограничение, заключающееся в том, что он не сжимает длинные строчные пробелы, но он определенно переносим и уважает макет, как веб-браузер.
static string HtmlToPlainText(string html) {
string buf;
string block = "address|article|aside|blockquote|canvas|dd|div|dl|dt|" +
"fieldset|figcaption|figure|footer|form|h\\d|header|hr|li|main|nav|" +
"noscript|ol|output|p|pre|section|table|tfoot|ul|video";
string patNestedBlock = $"(\\s*?</?({block})[^>]*?>)+\\s*";
buf = Regex.Replace(html, patNestedBlock, "\n", RegexOptions.IgnoreCase);
// Replace br tag to newline.
buf = Regex.Replace(buf, @"<(br)[^>]*>", "\n", RegexOptions.IgnoreCase);
// (Optional) remove styles and scripts.
buf = Regex.Replace(buf, @"<(script|style)[^>]*?>.*?</\1>", "", RegexOptions.Singleline);
// Remove all tags.
buf = Regex.Replace(buf, @"<[^>]*(>|$)", "", RegexOptions.Multiline);
// Replace HTML entities.
buf = WebUtility.HtmlDecode(buf);
return buf;
}
@ Профессор Фалькен, признаю. Я думаю, что у каждого кода есть свои плюсы и минусы. Его минусы - солидность, а плюсы - простота (в отношении sloc). Вы можете опубликовать код, используя XDocument.
Я столкнулся с подобной проблемой и нашел лучшее решение. Код ниже работает идеально для меня.
private string ConvertHtml_Totext(string source)
{
try
{
string result;
// Remove HTML Development formatting
// Replace line breaks with space
// because browsers inserts space
result = source.Replace("\r", " ");
// Replace line breaks with space
// because browsers inserts space
result = result.Replace("\n", " ");
// Remove step-formatting
result = result.Replace("\t", string.Empty);
// Remove repeating spaces because browsers ignore them
result = System.Text.RegularExpressions.Regex.Replace(result,
@"( )+", " ");
// Remove the header (prepare first by clearing attributes)
result = System.Text.RegularExpressions.Regex.Replace(result,
@"<( )*head([^>])*>","<head>",
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
result = System.Text.RegularExpressions.Regex.Replace(result,
@"(<( )*(/)( )*head( )*>)","</head>",
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
result = System.Text.RegularExpressions.Regex.Replace(result,
"(<head>).*(</head>)",string.Empty,
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
// remove all scripts (prepare first by clearing attributes)
result = System.Text.RegularExpressions.Regex.Replace(result,
@"<( )*script([^>])*>","<script>",
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
result = System.Text.RegularExpressions.Regex.Replace(result,
@"(<( )*(/)( )*script( )*>)","</script>",
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
//result = System.Text.RegularExpressions.Regex.Replace(result,
// @"(<script>)([^(<script>\.</script>)])*(</script>)",
// string.Empty,
// System.Text.RegularExpressions.RegexOptions.IgnoreCase);
result = System.Text.RegularExpressions.Regex.Replace(result,
@"(<script>).*(</script>)",string.Empty,
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
// remove all styles (prepare first by clearing attributes)
result = System.Text.RegularExpressions.Regex.Replace(result,
@"<( )*style([^>])*>","<style>",
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
result = System.Text.RegularExpressions.Regex.Replace(result,
@"(<( )*(/)( )*style( )*>)","</style>",
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
result = System.Text.RegularExpressions.Regex.Replace(result,
"(<style>).*(</style>)",string.Empty,
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
// insert tabs in spaces of <td> tags
result = System.Text.RegularExpressions.Regex.Replace(result,
@"<( )*td([^>])*>","\t",
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
// insert line breaks in places of <BR> and <LI> tags
result = System.Text.RegularExpressions.Regex.Replace(result,
@"<( )*br( )*>","\r",
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
result = System.Text.RegularExpressions.Regex.Replace(result,
@"<( )*li( )*>","\r",
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
// insert line paragraphs (double line breaks) in place
// if <P>, <DIV> and <TR> tags
result = System.Text.RegularExpressions.Regex.Replace(result,
@"<( )*div([^>])*>","\r\r",
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
result = System.Text.RegularExpressions.Regex.Replace(result,
@"<( )*tr([^>])*>","\r\r",
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
result = System.Text.RegularExpressions.Regex.Replace(result,
@"<( )*p([^>])*>","\r\r",
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
// Remove remaining tags like <a>, links, images,
// comments etc - anything that's enclosed inside < >
result = System.Text.RegularExpressions.Regex.Replace(result,
@"<[^>]*>",string.Empty,
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
// replace special characters:
result = System.Text.RegularExpressions.Regex.Replace(result,
@" "," ",
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
result = System.Text.RegularExpressions.Regex.Replace(result,
@"•"," * ",
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
result = System.Text.RegularExpressions.Regex.Replace(result,
@"‹","<",
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
result = System.Text.RegularExpressions.Regex.Replace(result,
@"›",">",
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
result = System.Text.RegularExpressions.Regex.Replace(result,
@"™","(tm)",
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
result = System.Text.RegularExpressions.Regex.Replace(result,
@"⁄","/",
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
result = System.Text.RegularExpressions.Regex.Replace(result,
@"<","<",
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
result = System.Text.RegularExpressions.Regex.Replace(result,
@">",">",
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
result = System.Text.RegularExpressions.Regex.Replace(result,
@"©","(c)",
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
result = System.Text.RegularExpressions.Regex.Replace(result,
@"®","(r)",
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
// Remove all others. More can be added, see
// http://hotwired.lycos.com/webmonkey/reference/special_characters/
result = System.Text.RegularExpressions.Regex.Replace(result,
@"&(.{2,6});", string.Empty,
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
// for testing
//System.Text.RegularExpressions.Regex.Replace(result,
// this.txtRegex.Text,string.Empty,
// System.Text.RegularExpressions.RegexOptions.IgnoreCase);
// make line breaking consistent
result = result.Replace("\n", "\r");
// Remove extra line breaks and tabs:
// replace over 2 breaks with 2 and over 4 tabs with 4.
// Prepare first to remove any whitespaces in between
// the escaped characters and remove redundant tabs in between line breaks
result = System.Text.RegularExpressions.Regex.Replace(result,
"(\r)( )+(\r)","\r\r",
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
result = System.Text.RegularExpressions.Regex.Replace(result,
"(\t)( )+(\t)","\t\t",
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
result = System.Text.RegularExpressions.Regex.Replace(result,
"(\t)( )+(\r)","\t\r",
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
result = System.Text.RegularExpressions.Regex.Replace(result,
"(\r)( )+(\t)","\r\t",
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
// Remove redundant tabs
result = System.Text.RegularExpressions.Regex.Replace(result,
"(\r)(\t)+(\r)","\r\r",
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
// Remove multiple tabs following a line break with just one tab
result = System.Text.RegularExpressions.Regex.Replace(result,
"(\r)(\t)+","\r\t",
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
// Initial replacement target string for line breaks
string breaks = "\r\r\r";
// Initial replacement target string for tabs
string tabs = "\t\t\t\t\t";
for (int index=0; index<result.Length; index++)
{
result = result.Replace(breaks, "\r\r");
result = result.Replace(tabs, "\t\t\t\t");
breaks = breaks + "\r";
tabs = tabs + "\t";
}
// That's it.
return result;
}
catch
{
MessageBox.Show("Error");
return source;
}
}
Сначала нужно было удалить escape-символы, такие как \ n и \ r, потому что они приводят к тому, что регулярные выражения перестают работать должным образом.
Более того, чтобы строка результата правильно отображалась в текстовом поле, может потребоваться разделить ее и установить свойство Lines текстового поля вместо присвоения свойству Text.
this.txtResult.Lines = StripHTML (this.txtSource.Text) .Split ("\ r" .ToCharArray ());
Источник: https://www.codeproject.com/Articles/11902/Convert-HTML-to-Plain-Text-2
Думаю, у него есть простой ответ:
public string RemoveHTMLTags(string HTMLCode)
{
string str=System.Text.RegularExpressions.Regex.Replace(HTMLCode, "<[^>]*>", "");
return str;
}
Для тех, кто ищет точное решение вопроса OP для текстового сокращения данного html-документа без символов новой строки и HTML-тегов, пожалуйста, найдите решение ниже.
Как и в случае любого предлагаемого решения, в приведенном ниже коде есть некоторые предположения:
he<span>ll</span>o должен выводить hello. Список встроенных
теги: https://www.w3schools.com/htmL/html_blocks.aspУчитывая вышеизложенное, следующее расширение строки со скомпилированными регулярными выражениями будет выводить ожидаемый простой текст с учетом экранированных символов html и null при вводе null.
public static class StringExtensions
{
public static string ConvertToPlain(this string html)
{
if (html == null)
{
return html;
}
html = scriptRegex.Replace(html, string.Empty);
html = inlineTagRegex.Replace(html, string.Empty);
html = tagRegex.Replace(html, " ");
html = HttpUtility.HtmlDecode(html);
html = multiWhitespaceRegex.Replace(html, " ");
return html.Trim();
}
private static readonly Regex inlineTagRegex = new Regex("<\/?(a|span|sub|sup|b|i|strong|small|big|em|label|q)[^>]*>", RegexOptions.Compiled | RegexOptions.Singleline);
private static readonly Regex scriptRegex = new Regex("<(script|style)[^>]*?>.*?</\\1>", RegexOptions.Compiled | RegexOptions.Singleline);
private static readonly Regex tagRegex = new Regex("<[^>]+>", RegexOptions.Compiled | RegexOptions.Singleline);
private static readonly Regex multiWhitespaceRegex = new Regex("\\s+", RegexOptions.Compiled | RegexOptions.Singleline);
}
Вот несколько хороших предложений от W3C: w3.org/Tools/html2things.html