質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

Q&A

解決済

4回答

4061閲覧

正規表現によるHTML内のスタイル除去時に、特定のスタイルは残したい

may_left

総合スコア12

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

0グッド

0クリップ

投稿2016/05/30 10:24

###HTMLコード内の正規表現によるスタイル除去で特定のスタイルを残す方法
PHP上で文字列として保持しているHTMLコード内の、

<td>タグでrowspanとcolspanを残し、それ以外を削除したいのですが可能でしょうか。

###現在作成してみた正規表現パターン

php

1$body = preg_replace('/<td ("[^"]*"|\'[^\']*\'|[^\'">])*>/', '<td>', $body);

この正規表現でTDタグのスタイル要素類全てを削除することができたのですが、rowspanとcolspanを残す。というのがどうしてもできずという状況です。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

ベストアンサー

こういう複雑なのは小さくわかりやすい要素から順番に考えていくのが常套です。

まず、タグの正規表現は「<」から始まり「>」で終わるため
例としてhoge要素のタグを考えると

php

1/<hoge [^>]*>/

それでとりあえず属性piyoをサーチするということで

php

1/<hoge [^>]*(piyo=((\'[^\'>]*\')|("[^">]*")))[^>]*>/2piyoは\1で回収

※piyoの値がエスケープを使ったクォーテーションを含む文字列のときはこれではダメですが複雑になるのでここでは無視してます。

これをベースに
hoge = td
piyo = rowpsan|colspan
を考えると

php

1'/<td [^>]*((row|col)span=((\'[^\'>]*\')|("[^">]*")))[^>]*>/'

そして、
0. tdはヘッダーであるthの場合もある
0. rowspan/colspanの値は数字
0. タグは大文字のときもある

を考えてpreg_replaceの関数に入れると

php

1$body = preg_replace('/<(td|th) [^>]*((row|col)span=("\d+"|\'\d+\'))[^>]*>/i', '<\1 \2>', $body);

となります。
完成!ヽ(=´▽`=)ノ 

↑うそでした

↓修正

colspanとrowspanをそれぞれ保つ場合もあることを失念してました。
なので本当は

php

1$body = preg_replace('/<(td|th) [^>]*?((?:row|col)span=(?:"\d+"|\'\d+\'))(?:[^>]*((row|col)span=("\d+"|\'\d+\')))?[^>]*>/i', '<\1 \2 \3>', $body);

です。
ちょっと解説する量が多くなるので解説はごめんなさい。パズルみたいに考えてみてください。

あと、これの後に

php

1$body = preg_replace('/<(td|th) +>/i','<td>',$body)

を更に入れておくと吐き出されるHTMLソースが綺麗になります。

投稿2016/05/30 13:14

編集2016/05/30 13:35
oskbt

総合スコア1895

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

may_left

2016/05/31 02:42

正規表現の考え方としての解説までしてくださりありがとうございます。
guest

0

あまり綺麗にいかなかったのですが、こんな感じでどうでしょう?

PHP

1$pattern = '/<td(( rowspan.*?(["\']).*?\3)|( colspan.*?(["\']).*?\5)|.)*?>/'; 2 3$str = "<td colspan='2' rowspan='\"3\"' aaa='123'>"; 4echo preg_replace($pattern, '<td\2\4>', $str); 5//<td rowspan='"3"' colspan='2'> シングル&ダブルクオートのネストは多分OK 6 7$str = "<td colspan='2'rowspan='3' aaa='123'>"; 8echo preg_replace($pattern, '<td\2\4>', $str); 9//<td colspan='2'> 先頭にスペースが無いと無視 10 11$str = "<td colspan='2' rowspan='3' aaa='123' rowspan='5'>"; 12echo preg_replace($pattern, '<td\2\4>', $str); 13//<td rowspan='5' colspan='2'> 同じ属性が2つある場合は後方優先

投稿2016/05/30 12:13

編集2016/05/30 14:23
hirohiro

総合スコア2068

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

may_left

2016/05/31 02:50

ありがとうございます。 大変たすかりました。
guest

0

あんまり複雑な条件を正規表現一発で何とかしようとするのはデバッグ等の面で割と大変なので、
ちょっと方向性を変えて単純化するという手もあります。

例えば

    • HTMLを改行や閉じタグ単位でexplode()等で分割して配列に格納する
    • 配列をforeachで走査する
    • (配列の要素が<td>を含んでるか確認し、含んでなかったら次の要素に飛ぶ)
    • 配列の要素一つ一つをpreg_match()で<td>タグのcolspan,rowspanを抜き出して変数に格納する
    • 格納した変数を今出来ているpreg_replaceの'<td>'に組み合わせて置換する
    • 出来上がった配列をimplode()で文字列に連結する

みたいにすれば出来るでしょうし、

もっとスマートに処理するなら
PHP HTML パーサで検索
して、HTMLを文字列では無くオブジェクトとして扱い、tdオブジェクトの要素を操作して必要な属性だけ残す。という事が出来るようになれば、今後別の要素に別の操作をしたい時にでもあんまり悩まずに色々出来るようにまります。

投稿2016/05/30 12:10

tanat

総合スコア18709

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

may_left

2016/05/31 02:51

正規表現にこだわっていましたが、パースしてしまえば確かに扱いが楽ですし colspan,rowspan以外の要素もってなった際に改修が楽そうですね。 ありがとうございます。
guest

0

もっとクレバーなやり方が有るとは思いますが、<td> を拾ってその中の必要な項目(rowspanとcolspan)を拾って結合することで実現できると思います。

PHP

1$body = preg_replace_callback( 2 '/<td[^>]*>/' 3 , function ( $tds ) { // PHP 5.3+ 4 preg_match_all( "/(\s(?:col|row)span=(?:\"[^\"]*\"|\'[^\']*\'))/i", $tds[ 0 ], $match ); 5 return '<td'.implode( '', $match[ 0 ] ).'>'; 6 } 7 , $body 8); 9echo $body;

投稿2016/05/30 12:14

kei344

総合スコア69364

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

may_left

2016/05/31 02:45

必要な物を抜出して、結合する。というやり方ですね。 頭から抜け落ちていたやり方でした。 ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問