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

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

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

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

正規表現

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

Q&A

解決済

1回答

1058閲覧

php・正規表現で特定文字列をリンク化したい(すでに<a>タグで囲われているときは除く)

glaxel

総合スコア8

PHP

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

正規表現

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

0グッド

1クリップ

投稿2021/07/15 08:00

phpにて、htmlのタグを含むある文章中の中で、特定文字列をリンク化したいのですが、その文字列がすでに<a>タグで囲われている場合は除外をしたいと考えています。

例えば、もとの文章を

html

1<p>木曾路はすべて山の中である。</p> 2 3<p>あるところは岨づたいに行く崖の道であり、 4 あるところは<a href="#url1" target="_blank">数十間の深さに臨む木曾川の岸</a>であり、 5 あるところは山の尾をめぐる谷の入り口である。</p> 6 7<p>一筋の街道はこの深い森林地帯を貫いていた。東ざかいの桜沢から、 8 西の十曲峠まで、<a href="#url1">木曾</a>十一宿はこの街道に添うて、 9 二十二里余にわたる長い谿谷の間に散在していた。 10 <a href="#url1">道路</a>の位置も幾たびか改まったもので、 11 古道はいつのまにか深い山間に埋もれた。</p>

として、

上記文章中の「木曾」を、すべてリンク化、
ただしすでに「木曾」を含む<a>タグは無視し、

html

1<p><a href="#url2">木曾</a>路はすべて山の中である。</p> 2 3<p>あるところは岨づたいに行く崖の道であり、 4 あるところは<a href="#url1" target="_blank">数十間の深さに臨む木曾川の岸</a>であり、 5 あるところは山の尾をめぐる谷の入り口である。</p> 6 7<p>一筋の街道はこの深い森林地帯を貫いていた。東ざかいの桜沢から、 8 西の十曲峠まで、<a href="#url1">木曾</a>十一宿はこの街道に添うて、 9 二十二里余にわたる長い谿谷の間に散在していた。 10 <a href="#url1">道路</a>の位置も幾たびか改まったもので、 11 古道はいつのまにか深い山間に埋もれた。</p>

のようにしたいです。
※すでに「木曾」を含む<a>タグは、「木曾」以外の文字列を含む可能性もあります

また、もし可能であれば、さきほどと反対に
すでに「木曾」を含む<a>タグのリンク先のみ置換する。

といったこともできると理想です。

正規表現を使わずに実現できるのであれば、
それでもかまいません。

何卒お力をお貸しいただけますと幸いです。
よろしくお願いいたします。

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

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

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

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

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

guest

回答1

0

ベストアンサー

たとえば

html

1<img src="・・・" alt="木曾">

のようなタグ内の属性として与えられる可能性もあるので
PHPでやるならDOMDocumentで処理してください

sample

PHP

1<form> 2キーワード:<input name="keyword"><br> 3URL:<input name="url" value="#url2"><br> 4<input type="submit" value="send"><br> 5</form> 6<hr> 7<?PHP 8mb_internal_encoding("UTF-8"); 9$html=<<<eof 10<p>木曾路はすべて山の中である。</p> 11 12<p>あるところは岨づたいに行く崖の道であり、 13 あるところは<a href="#url1" target="_blank">数十間の深さに臨む木曾川の岸</a>であり、 14 あるところは山の尾をめぐる谷の入り口である。</p> 15 16<p>一筋の街道はこの深い森林地帯を貫いていた。東ざかいの桜沢から、 17 西の十曲峠まで、<a href="#url1">木曾</a>十一宿はこの街道に添うて、 18 二十二里余にわたる長い谿谷の間に散在していた。 19 <a href="#url1">道路</a>の位置も幾たびか改まったもので、 20 古道はいつのまにか深い山間に埋もれた。</p> 21eof; 22$keyword=filter_input(INPUT_GET,"keyword"); 23$pattern="/".preg_quote($keyword,"/")."/"; 24$url=filter_input(INPUT_GET,"url"); 25 26$doc=new DOMDocument(); 27$doc->loadHTML("<meta http-equiv='Content-Type' content='text/html; charset=UTF-8' />\n".$html); 28$body=$doc->getElementsByTagName("body")[0]; 29if($keyword){ 30 foreach($body->getElementsByTagName("*") as $nodes){ 31 for($i=$nodes->childNodes->length-1;$i>=0;$i--){ 32 $node=$nodes->childNodes[$i]; 33 if($node->nodeType=="3" and $node->parentNode->tagName!=="a" and preg_match($pattern,$node->nodeValue)){ 34 $v=$node->nodeValue; 35 $newElements=[]; 36 foreach(preg_split($pattern,$v) as $key=>$n){ 37 if($key>0){ 38 $a=$doc->createElement('a'); 39 $a->setAttribute("href",$url); 40 $a->textContent=$keyword; 41 $newElements[]=$a; 42 } 43 $t=$doc->createTextNode($n); 44 $newElements[]=$t; 45 } 46 foreach($newElements as $n){ 47 $node->parentNode->insertBefore($n,$node); 48 } 49 $node->parentNode->removeChild($node); 50 } 51 } 52 } 53} 54foreach($body->childNodes as $node){ 55 print $doc->saveHTML($node); 56}

投稿2021/07/16 01:06

編集2021/07/16 03:59
yambejp

総合スコア116724

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

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

yambejp

2021/07/16 03:56

もうちょいなんとかなりそうな気はしますがsample上げておきます
glaxel

2021/07/16 04:34

確かにそのようなケースもありますね...。まったく想定できておりませんでした。 ご丁寧にサンプルもご提示いただきありがとうございます! いただいたサンプルをもとに学習をしてみます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問