I would like to comment on several things.
Firstly, as you have written your patterns, it is really a single pattern. I'm assuming that, when you talk about the 'first' and 'second' regex's that you are referring to the first and second alternates. In what follows, I've used just the first 2 lines as the 'first' regex and the last 2 as the 'second' regex.
With the first regex, looking at the "(?'content'(?=</\k'tagName'>))" part, this will never match anything, and the reason you are getting a match from your sample data is that you have no text between the start and end 'span' tags. What is happening is that you are starting a named group ('content') and then using a lookahead to make sure the next part of the text is the end tag. Remember that lookarounds are placeholders, they do not match any text and do not advance the the place in the text that the regex engine is examining.
Looking at your original post, I beleive that you are wanting to capture the text between the tags, in which case you should change this to something like "(?'content'((?!</\k'tagName'>).)*)". What this does is check to see if the next part of the text is the end tag. If it is not, then the '.' consumes 1 character and adds it to the match and then goes back to check the next character. When the lookahead finally does find the end tag, it 'fails' which exits the named match group and moves on to the part that matches the end tag. The way I have written it will allow for no text between the start and end tags, but also matches and captures any text that is there. (Of course there is always the warning about using '.' if the text can span lines breaks in which case the 'singleline' mode will be needed).
Now the 'second' regex. The reason it matches everything is that the ".*" part of the 'content' match group is greedy. This means that it will match as many characters as it possibly can and in your test case (in the above post, not the original post) that means to the end of the string. The regex engine then tries to match the end tag but can't (it's at the end of the string!). Therefore it backtracks by 1 character and tries again. Again it fails and so it will repeat the process until either it has backtracked over all of the characters matched by the 'content' group or it finds a match - in this case that is what happens. However, this is the LAST end tag in the string, not necessarily the end tag that immediately follows the one that started the match in the first place.
The straightforward solution is to make the ".*" non-greedy i.e. ".*?". This will then perform as you expect in this case.
Hope this makes sense.
Susan