C# – Loại bỏ HTML tags trong chuỗi

Bài viết này nhằm giới thiệu với các bạn cách để loại bỏ HTML Tags trong chuỗi bằng C#. Đây là cách hay để hiển thị các chuỗi HTML dưới dạng chuỗi thuần và loại bỏ các định dạng như in đậm, in nghiêng…

Phương thức có thể giúp loại bỏ các HTML tags trong chuỗi để có thể lưu vào CSDL một cách dễ dàng, hơn nữa chúng ta sẽ dễ dàng tìm kiếm ở CSDL hơn. Ví dụ tìm chuỗi “ Hà nội  Aptech” sẽ dễ chịu hơn nếu không có các HTML Tags trong các chuỗi như “<i> Hà nội </i>  <b> Aptech</b>”. Đây là phương thức rất nhiều người quan tâm.

Chúng ta sẽ xây dựng một phương thức có thể loại bỏ các HTML Tags ra khỏi một chuỗi:

Nhập vào: “<p><i> Hà nội </i>  <b> Aptech </b></p>”

Kết quả: Hà nội  Aptech

Chúng ta có nhiều cách để thực hiện điều này nhưng chọn lọc ba cách để chia sẻ cùng các bạn:

Cách 1 – Sử dụng Regex

Chúng ta cài đặt phương thức sử dụng Regex như sau:

public static string RemoveHtmlTagsUsingRegex(this string htmlString)
        {
            var result = Regex.Replace(htmlString, "<.*?>", string.Empty);
            return result;
        }

Khi đó chúng ta sẽ có thể gọi một cách dễ dàng:

var result = testString.RemoveHtmlTagsUsingRegex();

Cách 2 – Sử dụng Compiled Regex ( câu lệnh Regex được biên dịch trước)

Khi các bạn đọc tới “biên dịch trước”, hẳn các bạn sẽ đoán ran ngay là phương thức mới này sẽ có tốc đột thực thi nhanh hơn so với phương thức trên. Tuy nhiên, để xác thực, chúng ta sẽ thử ở một unit test mà tôi sẽ xây dựng ở phía cuối bài viết.

 

static readonly Regex HtmlRegex = new Regex("<.*?>", RegexOptions.Compiled);

public static string RemoveHtmlTagsUsingCompiledRegex(this string htmlString)
        {
            var result = HtmlRegex.Replace(htmlString, string.Empty);
            return result;
        }

Cách 3 – Sử dụng mảng các ký tự (char array)

Cách này có vẻ thủ công hơn nhiều, và nó sẽ giúp gia tăng tốc độ thực thi, chúng ta cài đặt như sau:

public static string RemoveHtmlTagsUsingCharArray(this string htmlString)
        {
            var array = new char[htmlString.Length];
            var arrayIndex = 0;
            var inside = false;

            foreach (var @let in htmlString)
            {
                if (let == '<')
                {
                    inside = true;
                    continue;
                }
                if (let == '>')
                {
                    inside = false;
                    continue;
                }
                if (inside) continue;
                array[arrayIndex] = let;
                arrayIndex++;
            }
            return new string(array, 0, arrayIndex);
        }

Kiểm thử & so sánh tốc độ thực thi

Sau đây một dự án MS Unit Tests có tên là StringUtitlies.Tests để kiểm thử cho các phương thức nói trên, lớp kiểm thử có tên là RemoveHtmlTagsTests.

Đầu tiên chúng ta sẽ xây dựng một phương thức để thực hiện việc loại bỏ HTML Tags và đo thời gian thực hiện theo các cách khác nhau. Có lẽ các bạn đã biết, sẽ sử dụng đối tượng Stopwatch để đo lường thời gian. Và vì để bớt lặp lại mã lệnh,định nghĩa một enum có tên là RemoveMethods và sau đó dùng nó để xây dựng phương thức RemoveHtmlTags như sau:

private TimeSpan RemoveHtmlTags(RemoveMethods method, out string result)
        {
            result = string.Empty;
            var stopWatch = new Stopwatch();
            stopWatch.Start();
            switch (method)
            {
                case RemoveMethods.Regex:
                    result = htmlString.RemoveHtmlTagsUsingRegex();
                    break;
                case RemoveMethods.CompiledRegex:
                    result = htmlString.RemoveHtmlTagsUsingCompiledRegex();
                    break;
                case RemoveMethods.CharArray:
                    result = htmlString.RemoveHtmlTagsUsingCharArray();
                    break;
            }
            stopWatch.Stop();

            return stopWatch.Elapsed;
        }

        private enum RemoveMethods
        {
            Regex,
            CompiledRegex,
            CharArray
        }

Tiếp theo sẽ xây dựng một phương thức kiểm thử để đảm bảo ba phương thức cho ra kết quả như  mong muốn (dĩ nhiên đây chỉ là một trường hợp đơn giản, nếu muốn kiểm thử kỹ càng hơn, bạn nên tự xây dựng thêm các test method của mình).

private const string HtmlString = "<p> <label style='color:red;'>Marry</label> has a <b>little lamb</b>! <br/><p>";
        private const string ExpectResult = "Marry has a little lamb!";

        [TestMethod]
        public void Can_Remove_HtmlTags_By_Three_Methods()
        {
            string result;

            var timeSpan = RemoveHtmlTags(RemoveMethods.Regex, out result);
            Assert.AreEqual(result.Trim(), ExpectResult);
            Console.WriteLine("Remove HTML Tags using regex elasped time {0}", timeSpan);

            timeSpan = RemoveHtmlTags(RemoveMethods.CompiledRegex, out result);
            Assert.AreEqual(result.Trim(), ExpectResult);
            Console.WriteLine("Remove HTML Tags using compiled regex elasped time {0}", timeSpan);

            timeSpan = RemoveHtmlTags(RemoveMethods.CharArray, out result);
            Assert.AreEqual(result.Trim(), ExpectResult);
            Console.WriteLine("Remove HTML Tags using char array elasped time {0}", timeSpan);
        }

Kết quả khi chạy kiểm thử:

Chúng ta có thể thấy rằng, thời gian để chạy Compiled Regex sẽ nhanh hơn sử dụng Regex chưa biên dịch, và sử dụng char array cho tốc độ thực thi cao nhất, cao hơn nhiều so với hai cách còn lại.

Theo tumivn