注意
-
一部のパターンは未完成です。
-
本投稿には原文の引用を載せていますが、著者は英訳が出来ません。翻訳ミスの指摘などは、翻訳元の投稿にお願いします。
-
本投稿の正規表現をPHPで利用する場合、UTF-8の文字列に対して使う場合にはu(PCRE_UTF8)オプションを指定してください。
指定しない場合、文字列が破壊される恐れがあります。
参考
- HTML5 で省略できるタグ - Qiita
- 12.1.2.4 Optional tags - HTML Standard
- 正規表現 - 文字列内から HTML タグを正確に判別! - mk-mode BLOG
- htmlのコメントタグを除去するJavaScriptの正規表現。 - freefielder.jp
- 4.3. Elements - HTML syntax - HTML5
前提
-
以下の正規表現は、正当なHTMLで動作させることを想定しています。
要素ではない<や>などの文字は、<や>に置換されている必要があります。 -
この正規表現では肯定的前方先読み
(?=pattern)と否定的前方先読み(?!pattern)のパターンを利用しています。
また、厳密版のパターンでは、制御文字の指定のためバイトコード表現\xhh(hは16進表現の文字)を利用しています。 -
PHPのpreg_match_all関数で検証を行っていますが、ミスが存在するかもしれません。利用する場合、予め検証を行って下さい。またミスが見つかった場合、指摘していただければありがたいです。
HTMLの正規表現
簡易版
<[0-9a-zA-Z]+(\s+[^\s"'>/=]+(\s*=\s*([^\s"'=><`]+|'[^']*'|"[^"]*"))?)*\s*/?>
</[0-9a-zA-Z]+\s*>
<!--[\s\S]*?-->
\s
<x(\s+[^\s"'>/=]+(\s*=\s*([^\s"'=><`]+|'[^']*'|"[^"]*"))?)*\s*/?>
</x\s*>
厳密版
<[0-9a-zA-Z]+([ \t\n\f\r]+[^ \x00-\x1F\x7F"'>/=]+([ \t\n\f\r]*=[ \t\n\f\r]*([^ \t\n\f\r"'=><`]+|'[^\x00-\x08\x0B\x0E-\x1F\x7F']*'|"[^\x00-\x08\x0B\x0E-\x1F\x7F"]*"))?)*[ \t\n\f\r]*/?>
</[0-9a-zA-Z]+[ \t\n\f\r]*>
<!--[\s\S]*?-->
[ \t\n\f\r]
<x([ \t\n\f\r]+[^ \x00-\x1F\x7F"'>/=]+([ \t\n\f\r]*=[ \t\n\f\r]*([^ \t\n\f\r"'=><`]+|'[^\x00-\x08\x0B\x0E-\x1F\x7F']*'|"[^\x00-\x08\x0B\x0E-\x1F\x7F"]*"))?)*[ \t\n\f\r]*/?>
</x[ \t\n\f\r]*>
注意
- 制御文字の指定のため、バイトコード表現の
[\x00-\x1F\x7F]を利用しています。このため、環境によっては正常に動作しない可能性があります。 - 仕様では、属性値などにUnicodeにない文字は利用できませんが、本投稿の正規表現では考慮していません。
Unicodeにない文字の正規表現なんてどう書けばいいのよ…?
参考
- 正規表現 - 文字列内から HTML タグを正確に判別! - mk-mode BLOG
- htmlのコメントタグを除去するJavaScriptの正規表現。 - freefielder.jp
- 4.3. Elements - HTML syntax - HTML5
正規表現
<html>
Anhtmlelement's start tag may be omitted if the first thing inside thehtmlelement is not a comment.
<html>はその最初の内容がコメントでなければ省略できる
<html\s*>(?!<!--[\s\S]*?-->)
<html[ \t\n\f\r]*>(?!<!--[\s\S]*?-->)
</html>
Anhtmlelement's end tag may be omitted if thehtmlelement is not immediately followed by a comment.
</html>は直後にコメントが続かなければ省略できる
</html\s*>(?!<!--[\s\S]*?-->)
</html[ \t\n\f\r]*>(?!<!--[\s\S]*?-->)
<head>
Aheadelement's start tag may be omitted if the element is empty, or if the first thing inside theheadelement is an element.
<head>は内容が空か、最初の内容が要素なら省略できる
<head\s*>(?=</head\s*>|<[0-9a-zA-Z]+(\s+[^\s"'>/=]+(\s*=\s*([^\s"'=><`]+|'[^']*'|"[^"]*"))?)*\s*/?>)
<head[ \t\n\f\r]*>(?=</head[ \t\n\f\r]*>|<[0-9a-zA-Z]+([ \t\n\f\r]+[^ \x00-\x1F\x7F"'>/=]+([ \t\n\f\r]*=[ \t\n\f\r]*([^ \t\n\f\r"'=><`]+|'[^\x00-\x08\x0B\x0E-\x1F\x7F']*'|"[^\x00-\x08\x0B\x0E-\x1F\x7F"]*"))?)*[ \t\n\f\r]*/?>)
</head>
Aheadelement's end tag may be omitted if theheadelement is not immediately followed by a space character or a comment.
</head>は直後に空白文字かコメントがなければ省略できる
</head\s*>(?!\s|<!--[\s\S]*?-->)
</head[ \t\n\f\r]*>(?![ \t\n\f\r]|<!--[\s\S]*?-->)
<body>
Abodyelement's start tag may be omitted if the element is empty, or if the first thing inside thebodyelement is not a space character or a comment, except if the first thing inside thebodyelement is ameta,link,script,style, ortemplateelement.
<body>は内容が空か、最初の内容が空白文字かコメントでなければ省略できるが、最初の要素が meta, link, script, style, template なら省略できない
<body\s*>(?=</body\s*>|(?!\s|<!--[\s\S]*?-->|<(script|style|template)(\s+[^\s"'>/=]+(\s*=\s*([^\s"'=><`]+|'[^']*'|"[^"]*"))?)*\s*>|<(meta|link)(\s+[^\s"'>/=]+(\s*=\s*([^\s"'=><`]+|'[^']*'|"[^"]*"))?)*\s*/?>))
<body[ \t\n\f\r]*>(?=</body[ \t\n\f\r]*>|(?![ \t\n\f\r]|<!--[\s\S]*?-->|<(script|style|template)([ \t\n\f\r]+[^ \x00-\x1F\x7F"'>/=]+([ \t\n\f\r]*=[ \t\n\f\r]*([^ \t\n\f\r"'=><`]+|'[^\x00-\x08\x0B\x0E-\x1F\x7F']*'|"[^\x00-\x08\x0B\x0E-\x1F\x7F"]*"))?)*[ \t\n\f\r]*>|<(meta|link)([ \t\n\f\r]+[^ \x00-\x1F\x7F"'>/=]+([ \t\n\f\r]*=[ \t\n\f\r]*([^ \t\n\f\r"'=><`]+|'[^\x00-\x08\x0B\x0E-\x1F\x7F']*'|"[^\x00-\x08\x0B\x0E-\x1F\x7F"]*"))?)*[ \t\n\f\r]*/?>))
</body>
Abodyelement's end tag may be omitted if thebodyelement is not immediately followed by a comment.
</body>は直後にコメントが続かなければ省略できる
</body\s*>(?!<!--[\s\S]*?-->)
</body[ \t\n\f\r]*>(?!<!--[\s\S]*?-->)
</li>
Anlielement's end tag may be omitted if thelielement is immediately followed by anotherlielement or if there is no more content in the parent element.
</li>は直後に li 要素が続くか、親要素にそれ以上内容がなければ省略できる
</li\s*>(?=<li(\s+[^\s"'>/=]+(\s*=\s*([^\s"'=><`]+|'[^']*'|"[^"]*"))?)*\s*>|</[0-9a-zA-Z]+\s*>)
</li[ \t\n\f\r]*>(?=<li([ \t\n\f\r]+[^ \x00-\x1F\x7F"'>/=]+([ \t\n\f\r]*=[ \t\n\f\r]*([^ \t\n\f\r"'=><`]+|'[^\x00-\x08\x0B\x0E-\x1F\x7F']*'|"[^\x00-\x08\x0B\x0E-\x1F\x7F"]*"))?)*[ \t\n\f\r]*>|</[0-9a-zA-Z]+[ \t\n\f\r]*>)
</dt>
Adtelement's end tag may be omitted if thedtelement is immediately followed by anotherdtelement or addelement.
</dt>は直後に dt, dd 要素が続けば省略できる
</dt\s*>(?=<(dt|dd)(\s+[^\s"'>/=]+(\s*=\s*([^\s"'=><`]+|'[^']*'|"[^"]*"))?)*\s*>)
</dt[ \t\n\f\r]*>(?=<(dt|dd)([ \t\n\f\r]+[^ \x00-\x1F\x7F"'>/=]+([ \t\n\f\r]*=[ \t\n\f\r]*([^ \t\n\f\r"'=><`]+|'[^\x00-\x08\x0B\x0E-\x1F\x7F']*'|"[^\x00-\x08\x0B\x0E-\x1F\x7F"]*"))?)*[ \t\n\f\r]*>)
</dd>
Addelement's end tag may be omitted if theddelement is immediately followed by anotherddelement or adtelement, or if there is no more content in the parent element.
</dd>は直後に dt, dd 要素が続くか、親要素にそれ以上内容がなければ省略できる
</dd\s*>(?=<(dt|dd)(\s+[^\s"'>/=]+(\s*=\s*([^\s"'=><`]+|'[^']*'|"[^"]*"))?)*\s*>|</[0-9a-zA-Z]+\s*>)
</dd[ \t\n\f\r]*>(?=<(dt|dd)([ \t\n\f\r]+[^ \x00-\x1F\x7F"'>/=]+([ \t\n\f\r]*=[ \t\n\f\r]*([^ \t\n\f\r"'=><`]+|'[^\x00-\x08\x0B\x0E-\x1F\x7F']*'|"[^\x00-\x08\x0B\x0E-\x1F\x7F"]*"))?)*[ \t\n\f\r]*>|</[0-9a-zA-Z]+[ \t\n\f\r]*>)
</p>
Apelement's end tag may be omitted if thepelement is immediately followed by anaddress,article,aside,blockquote,details,div,dl,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,header,hgroup,hr,main,menu,nav,ol,p,pre,section,table, orulelement, or if there is no more content in the parent element and the parent element is an HTML element that is not ana,audio,del,ins,map,noscript, orvideoelement.
</p>は直後に address, article, aside, blockquote, details, div, dl, fieldset, figcaption, figure, footer, form, h1, h2, h3, h4, h5, h6, header, hgroup, hr, main, menu, nav, ol, p, pre, section, table, ul 要素が続くか、親要素が a, audio, del, ins, map, noscript, video 以外で親要素にそれ以上内容がなければ省略できる
</p\s*>(?=<(address|article|aside|blockquote|details|div|dl|fieldset|figcaption|figure|footer|form|h1|h2|h3|h4|h5|h6|header|hgroup|main|menu|nav|ol|p|pre|section|table|ul)(\s+[^\s"'>/=]+(\s*=\s*([^\s"'=><`]+|'[^']*'|"[^"]*"))?)*\s*>|<hr(\s+[^\s"'>/=]+(\s*=\s*([^\s"'=><`]+|'[^']*'|"[^"]*"))?)*\s*/?>|</(?!(a|audio|del|ins|map|noscript|video)\s*>)[0-9a-zA-Z]+\s*>)
</p[ \t\n\f\r]*>(?=<(address|article|aside|blockquote|details|div|dl|fieldset|figcaption|figure|footer|form|h1|h2|h3|h4|h5|h6|header|hgroup|main|menu|nav|ol|p|pre|section|table|ul)([ \t\n\f\r]+[^ \x00-\x1F\x7F"'>/=]+([ \t\n\f\r]*=[ \t\n\f\r]*([^ \t\n\f\r"'=><`]+|'[^\x00-\x08\x0B\x0E-\x1F\x7F']*'|"[^\x00-\x08\x0B\x0E-\x1F\x7F"]*"))?)*[ \t\n\f\r]*>|<hr([ \t\n\f\r]+[^ \x00-\x1F\x7F"'>/=]+([ \t\n\f\r]*=[ \t\n\f\r]*([^ \t\n\f\r"'=><`]+|'[^\x00-\x08\x0B\x0E-\x1F\x7F']*'|"[^\x00-\x08\x0B\x0E-\x1F\x7F"]*"))?)*[ \t\n\f\r]*/?>|</(?!(a|audio|del|ins|map|noscript|video)[ \t\n\f\r]*>)[0-9a-zA-Z]+[ \t\n\f\r]*>)
</rt>
Anrtelement's end tag may be omitted if thertelement is immediately followed by anrtorrpelement, or if there is no more content in the parent element.
</rt>は直後に rt, rp 要素が続くか、親要素にそれ以上内容がなければ省略できる
</rt\s*>(?=<(rt|rp)(\s+[^\s"'>/=]+(\s*=\s*([^\s"'=><`]+|'[^']*'|"[^"]*"))?)*\s*>|</[0-9a-zA-Z]+\s*>)
</rt[ \t\n\f\r]*>(?=<(rt|rp)([ \t\n\f\r]+[^ \x00-\x1F\x7F"'>/=]+([ \t\n\f\r]*=[ \t\n\f\r]*([^ \t\n\f\r"'=><`]+|'[^\x00-\x08\x0B\x0E-\x1F\x7F']*'|"[^\x00-\x08\x0B\x0E-\x1F\x7F"]*"))?)*[ \t\n\f\r]*>|</[0-9a-zA-Z]+[ \t\n\f\r]*>)
</rp>
Anrpelement's end tag may be omitted if therpelement is immediately followed by anrtorrpelement, or if there is no more content in the parent element.
</rp>は直後に rt, rp 要素が続くか、親要素にそれ以上内容がなければ省略できる
</rp\s*>(?=<(rt|rp)(\s+[^\s"'>/=]+(\s*=\s*([^\s"'=><`]+|'[^']*'|"[^"]*"))?)*\s*>|</[0-9a-zA-Z]+\s*>)
</rp[ \t\n\f\r]*>(?=<(rt|rp)([ \t\n\f\r]+[^ \x00-\x1F\x7F"'>/=]+([ \t\n\f\r]*=[ \t\n\f\r]*([^ \t\n\f\r"'=><`]+|'[^\x00-\x08\x0B\x0E-\x1F\x7F']*'|"[^\x00-\x08\x0B\x0E-\x1F\x7F"]*"))?)*[ \t\n\f\r]*>|</[0-9a-zA-Z]+[ \t\n\f\r]*>)
</optgroup>
Anoptgroupelement's end tag may be omitted if theoptgroupelement is immediately followed by anotheroptgroupelement, or if there is no more content in the parent element.
</optgroup>は直後に別の optgroup 要素が続くか、親要素にそれ以上内容がなければ省略できる
</optgroup\s*>(?=<optgroup(\s+[^\s"'>/=]+(\s*=\s*([^\s"'=><`]+|'[^']*'|"[^"]*"))?)*\s*>|</[0-9a-zA-Z]+\s*>)
</optgroup[ \t\n\f\r]*>(?=<optgroup([ \t\n\f\r]+[^ \x00-\x1F\x7F"'>/=]+([ \t\n\f\r]*=[ \t\n\f\r]*([^ \t\n\f\r"'=><`]+|'[^\x00-\x08\x0B\x0E-\x1F\x7F']*'|"[^\x00-\x08\x0B\x0E-\x1F\x7F"]*"))?)*[ \t\n\f\r]*>|</[0-9a-zA-Z]+[ \t\n\f\r]*>)
</option>
Anoptionelement's end tag may be omitted if theoptionelement is immediately followed by anotheroptionelement, or if it is immediately followed by anoptgroupelement, or if there is no more content in the parent element.
</option>は直後に option, optgroup 要素が続くか、親要素にそれ以上内容がなければ省略できる
</option\s*>(?=<(option|optgroup)(\s+[^\s"'>/=]+(\s*=\s*([^\s"'=><`]+|'[^']*'|"[^"]*"))?)*\s*>|</[0-9a-zA-Z]+\s*>)
</option[ \t\n\f\r]*>(?=<(option|optgroup)([ \t\n\f\r]+[^ \x00-\x1F\x7F"'>/=]+([ \t\n\f\r]*=[ \t\n\f\r]*([^ \t\n\f\r"'=><`]+|'[^\x00-\x08\x0B\x0E-\x1F\x7F']*'|"[^\x00-\x08\x0B\x0E-\x1F\x7F"]*"))?)*[ \t\n\f\r]*>|</[0-9a-zA-Z]+[ \t\n\f\r]*>)
<colgroup>
未完成
Acolgroupelement's start tag may be omitted if the first thing inside thecolgroupelement is acolelement, and if the element is not immediately preceded by anothercolgroupelement whose end tag has been omitted. (It can't be omitted if the element is empty.)
<colgroup>はその最初の内容が col 要素で、直前に終了タグを省略した colgroup 要素がなければ省略できる (ただし空要素の場合省略できない)
```txt:最初の内容がcol要素の<colgroup>(簡易版)
```txt:最初の内容がcol要素の`<colgroup>`(厳密版)
<colgroup[ \t\n\f\r]*>(?=<col([ \t\n\f\r]+[^ \x00-\x1F\x7F"'>/=]+([ \t\n\f\r]*=[ \t\n\f\r]*([^ \t\n\f\r"'=><`]+|'[^\x00-\x08\x0B\x0E-\x1F\x7F']*'|"[^\x00-\x08\x0B\x0E-\x1F\x7F"]*"))?)*[ \t\n\f\r]*/?>)
Note
-
終了タグを省略したX要素にマッチしないパターンの戻り読みが出来ず、解決方法が不明。
殆どの環境で可変長テキストの戻り読みはサポートされておらず、多分詰んでいる。 -
(ただし空要素の場合省略できない)
ここで言う空要素が何を示すのか不明。
- 省略対象の colgroup 要素は、そもそも子要素に col 要素が含まれなければならず、空要素とはならない。
- 内容に当たる col 要素は、そもそも常に空要素(閉じタグは無し)。
- 直前の colgroup 要素については、空要素(中身の無い要素、閉じタグはルールにより省略不可)でも問題なし。
(It can't be omitted if the element is empty.)
原文にはこうある(「ただし」と書かれてはいない)ので、省略対象の colgroup 要素の事だと思われるが…
例示
※要素(タグ)の間にある改行や空白文字、説明用のHTMLコメントは無視するものとする。
<table>
<caption>保元の乱</caption>
<colgroup><!-- 直前にはcolgroup要素そのものが無いため、省略可 -->
<col>
</colgroup>
<colgroup><!-- 直前のcolgroup要素は終了タグが省略されていないため、省略可 -->
<col style="background:#f96;">
<colgroup><!-- 直前のcolgroup要素は終了タグが省略されており、省略不可 -->
<col style="background:#ffc;">
<col style="background:#9fc;">
<col style="background:#69f;">
<tr>
<th>
<th>天皇家
<th>藤原氏
<th>平氏
<th>源氏
<tr>
<th>天皇方
<td>後白河
<td>忠通
<td>清盛
<td>義朝
<tr>
<th>上皇方
<td>崇徳
<td>頼長
<td>忠正
<td>為義
</table>
</colgroup>
Acolgroupelement's end tag may be omitted if thecolgroupelement is not immediately followed by a space character or a comment.
</colgroup>は直後に空白文字かコメントがなければ省略できる
</colgroup\s*>(?!\s|<!--[\s\S]*?-->)
</colgroup[ \t\n\f\r]*>(?![ \t\n\f\r]|<!--[\s\S]*?-->)
</caption>
Acaptionelement's end tag may be omitted if thecaptionelement is not immediately followed by a space character or a comment.
</caption>は直後に空白文字かコメントがなければ省略できる
</caption\s*>(?!\s|<!--[\s\S]*?-->)
</caption[ \t\n\f\r]*>(?![ \t\n\f\r]|<!--[\s\S]*?-->)
</thead>
Atheadelement's end tag may be omitted if thetheadelement is immediately followed by atbodyortfootelement.
</thead>は直後に tbody, tfoot 要素が続けば省略できる
</thead\s*>(?=<(tbody|tfoot)(\s+[^\s"'>/=]+(\s*=\s*([^\s"'=><`]+|'[^']*'|"[^"]*"))?)*\s*>)
</thead[ \t\n\f\r]*>(?=<(tbody|tfoot)([ \t\n\f\r]+[^ \x00-\x1F\x7F"'>/=]+([ \t\n\f\r]*=[ \t\n\f\r]*([^ \t\n\f\r"'=><`]+|'[^\x00-\x08\x0B\x0E-\x1F\x7F']*'|"[^\x00-\x08\x0B\x0E-\x1F\x7F"]*"))?)*[ \t\n\f\r]*>)
<tbody>
未完成
Atbodyelement's start tag may be omitted if the first thing inside thetbodyelement is atrelement, and if the element is not immediately preceded by atbody,thead, ortfootelement whose end tag has been omitted. (It can't be omitted if the element is empty.)
<tbody>はその最初の内容が tr で、直前に終了タグを省略した tbody, thead, tfoot 要素がなければ省略できる
```txt:最初の内容がtr要素の<tbody>(簡易版)
```txt:最初の内容がtr要素の`<tbody>`(厳密版)
<tbody[ \t\n\f\r]*>(?=<tr([ \t\n\f\r]+[^ \x00-\x1F\x7F"'>/=]+([ \t\n\f\r]*=[ \t\n\f\r]*([^ \t\n\f\r"'=><`]+|'[^\x00-\x08\x0B\x0E-\x1F\x7F']*'|"[^\x00-\x08\x0B\x0E-\x1F\x7F"]*"))?)*[ \t\n\f\r]*>)
Note
終了タグを省略したX要素にマッチしないパターンの戻り読みが出来ず、解決方法が不明。
殆どの環境で可変長テキストの戻り読みはサポートされておらず、多分詰んでいる。
</tbody>
Atbodyelement's end tag may be omitted if thetbodyelement is immediately followed by atbodyortfootelement, or if there is no more content in the parent element.
</tbody>は直後に tbody, tfoot 要素が続くか、親要素にそれ以上内容がなければ省略できる
</tbody\s*>(?=<(tbody|tfoot)(\s+[^\s"'>/=]+(\s*=\s*([^\s"'=><`]+|'[^']*'|"[^"]*"))?)*\s*>|</[0-9a-zA-Z]+\s*>)
</tbody[ \t\n\f\r]*>(?=<(tbody|tfoot)([ \t\n\f\r]+[^ \x00-\x1F\x7F"'>/=]+([ \t\n\f\r]*=[ \t\n\f\r]*([^ \t\n\f\r"'=><`]+|'[^\x00-\x08\x0B\x0E-\x1F\x7F']*'|"[^\x00-\x08\x0B\x0E-\x1F\x7F"]*"))?)*[ \t\n\f\r]*>|</[0-9a-zA-Z]+[ \t\n\f\r]*>)
</tfoot>
Atfootelement's end tag may be omitted if thetfootelement is immediately followed by atbodyelement, or if there is no more content in the parent element.
</tfoot>は直後に tbody 要素が続くか、親要素にそれ以上内容がなければ省略できる
</tfoot\s*>(?=<tbody(\s+[^\s"'>/=]+(\s*=\s*([^\s"'=><`]+|'[^']*'|"[^"]*"))?)*\s*>|</[0-9a-zA-Z]+\s*>)
</tfoot[ \t\n\f\r]*>(?=<tbody([ \t\n\f\r]+[^ \x00-\x1F\x7F"'>/=]+([ \t\n\f\r]*=[ \t\n\f\r]*([^ \t\n\f\r"'=><`]+|'[^\x00-\x08\x0B\x0E-\x1F\x7F']*'|"[^\x00-\x08\x0B\x0E-\x1F\x7F"]*"))?)*[ \t\n\f\r]*>|</[0-9a-zA-Z]+[ \t\n\f\r]*>)
</tr>
Atrelement's end tag may be omitted if thetrelement is immediately followed by anothertrelement, or if there is no more content in the parent element.
</tr>は直後に tr 要素が続くか、親要素にそれ以上内容がなければ省略できる
</tr\s*>(?=<tr(\s+[^\s"'>/=]+(\s*=\s*([^\s"'=><`]+|'[^']*'|"[^"]*"))?)*\s*>|</[0-9a-zA-Z]+\s*>)
</tr[ \t\n\f\r]*>(?=<tr([ \t\n\f\r]+[^ \x00-\x1F\x7F"'>/=]+([ \t\n\f\r]*=[ \t\n\f\r]*([^ \t\n\f\r"'=><`]+|'[^\x00-\x08\x0B\x0E-\x1F\x7F']*'|"[^\x00-\x08\x0B\x0E-\x1F\x7F"]*"))?)*[ \t\n\f\r]*>|</[0-9a-zA-Z]+[ \t\n\f\r]*>)
</td>
Atdelement's end tag may be omitted if thetdelement is immediately followed by atdorthelement, or if there is no more content in the parent element.
</td>は直後に td, th 要素が続くか、親要素にそれ以上内容がなければ省略できる
</td\s*>(?=<(td|th)(\s+[^\s"'>/=]+(\s*=\s*([^\s"'=><`]+|'[^']*'|"[^"]*"))?)*\s*>|</[0-9a-zA-Z]+\s*>)
</td[ \t\n\f\r]*>(?=<(td|th)([ \t\n\f\r]+[^ \x00-\x1F\x7F"'>/=]+([ \t\n\f\r]*=[ \t\n\f\r]*([^ \t\n\f\r"'=><`]+|'[^\x00-\x08\x0B\x0E-\x1F\x7F']*'|"[^\x00-\x08\x0B\x0E-\x1F\x7F"]*"))?)*[ \t\n\f\r]*>|</[0-9a-zA-Z]+[ \t\n\f\r]*>)
</th>
Athelement's end tag may be omitted if thethelement is immediately followed by atdorthelement, or if there is no more content in the parent element.
</th>は直後に td, th 要素が続くか、親要素にそれ以上内容がなければ省略できる
</th\s*>(?=<(td|th)(\s+[^\s"'>/=]+(\s*=\s*([^\s"'=><`]+|'[^']*'|"[^"]*"))?)*\s*>|</[0-9a-zA-Z]+\s*>)
</th[ \t\n\f\r]*>(?=<(td|th)([ \t\n\f\r]+[^ \x00-\x1F\x7F"'>/=]+([ \t\n\f\r]*=[ \t\n\f\r]*([^ \t\n\f\r"'=><`]+|'[^\x00-\x08\x0B\x0E-\x1F\x7F']*'|"[^\x00-\x08\x0B\x0E-\x1F\x7F"]*"))?)*[ \t\n\f\r]*>|</[0-9a-zA-Z]+[ \t\n\f\r]*>)