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

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

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

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

正規表現

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

Q&A

解決済

3回答

2458閲覧

「PHP 正規表現」特定タグコードの置き換え、修正方法

KazukiF

総合スコア12

PHP

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

正規表現

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

0グッド

0クリップ

投稿2016/08/23 06:16

編集2016/08/23 06:19

以下のコードを修正、表示したいと思っているのですが私には難解すぎて困っています。

現在PHPで作成したRSSを配信しているのですが、その中で、もともとあるコードを加工したいと思っています。

(例)
▼現
<img class="aa bb cc etc" src="https://hogehoeg.com/○○○.jpg" alt="○○○" width="○○○" height="○○○" />出典:https://△△△.com

▼改

<figure><img src="https://hogehoeg.com/○○○.jpg" alt="○○○" /><figcaption>出典:https://△△△.com</figcaption></figure>

上記現から改のように、imgタグのsrcとaltのみを残したまま<figure>内に入れ込み、かつ「出典」部分のテキストのみを<figcaption>内に入れ込むという正規表現、置き換え方法をご教示いただければ幸いです。

なお、出典直後の「:」は全角(:)と半角(:)の場合があります。

img直後は必ず「出典」文字列が付与されていますが改行タグやスペースが入っていることもあります。

preg_replaceをあれこれ試してみたものの見当違いな結果を連発し、困っていたところたどり着きました。

不足情報などありましたらお答えしますので何卒どうぞよろしくお願い致します。

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

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

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

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

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

kunai

2016/08/23 06:23

そのあれこれ試してみた事を書いていただけませんか。
guest

回答3

0

正規表現版 (変更に弱いですが,決め打ちであればこれで十分です)

php

1<?php 2 3$content = <<<EOD 4<img class="aa bb cc etc" src="https://hogehoeg.com/○○○.jpg" alt="○○○" width="○○○" height="○○○" />出典:https://△△△.com 5<img class="aa bb cc etc" src="https://hogehoeg.com/○○○.jpg" alt='xx oo' width="○○○" height="○○○" />出典:https://△△△.com 6<img class="aa bb cc etc" src="https://hogehoeg.com/○○○.jpg" width="○○○" height="○○○" />出典:https://△△△.com 7EOD; 8 9echo preg_replace_callback( 10 '@<img( class="aa bb cc etc".*?) />\s*+([^\s<]*+)@s', 11 function ($m) { 12 $m[1] = preg_replace('@ 13 \s*+(?: 14 (?:src|alt)(*SKIP)(*FAIL)|[\w-]++ 15 )=(?:"[^"]*+"|\'[^\']*+\') 16 @x', '', $m[1]); 17 return "<figure><img$m[1]><figcaption>$m[2]</figcaption></figure>"; 18 }, 19 $content 20);
DOM版 (細かい差異に依存しないので変更により強いです)

(ただしインデントが崩れたり一部文字がHTMLエンティティに置換されてしまうなど,少し弊害があります…)

php

1<?php 2 3// 何かこれらを括っている親要素があると仮定 (もしなければ付加してください) 4$content = <<<EOD 5<root> 6 <img class="aa bb cc etc" src="https://hogehoeg.com/○○○.jpg" alt="○○○" width="○○○" height="○○○" />出典:https://△△△.com 7 <img class="aa bb cc etc" src="https://hogehoeg.com/○○○.jpg" alt='xx oo' width="○○○" height="○○○" />出典:https://△△△.com 8 <img class="aa bb cc etc" src="https://hogehoeg.com/○○○.jpg" width="○○○" height="○○○" />出典:https://△△△.com 9</root> 10EOD; 11 12$dom = new DOMDocument; 13libxml_use_internal_errors(true); 14$dom->loadHTML( 15 mb_convert_encoding($content, 'HTML-ENTITIES', 'UTF-8'), 16 LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD 17); 18libxml_clear_errors(); 19$xpath = new DOMXPath($dom); 20 21foreach ($xpath->query('//img[@class="aa bb cc etc"]') as $i => $node) { 22 23 foreach ($xpath->query('./@*[not(name()="src")][not(name()="alt")]', $node) as $attr) { 24 $node->removeAttribute($attr->name); 25 } 26 27 if ($textnode = $node->nextSibling and $textnode->nodeType === XML_TEXT_NODE) { 28 $node->parentNode->removeChild($textnode); 29 } else { 30 $textnode = $dom->createTextNode(''); 31 } 32 33 $figure = $dom->createElement('figure'); 34 $node->parentNode->replaceChild($figure, $node); 35 $figure->appendChild($node); 36 37 $figcaption = $dom->createElement('figcaption', trim($textnode->nodeValue) ?: 'タイトル無し'); 38 $figure->appendChild($figcaption); 39 40} 41 42$result = $dom->saveXML($dom->documentElement); 43echo $result; 44 45// もし最初に親要素を付加したならば,後からそれを除外してください 46// $result = substr($dom->saveXML($dom->documentElement), 6, -7);

投稿2016/08/23 08:26

編集2016/08/24 09:36
mpyw

総合スコア5223

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

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

mpyw

2016/08/23 08:27

ちょっと微妙に違っていたので訂正します…
mpyw

2016/08/23 08:48

テキストノードが削除できなくて苦戦中… もとのRSSがXMLではなくてHTMLなのでちょっときついかな… (正規表現のほうが良さそうです)
mpyw

2016/08/23 09:03

一応動作する形にはなりました
KazukiF

2016/08/24 02:57

いろいろなパターンをありがとうございます!伝え方が悪く申し訳有りませんが、imgと出典の間には何かスペースがあったため解決に至っておりません。(あとで気づきました)その場合に何か違う記載方法があればご教授いただければ幸いです。。
mpyw

2016/08/24 09:13

その間の部分に \s*+ というパターンを入れるだけです.修正しておきます.
mpyw

2016/08/24 09:15 編集

ちなみにDOM版にはこういう「スペースが入った」などの影響を全く受けない強みがあります.正規表現が「変更に弱い」とはこういうことです.
mpyw

2016/08/24 09:21

正規表現の難解な部分について補足しておきます.汎用的な正規表現というよりPCREの独自機能ですが… http://stackoverflow.com/questions/24534782/how-do-skip-or-f-work-on-regex このテクニックを使うと,後ろにマッチさせるもののうち特定のものを前で除外しておくことができます.今回は全ての属性の中からsrcとaltだけを除外して置換しないようにしています.
KazukiF

2016/08/25 06:27

ご丁寧にありがとうございました。動作がうまくいき、かなり悩んでましたのでただただ感謝の気持ちでいっぱいです。勉強になりました、またなにかございましたらよろしくお願いします。
guest

0

ベストアンサー

simplexml_load_string()あたりでやるほうが良い気もしますが
あえて正規表現で

PHP

1<?PHP 2$content=<<<eof 3<img class="aa bb cc etc" src="https://hogehoeg.com/○○○.jpg" alt="○○○" width="○○○" height="○○○" />出典:https://△△△.com 4<img class="aa bb cc etc" src="https://hogehoeg.com/○○○.jpg" alt='xx oo' width="○○○" height="○○○" />出典:https://△△△.com 5<img class="aa bb cc etc" src="https://hogehoeg.com/○○○.jpg" width="○○○" height="○○○" />出典:https://△△△.com 6eof; 7 8$pattern="/(<img) (.*?)>(出典.*)$/m"; 9$replacement=function($a){ 10 $str="<figure>".$a[1]; 11 $pattern="/(?:src|alt)=([\"']).*?\\1/"; 12 if(preg_match_all($pattern,$a[2],$matches)){ 13 foreach($matches[0] as $val){ 14 $str.=" ".$val; 15 } 16 } 17 $str.="/>"; 18 $str.="<figcaption>".$a[3]."</figcaption></figure>"; 19 return $str; 20}; 21$content=preg_replace_callback($pattern,$replacement,$content); 22print htmlspecialchars($content); 23?>

修正版

「出典」の前に半角スペースやタブが入っている可能性がある場合は
「\s*」=0個以上のスペース文字をヒットさせてください

PHP

1$pattern="/(<img) (.*?)>\s*(出典[^\n\r]*)/m";

元ソースだとm修飾子を使うと改行文字を拾っちゃうみたいなので
出典以降改行文字がでてくるまでに変えておきました。

投稿2016/08/23 07:50

編集2016/08/24 03:20
yambejp

総合スコア114837

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

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

KazukiF

2016/08/24 02:52

発想がすごいですね、ただただ未熟さを痛感しております。 惜しいところまで行ってそうなのですが、 <figure><img src="https://abcabc.jpg" alt=""/><figcaption> </figcaption></figure> 出典:http://www.xyzxyz.com/ とfigcaptionの中に出典:http://www.xyzxyz.com/を入れ込むことができません。 要因としては、お伝えできていなかったのですが、imgタグの終了地点と出典文字列の間に何かスペースがあり、それが原因かと思っております。 その場合、 $pattern="/(<img) (.*?)>(出典.*)$/m"; の部分でどういった書き方をすればよろしいでしょうか? 申し訳有りませんがお知恵を拝借できれば幸いです!
yambejp

2016/08/24 03:22

修正箇所を追記しておきました なにか仕様がちがったり、動作が想定と違うようであれば再度指示ください
KazukiF

2016/08/24 05:15

お世話になります、動作しました、ありがとうございます! 本当にどうもありがとうございました。 初めてなのですが、ベウトアンサーを差し上げたら完了扱いでよろしいのでしょうか?
guest

0

とりあえずチャレンジしてみました。

<?php $org = '<img class="aa bb cc etc" src="https://hogehoeg.com/xxx.jpg" alt="あああ" width="xxx" height="xxx" />出典:https://xxx.yyy.com'; echo $org. "\n"; echo preg_replace('/(<img.*)width.*\/>(.*$)/u', '<figure>\\1/><figcaption>\\2</figcaption></figure>', $org);

投稿2016/08/23 09:20

編集2016/08/23 09:26
nullbot

総合スコア910

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問