HTML etiketlerini kaldırmak için C # normal ifadelerini kullanma


139

Köşeli parantez dahil tüm HTML etiketlerini değiştirmek / kaldırmak için C # normal ifadesini nasıl kullanabilirim? Birisi bana kod konusunda yardımcı olabilir mi?



Bunu belirtmezsiniz, ancak komut dosyası ve stil öğelerini tamamen kaldırmak ve yalnızca etiketi kaldırmak istemediğinizden çıkarım. Aşağıdaki HTML Çeviklik Paketi yanıtı, etiketleri kaldırmak için doğrudur, ancak komut dosyasını ve stili kaldırmak için ayrıca stackoverflow.com/questions/13441470/…
John

1
Yinelenen olarak gösterilen soru çok fazla bilgiye sahiptir (ve Tony the Pony!), Ancak tüm etiketleri değil, yalnızca etiketleri açmasını istedi. Bu yüzden teknik olarak bir kopya olduğundan emin değilim. Bununla birlikte, cevap aynıdır: yapma.
goodeye

Yanıtlar:


154

Daha önce de belirtildiği gibi, XML veya HTML belgelerini işlemek için normal ifadeler kullanmamalısınız. İç içe geçmiş yapıları genel bir şekilde ifade etmenin bir yolu olmadığından, HTML ve XML belgeleriyle çok iyi performans göstermezler.

Aşağıdakileri kullanabilirsiniz.

String result = Regex.Replace(htmlDocument, @"<[^>]*>", String.Empty);

Bu çoğu durumda işe yarar, ancak bunun beklendiği gibi çalışmadığı durumlar (örneğin, CDATA içeren köşeli parantezler) olacaktır.


13
Bu naif bir uygulama .. Yani, <div id = "x <4>"> maalesef geçerli bir html. Yine de en aklı başında davaları ele ..
Ryan Emerle

8
Belirtildiği gibi, bu ifadenin bazı durumlarda başarısız olacağını biliyorum. Genel davanın hatasız herhangi bir düzenli ifade ile işlenip işlenemeyeceğinden bile emin değilim.
Daniel Brückner

1
Hayır, bu her durumda başarısız olacaktır! açgözlü.
Jake

13
@ Şifre, açgözlülüğün neden bir sorun olduğunu düşünüyorsun? Eşleşmenin geçerli bir HTML etiketinin başlangıcında başladığını varsayarsak, hiçbir zaman bu etiketin sonunu aşmayacaktır. [^>] Bunun içindir.
Alan Moore

1
@AlanMoore html bir "normal dil" değildir, yani geçerli html olan her şeyi normal ifadelerle düzgün şekilde eşleştiremezsiniz. bkz. stackoverflow.com/questions/590747/…
Kache

78

Doğru cevap bunu yapmayın, HTML Çeviklik Paketi'ni kullanın .

Eklemek için düzenlendi:

Jesse tarafından aşağıdaki yorumdan utanmadan çalmak ve tüm bunlardan sonra soruyu yetersiz cevaplamakla suçlanmaktan kaçınmak için, HTML Çeviklik Paketi'ni kullanarak en kusurlu şekilde oluşturulmuş, kaprisli HTML parçalarıyla bile çalışan basit, güvenilir bir snippet:

HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(Properties.Resources.HtmlContents);
var text = doc.DocumentNode.SelectNodes("//body//text()").Select(node => node.InnerText);
StringBuilder output = new StringBuilder();
foreach (string line in text)
{
   output.AppendLine(line);
}
string textOnly = HttpUtility.HtmlDecode(output.ToString());

HTML'yi ayrıştırmak için normal bir ifade kullanmak için çok az savunulabilir durum vardır, çünkü HTML geleneksel olmayan bir normal ifade motorunda bile sağlamak çok acı verici bir bağlam farkındalığı olmadan doğru şekilde ayrıştırılamaz. RegEx ile orada kısmen yol alabilirsiniz, ancak manuel doğrulama yapmanız gerekir.

Html Agility Pack, HTML'ye içeriksiz bir dilbilgisi olarak naif davranmanın yol açabileceği sapmaları manuel olarak düzeltme ihtiyacını azaltacak sağlam bir çözüm sağlayabilir.

Düzenli bir ifade size çoğunlukla istediğinizi sağlayabilir, ancak çok yaygın durumlarda başarısız olur. HTML Agility Pack'den daha iyi / daha hızlı bir ayrıştırıcı bulabilirseniz, bunun için gidin, ancak dünyayı daha bozuk HTML hackery'lerine maruz bırakmayın.


27
HTML Çeviklik Paketi, HTML ile çalışmakla ilgili her şeyin yanıtı değildir (örneğin, yalnızca HTML kodunun parçalarıyla çalışmak istiyorsanız ne olur ?!).
Propellerhead

7
HTML parçalarıyla oldukça iyi çalışır ve orijinal poster tarafından açıklanan senaryo için en iyi seçenektir. Bir Regex ise sadece idealize edilmiş bir HTML ile çalışır ve HTML'nin dilbilgisi düzenli olmadığından mükemmel geçerli bir HTML ile kırılır. Ruby kullanıyor olsaydı, hala nokogiri veya hpricot veya Python için güzel bir çorba önerirdim. HTML'yi dilbilgisi olmayan rastgele bir metin akışı değil, HTML gibi işlemek en iyisidir.
09:54, JasonTrue

1
HTML normal bir dilbilgisi değildir ve bu nedenle yalnızca normal ifadelerle ayrıştırılamaz. Düzenleme için normal ifadeleri kullanabilirsiniz, ancak ayrıştırma için kullanamazsınız. Gerçekten bu kadar basit. Dilbilimciler, HTML bile var olmadan bunu kabul ederdi.
43'te JasonTrue

20
Bu bir görüş meselesi değil. Düzenli bir ifade size çoğunlukla istediğinizi sağlayabilir, ancak çok yaygın durumlarda başarısız olur. HTML Çeviklik Paketi'nden daha iyi / daha hızlı bir ayrıştırıcı bulabilirseniz, bunun için gidin, ancak dünyayı daha bozuk HTML hackery'lerine maruz bırakmayın.
Mart'ta

2
HTML'yi ayrıştırmadan HTML etiketlerini doğru bir şekilde tanımlayamazsınız. HTML için tüm dilbilgisini anlıyor musunuz? Diğer cevapların önerdiği "oldukça yakına" ulaşmak için kötü hack'e bakın ve bana bunu neden sürdürmek istediğinizi söyleyin. Örnek girişiniz için hileli bir hızlı girişimin işe yaraması nedeniyle beni aşağı indiriyor, çözümünüzü doğru yapmayacak. Bazen HTML içeriğinden raporlar oluşturmak veya negatif eşleme kullanarak bazı CSS referanslarını düzeltmek için regexes kullandım & gt; hata olasılığını sınırlamak için ek doğrulamalar yaptık; genel bir amaç değildi.
11:13, JasonTrue

38

Soru kesin olarak cevaplanamayacak kadar geniştir. Web sayfası gibi gerçek dünyadaki bir HTML belgesindeki tüm etiketleri kaldırmaktan mı bahsediyorsunuz? Eğer öyleyse, yapmanız gerekenler:

  • <! DOCTYPE bildirimini veya varsa <? xml protokolünü kaldırın
  • tüm SGML yorumlarını kaldır
  • HEAD elemanının tamamını kaldır
  • tüm SCRIPT ve STYLE öğelerini kaldır
  • FORM ve TABLE elemanları ile Grabthar-knows-what
  • kalan etiketleri kaldır
  • <! [CDATA [ve]]> dizilerini CDATA bölümlerinden kaldırın, ancak içeriklerini yalnız bırakın

Bu sadece kafamın üstünden - eminim daha fazlası var. Tüm bunları yaptıktan sonra, bazı yerlerde bir araya getirilen kelimeler, cümleler ve paragraflar ve diğerlerinde büyük yararsız boşluk parçaları ile sonuçlanacaksınız.

Ancak, sadece bir parça ile çalıştığınızı ve tüm etiketleri kaldırmayla kurtulabileceğinizi varsayarsak, kullanacağım normal ifade:

@"(?></?\w+)(?>(?:[^>'""]+|'[^']*'|""[^""]*"")*)>"

Tek ve çift tırnaklı dizeleri kendi alternatifleriyle eşleştirmek, öznitelik değerlerindeki köşeli parantez sorunuyla başa çıkmak için yeterlidir. Ryan'ın cevabındaki normal ifade gibi, özellik adlarını ve etiket içindeki diğer şeyleri açıkça eşleştirmeye gerek görmüyorum; ilk alternatif bunların hepsini halleder.

Bu (?>...)yapıları merak ediyorsanız , atom gruplarıdır . Normal ifadeyi biraz daha verimli hale getirir, ancak daha da önemlisi, kontrolden çıkmayı engeller, bu da yaptığım gibi alternatif ve iç içe nicelik belirteçleri karıştırdığınızda her zaman dikkat etmeniz gereken bir şeydir. Bunun gerçekten bir sorun olacağını düşünmüyorum, ama bundan bahsetmezsem, başkası yapacağını biliyorum. ;-)

Bu normal ifade elbette mükemmel değil, ama muhtemelen ihtiyacınız olduğu kadar iyi.


1
Bu açık ara en iyi cevap. Posterin sorusunu yanıtlarsınız ve verilen görev için neden normal ifadenin kullanılmaması gerektiğini açıklarsınız. Aferin.
JWilliams

26
Regex regex = new Regex(@"</?\w+((\s+\w+(\s*=\s*(?:"".*?""|'.*?'|[^'"">\s]+))?)+\s*|\s*)/?>", RegexOptions.Singleline);

Kaynak


18

@JasonTrue doğrudur, HTML etiketlerini sıyırma normal ifadelerle yapılmamalıdır.

HtmlAgilityPack kullanarak HTML etiketlerini çıkarmak oldukça basittir:

public string StripTags(string input) {
    var doc = new HtmlDocument();
    doc.LoadHtml(input ?? "");
    return doc.DocumentNode.InnerText;
}

1
Biraz geç kalırken, bunun Word ve diğer ofis ürünleri tarafından üretilen gibi xml üzerinde de çalıştığını belirtmek isterim. Word xml ile başa çıkmaya ihtiyacı olan herkes, bunu kullanmaya bakmak için iyi olurdu, çünkü özellikle de tam olarak ihtiyacım olan şey olan içerikten etiketleri çıkarmanız gerekiyorsa, çok yardımcı olur.
Steve Pettifer

Her şey başarısız gibi göründüğünde, bu basit kod snippet'i günü kurtardı. Teşekkürler!
Ted Krapf

14

Jason'ın yanıtını yankılamak istiyorum, ancak bazen bazı Html'leri saf bir şekilde ayrıştırıp metin içeriğini çıkarmanız gerekiyor.

Bunu her zaman eğlenceli ve oyunlar olan zengin bir metin editörü tarafından oluşturulan bazı Html ile yapmam gerekiyordu.

Bu durumda, bazı etiketlerin içeriğini ve yalnızca etiketlerin kendisini kaldırmanız gerekebilir.

Benim durumumda ve etiketler bu karışıma atılmış. Bazıları (çok az) daha az naif uygulamamı faydalı bir başlangıç ​​noktası olarak görebilir.

   /// <summary>
    /// Removes all html tags from string and leaves only plain text
    /// Removes content of <xml></xml> and <style></style> tags as aim to get text content not markup /meta data.
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    public static string HtmlStrip(this string input)
    {
        input = Regex.Replace(input, "<style>(.|\n)*?</style>",string.Empty);
        input = Regex.Replace(input, @"<xml>(.|\n)*?</xml>", string.Empty); // remove all <xml></xml> tags and anything inbetween.  
        return Regex.Replace(input, @"<(.|\n)*?>", string.Empty); // remove any tags but not there content "<p>bob<span> johnson</span></p>" becomes "bob johnson"
    }

1
Belli çapraz platformlar arası linebreak sorunlarının yanı sıra, içerik sınırlandığında ungreedy niceleyiciye sahip olmak yavaştır. İlk ikisi ve sonuncusu için değiştirici <xml>.*(?!</xml>)</xml>ile benzer şeyler kullanın . Bunlardan ilki, ilk etiket adında yakalanan bir alternatif ve negatif ileri ve son etikette kendisine yapılan referanslarla birleştirilebilir. RegexOptions.SingleLine<[^>]*>
ChrisF

5

bu URL'de normal ifade yöntemini deneyin: http://www.dotnetperls.com/remove-html-tags

/// <summary>
/// Remove HTML from string with Regex.
/// </summary>
public static string StripTagsRegex(string source)
{
return Regex.Replace(source, "<.*?>", string.Empty);
}

/// <summary>
/// Compiled regular expression for performance.
/// </summary>
static Regex _htmlRegex = new Regex("<.*?>", RegexOptions.Compiled);

/// <summary>
/// Remove HTML from string with compiled Regex.
/// </summary>
public static string StripTagsRegexCompiled(string source)
{
return _htmlRegex.Replace(source, string.Empty);
}

3

bunu kullan..

@"(?></?\w+)(?>(?:[^>'""]+|'[^']*'|""[^""]*"")*)>"


-1

Etiketleri kaldırmak için bu yöntemi kullanın:

public string From_To(string text, string from, string to)
{
    if (text == null)
        return null;
    string pattern = @"" + from + ".*?" + to;
    Regex rx = new Regex(pattern, RegexOptions.Compiled | RegexOptions.IgnoreCase);
    MatchCollection matches = rx.Matches(text);
    return matches.Count <= 0 ? text : matches.Cast<Match>().Where(match => !string.IsNullOrEmpty(match.Value)).Aggregate(text, (current, match) => current.Replace(match.Value, ""));
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.