开发者

Regex: matching all improper tag attributes

For an example input of:

<a href="abc" something=b foo="bar" baz=cool>

I am trying to match:

something=b
baz=cool

However, everything I end up with will only match the first one (something=b), even when using preg_match_all. The regular expression I am using is:

<\w+.*?(\w+=[^"|^'|^>]).*?>

Or:

<\w+ # Word starting with <
.*?  # Anything that comes in front of the matching attribute.
(
\w+  # The attribute
=
[^"|^'|^>]+? # Keep going until we find a ", ' or >
)
.*? # Anything that comes after the matching attribute.
> # Closing >

I'm probably doing something horribly wrong, pretty new to regular expressions. Please advise! :)

edit:

Revised regular expression:

<\w+.*开发者_Python百科?\w+=([^"\'\s>]+).*?>

Regex: matching all improper tag attributes

I want it to match zzz=aaa there too ;)


Use a library like Tidy or HTMLPurifier to fix broken HTML for you.


For starters, the caret "^" symbol negates the entire character class. The character class has implied or statements, that's the point of a character class, so your class can be shortened to [^'">]

Now as to why you're only getting the "something=b" tag, I believe you're missing a + after your character class.

So your regexp with my modifications would be:

<\w+.*?(\w+=[^"'>]+?) .*?>

Note the space after the end of the group


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

You may try this with # delimiter and x modifier. I have formatted it so it is more readable.


In your regex <\w+.*?(\w+=[^"|^'|^>]).*?>, the \w+=[^"|^'|^>] part doesn't do what you think it does - you are mixing character classes and alternation with pipe character

Writing a regex that will catch all malformed attributes inside a given XMLish tag is tricky if the attribute value can have > or = characters.

For example:

<a href="asd" title=This page proves that e=MC^2>

Your regex tries to extract all attributes from the whole string in one step - it looks for <tag and then an unquoted attribute somewhere later. This way you'll match only one attribute, the first one.

You can extract the contents of the opening and closing angle brackets in one step and then look for attributes within that. The regex <\w+\s+([^>]+?)\s*> will give you the substring of attributes. Search within that string for unquoted attributes. If the attributes are simple (as in they don't contain spaces), you can use a simple

\w+=(?=[^"'])[^ ]+

If they can contain spaces too, you're gonna need some more lookahead:

\w+=(?=[^"']).+?(?=\w+=|$)


If you know you don't have any = sign outside your tags, you can use this regex:

(?<=\=)([^"\'\s>]+)(?=[\s>])

In this example it matches all improper attributes

Edit:

(?<=\=)([^"\'\s/>]+)(?=[\s/?>])

this matches class2 in <div class=class2/> also.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜