Search code examples
c#regextagspattern-matchingrichtext

How to get inner color tag matches using Regex?


I have this one problem, what pattern I should use to find all rich text color tags within other color tags?

So for example I have this input:

<color=yellow>Hello <color=cyan>World!</color></color>

And remove, by replacing with empty string matched tags and have this as an input after:

<color=yellow>Hello World!</color>

It could be even more tags within, for example:

<color=yellow>Hello my <color=cyan>name</color> is <color=gray>Kite <color=white>Watson!</color></color></color>

And have this after:

<color=yellow>Hello my name is Kite Watson!</color>

The reason I need this is because I use Regex to apply code highlighter to text in text box and some keywords are colorized within comments, like in below example

enter image description here

So I want to check and remove if there are any color tags within color tags, like in this comment example.

I'm pretty new to Regex, so currently a bit lost and not sure what to do. Can someone give me some advice on how can I accomplish this? :) Thank you!


Solution

  • I went with a bit different approach.

        Regex tags = new Regex(@"<color=#.*?>|<\/color>");
        MatchCollection matches = tags.Matches(c);
    
        bool hasStarted = false;
        int innerTags = 0;
    
        const string tempStart = "¬¬¬¬¬¬¬Â";
        const string tempEnd = "Â~Â~Â~Â~";
        foreach (Match match in matches)
        {
            if (match.Value.Contains("<color=#"))
            {
                if (hasStarted)
                {
                    var cBuilder = new StringBuilder(c);
                    cBuilder.Remove(match.Index, match.Length);
                    cBuilder.Insert(match.Index, tempStart);
    
                    c = cBuilder.ToString();
    
                    innerTags++;
                }
                else
                {
                    hasStarted = true;
                }
            }
            else if (match.Value.Equals("</color>"))
            {
                if (innerTags > 0)
                {
                    var cBuilder = new StringBuilder(c);
                    cBuilder.Remove(match.Index, match.Length);
                    cBuilder.Insert(match.Index, tempEnd);
    
                    c = cBuilder.ToString();
    
                    innerTags--;
                }
                else if (innerTags <= 0)
                {
                    hasStarted = false;
                }
            }
        }
        c = c.Replace(tempStart, string.Empty);
        c = c.Replace(tempEnd, string.Empty);
    

    Not sure if it's the best way, but it works quite well.