文字列で処理するなら考え方としてはチェックするのは
「<a\s」ではじまる文字列の「>」までの間だけでよいでしょう。
あとは条件次第
- targetがないものは付加するだけ
- targetがあるものはどうする?targetをはずして新たに_blankをつける?
- targetがある場合の例外はどこまで対応する必要があるか
たとえば、
HTML
1<a href="hoge.htm" data-dummy="target='_blank'">hoge</a>
のようなものが文字列でのチェックだと引っかかる
また、既存のtargetが
<a href="fuga.htm" TarGet = '_BlanK' data-hoge="fuga<fuga>fuga">fuga</a>
のように大文字小文字混じりだったり、スペースがはいっていたり
本来小文字指定の「_blank」が不適当な大文字化していたり
本来のタグ終端子である「>」が途中で文字列として出現したり
どこまでフォローすべきかです。
そういうの煩わしさを防ぐのがDOMとしての処理です
sample
文字列での検証は例外が多すぎるためかなり困難であることはすでにお伝えしたとおりですが
逆に言えば極端に変なタグ設定をしていなければ以下で大丈夫だとおもいます
- まずはaタグを拾う
- aタグの中身を検証して書き換える
PHP
1<?PHP
2$str=<<<eof
3(1)test<a href="hoge.htm">hoge1</a>test<br>
4(2)test<a href="hoge.htm" target="fuga">hoge2</a>test<br>
5(3)test<a href="hoge.htm" data-target="fuga">hoge3</a>test<br>
6(4)test<a class="hoge target" href="hoge.htm">hoge4</a>test<br>
7eof;
8
9$pattern1="/(?<=<a\s).*?(?=>)/";
10$replacement=function($x){
11 $ret=$x[0];
12 if(!preg_match("/(?<=\s)target/i",$x[0],$m)){
13 $ret.=' target="_blank"';
14 }
15 return $ret;
16};
17$str=preg_replace_callback($pattern1,$replacement,$str);
18print "<pre>";
19print htmlspecialchars($str);
20print "</pre>";
※上記(4)はNGです
追記
よくよく考えたら正規表現でaタグをひろったあと
callbackの中でdom処理をしてもいいかもしれません
PHP
1$str=<<<eof
2(1)test<a href="hoge.htm">hoge1</a>test<br>
3(2)test<a href="hoge.htm" target="fuga">hoge2</a>test<br>
4(3)test<a href="hoge.htm" data-target="fuga">hoge3</a>test<br>
5(4)test<a class="hoge target" href="hoge.htm">hoge4</a>test<br>
6eof;
7
8$pattern="/<a\s.*?</a>/";
9$replacement=function($x){
10 $doc=new DOMDocument();
11 $doc->loadHTML($x[0]);
12 $node=$doc->getElementsByTagName("a")[0];
13 $target=$node->getAttribute("target");
14 if(empty($target)) $node->setAttribute("target","_blank");
15 return $doc->saveXML($node);
16};
17$str=preg_replace_callback($pattern,$replacement,$str);
18print "<pre>";
19print htmlspecialchars($str);
20print "</pre>";
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/02/20 14:41
2018/02/20 22:38