views:

1158

answers:

6

I'm trying to convert all instances of the > character to its HTML entity equivalent, >, within a string of HTML that contains HTML tags. The furthest I've been able to get with a solution for this is using a regex.

Here's what I have so far:

        public static readonly Regex HtmlAngleBracketNotPartOfTag = new Regex("(?:<[^>]*(?:>|$))(>)", RegexOptions.Compiled | RegexOptions.Singleline);

The main issue I'm having is isolating the single > characters that are not part of an HTML tag. I don't want to convert any existing tags, because I need to preserve the HTML for rendering. If I don't convert the > characters, I get malformed HTML, which causes rendering issues in the browser.

This is an example of a test string to parse:

"Ok, now I've got the correct setting.<br/><br/>On 12/22/2008 3:45 PM, [email protected] wrote:<br/><div class"quotedReply">> Ok, got it, hope the angle bracket quotes are there.<br/>><br/>> On 12/22/2008 3:45 PM, > [email protected] wrote:<br/>>> Please someone, reply to this.<br/>>><br/>><br/></div>"

In the above string, none of the > characters that are part of HTML tags should be converted to >. So, this:

<div class"quotedReply">>

should become this:

<div class"quotedReply">&gt;

Another issue is that the expression above uses a non-capturing group, which is fine except for the fact that the match is in group 1. I'm not quite sure how to do a replace only on group 1 and preserve the rest of the match. It appears that a MatchEvaluator doesn't really do the trick, or perhaps I just can't envision it right now.

I suspect my regex could do with some lovin'.

Anyone have any bright ideas?

+1  A: 

Maybe read your HTML into an XML parser which should take care of the conversions for you.

Jeff.Crossett
I'm not sure this is the correct way to do what he's trying to do.
LarryF
A: 

Are you talking about the > chars inside of an HTML tag, (Like in Java's innerText), or in the arguements list of an HTML tag?

If you want to just sanitize the text between the opening and closing tag, that should be rather simple. Just locate any > char, and replace it with the &gt ;. (I'd also do it with the &lt tag), but the HTML render engine SHOULD take care of this for you...

Give an example of what you are trying to sanitize, and maybe we an find the best solution for it.

Larry

LarryF
I'm talking about characters that don't fall inside an HTML tag, including the characters that make up the tag.
steve_c
A: 

Could you read the string into an XML document and look at the values and replace the > with &gt; in the values. This would require recursively going into each node in the document but that shouldn't be too hard to do.

JB King
I thought of this using an HTML parser. The problem I encountered with this is that not everything is inside a node, so it was discarding all text that wasn't between a node.
steve_c
Where is a > that isn't part of an HTML tag and not inside a node?
JB King
A: 

Steve_C, you may try this RegEx. This will give capture any HTML tags in reference 1, and the text between the tags is stored in capture 2. I didn't fully test this, just throwing it out there in case it might help.

<([A-Z][A-Z0-9]*)[^>]*>(.*?)</\1>
LarryF
+4  A: 

Why do you want to do this? What harm are the > doing? Most parsers I've come across are quite happy with a > on its own without it needing to be escaped to an entity.

Additionally, it would be more appropriate to properly encode the content strings with HtmlUtilty.HtmlEncode before concatenating them with strings containing HTML markup, hence if this is under your control you should consider dealing with it there.

AnthonyWJones
If I leave the HTML as is, it will render with errors in Firefox.
steve_c
Are you sure? I've just tried it and not got any problems?
AnthonyWJones
+1. > does not, in general, cause problems in well-formed HTML. The *only* troublesome case is that the string ‘]]>’ is not allowed in text content in X[HT]ML. If you're getting errors, please post example code and the errors it gives. Regex is simply not capable of parsing [X][HT]ML.
bobince
+3  A: 

The trick is to capture everything that isn't the target, then plug it back in along with the changed text, like this:

Regex.Replace(str, @"\G((?>[^<>]+|<[^>]*>)*)>", "$1&gt;");

But Anthony's right: right angle brackets in text nodes shouldn't cause any problems. And matching HTML with regexes is tricky; for example, comments and CDATA can contain practically anything, so a robust regex would have to match them specifically.

Alan Moore
This did the trick. Just writing some test cases for it, but all looks good so far.
steve_c