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

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

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

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

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

正規表現

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

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

Q&A

解決済

5回答

2628閲覧

ルビの振られたHTMLからルビを無視して文字列をマッチさせたい

totomaru483838

総合スコア7

PHP

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

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

正規表現

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

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

0グッド

0クリップ

投稿2017/03/25 16:37

編集2017/03/30 00:32

###前提・実現したいこと
php か jQeury のどちらかで実現できる方法、もしくは両方で実現できる方法を探しています。

ルビのある文字文字列をハイライトしたいです。

サイトを運営しております。自身のサーバーにルビ情報を含んだテキストファイルがあり、それを php で読み込んで表示しております。

この文章に対して指定した部分をハイライトにしたいです。たとえば「腰を抜かしたことがある」の部分にハイライトを施すために以下のように書き換えたいです。

「腰を抜かしたことがある」の部分だけ取り出すとこう

html

1<span class=highlight></span></rb><rp></rp><rt>こし</rt><rp></rp></ruby><span class=highlight></span><ruby><rb><span class=highlight></span></rb><rp></rp><rt></rt><rp></rp></ruby><span class=highlight>かした事がある。</span>

ルビのふりがなと(かっこ)以外を highlight という名前の class で囲んでいます。

「腰を抜かしたことがある」の部分は自身の管理するデータベースに保存してあります。

###発生している問題

html

1</rb><rp></rp><rt>こし</rt><rp></rp></ruby><ruby><rb></rb><rp></rp><rt></rt><rp></rp></ruby>かした事がある。

上の文章(ルビ付きの文章)がデーターベースにあれば自分でもphp や jQuery の正規表現などで置換して span class で囲うことができます。しかし、データーベースにはルビが取り除かれた文章しかありません。

html

1腰を抜かしたことがある

正規表現をうまく使えばできるような気もするのですが、いい方法が思いつきません。
何かいいアイデアがあれば教えていただきたいです。

よろしくお願いします。

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

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

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

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

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

akabee

2017/03/25 16:47 編集

夏目漱石ですか。追記いただきたいのが、「手元」というのがどういうことかということです。私の感覚ですとHTMLの書き方が分かっているのであればそう書けばいいだけの話ではないかと思ってしまいます。どこに問題があるのか、もう少し具体的に書いていただけませんでしょうか。ハイライトを施したいのは、誰か他人のページで、そこに対して自分から手を加えてハイライトを加えたいのかな?などと想像しています。
totomaru483838

2017/03/25 18:29

はい、夏目漱石。言葉足らずで申し訳ございません。質問文章を見直しました。もし分かるようならばお願いします。
Zuishin

2017/03/25 23:26 編集

ハイライトしたい部分だけを収めた情報というのはどのような形で入っているのですか? ルビのない文章、そのルビ情報、ハイライト情報の三つが入力データですね? その三つを一組として、三組ほど提示お願いします。
Zuishin

2017/03/25 23:45

あと、例えば ABC という文字列があったとして、AB がハイライト指定、BC がルビ指定の場合、または AB がルビ指定、BC がハイライト指定の場合は ABC 全体をハイライトしてもいいのですか?
totomaru483838

2017/03/25 23:48

1 → ハイライトのない文章(ルビあり)。2 → ハイライトしたい箇所の文字情報(ルビなし)この二つの情報を持っています。2は1の一部分です。ですが1がルビありなのに対して、2はルビがないためマッチのさせ方が分からないという質問です。
Zuishin

2017/03/25 23:57

わかりました。説明だけいただいたので、こちらもアルゴリズムだけ。まず双方の文章からルビもハイライトもない文章を取り出します。そして、ルビとハイライトの位置を対応させます。例えば、ルビを 1、ハイライトを 2、どちらもあるものを 3 とし、「腰を抜かしたことがある」のうち、「腰」「抜」にルビが振られ、「腰を抜かした」までがハイライトだとすると、ルビハイライト情報は「3232200000」となります。3 の連続部分をルビとハイライトで囲み、2 の連続部分をハイライトで囲めば完成ですが、ルビを振る漢字が連続している場合があるので、この情報だけではなくルビ情報も参照します。以上です。
guest

回答5

0

考えてみました。

まず、検索対象のテキストだけ取り出します。だいたいこんなコードになると思います。

javascript

1var str = '<p><ruby><rb>親譲</rb><rp>(</rp><rt>おやゆず</rt><rp>)</rp></ruby>りの<ruby><rb>無鉄砲</rb><rp>(</rp><rt>むてっぽう</rt><rp>)</rp></ruby>で小供の時から損ばかりしている。...'; 2 3var skippedElements = Array('RP', 'RT'); 4var textNodes = Array(); 5function getTextNodes(node) { 6 if (node.nodeName && skippedElements.includes(node.nodeName.toUpperCase())) 7 ; 8 else if (node.nodeType === 1) 9 node.childNodes.forEach(function(e){getTextNodes(e)}); 10 else if (node.nodeType === 3) 11 textNodes.push(node); 12} 13 14var nodes = $.parseHTML(str); 15nodes.forEach(function(node){ 16 getTextNodes(node); 17}); 18 19var text = textNodes.map(function(node){node.nodeValue}).join('');

検索対象になるテキストがtextに、それに対応するDOMのテキストノードの配列がtextNodesに入っています。概念的に書くと、つぎのようになっているはずです。

textNodes = [Text("親譲"), Text("りの"), Text("無鉄砲"), Text("で小供の時から損ばかりしている。...")]; text = "親譲りの無鉄砲で小供の時から損ばかりしている。...";

なお、上でTextで示したオブジェクトは、元の文書に含まれるテキストノードそのものです (javascriptのメソッドではありません)。

ここからは具体的なコードは書きませんが、次のようにすればいいと思います。

"損ばかり"を見つけてハイライトしたいとします。textでこの文字列を探すと、14番目の文字 (最初を0番目とする) から始まる4文字が一致します。

textNodesの要素を最初から順に見ていくと、文字数が2、2、3、…ですから、全体で14番目の文字は、3番目 (最初を0番目とする) の要素の7番目の文字です (14 - (2 + 2 + 3))。

そこで、テキストノードを次のような複数のノードで置換します。

投稿2017/03/26 07:30

編集2017/03/26 10:40
ikedas

総合スコア4354

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

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

0

課題

技術的には可能ですが、要件だけ出して「教えてください」といえる難易度の問題ではないように思います。

  1. <span>あいう</span><span>えお</span> に対して検索語「あいうえお」がマッチしなければならない(MUST)
  2. <span>あいう</span><span>えお</span> に対して検索語「うえ」がマッチしなければならない(MUST)
  3. <span title="すくりぷと">Script</span> に対して検索語「すくりぷと」がマッチしてはならない(MUST NOT)
  4. <h1>サンプル</h1><p>これはテストです。</p> に対して「検索語「サンプルこれはテストです。」がマッチしてはならない(MUST NOT)

上記例題は次のDOMを出力する事を期待します。

  1. <span><mark class="highlight">あいう</mark></span><span><mark class="highlight">えお</mark></span> もしくは <mark class="highlight"><span>あいう</span><span>えお</span></mark>
  2. <span>あい<mark class="highlight">う</mark></span><span><mark class="highlight">え</mark>お</span>
  3. マッチしない
  4. マッチしない

※1. は後者がすっきりしていますが、2. の処理を入れることを踏まえると前者の方がコードを書きやすいかもしれません。

実装案

正規表現でタグの対応関係、インラインボックスのタグだけ抽出する実装は複雑化してしまいます。
以下にDOM API で実装する手順を書きます。

  1. document.evaluate で検索語の1文字目となるテキストノードを検索(参考: https://teratail.com/questions/31198)
  2. テキストノード内の文字列を1文字ずつ検索し、テキストノード内に検索語の前方一致語区を発見したら、createElement で mark 要素を生成し、appendChild でテキストノードを挿入後に replaceChild で置換する
  3. テキストノード内に検索語が部分一致で見つかったら処理を終了し、前方一致で見つかったら 4. へ進む
  4. element.parentNode で親要素を参照し、computedStyledisplay プロパティが inline もしくは inline-block の場合に 5. へ進み、そうでないなら終了する
  5. element.nextSibling が存在しないなら 4.へ戻り、存在するなら element.nextSibling を参照して 6. へ進む
  6. element.nodeType がテキストノードならまだマッチしていない検索語を対象にして 3. へ戻り、要素ノードなら 7. へ進む
  7. element.firstChildnodeType がテキストノードになるまで firstChild を参照し続け、テキストノードを発見したら 6. へ戻り、 firstChildnull になるまで参照し続けたら終了する

コメントノードの読み飛ばし等、細かな例外処理はありますが、大まかにはこんな流れで実装可能だと思います。

Re: totomaru483838 さん

投稿2017/03/26 03:09

編集2017/03/26 03:51
think49

総合スコア18166

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

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

0

アイデアだけを記述します

HTMLタグなし文字列 -> ハイライト文章置換 -> ルビ文字置換 して完成させる方法です

A: 置換作業用に ルビ対象文字 と <ruby>タグ文字列 の取得
0. オリジナルのHTMLから正規表現を使って <ruby>タグ文字列 を取得する
0. <ruby>タグ文字列 から正規表現を使って <rb>タグ内の ルビ対象文字 を取得する

B: ハイライト文章・ルビ対象文字 の置換
0. オリジナルHTMLから タグを取り除いた文字列 を取得する
0. タグを取り除いた文字列 の中の ハイライト文章を <span class="highlight">ハイライト文章</span> で置換する
0. さらに ルビ対象文字 を <ruby>タグ文字列 で置換する

投稿2017/03/26 01:01

編集2017/03/26 01:03
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

0

追記ありがとうございます。
内容確認しましたが、現状の情報だけでは実現は難しいと思います。
つまり「ハイライトしたい文字列」を「HTMLタグ単位」でプログラム側で把握する必要があります。

「ハイライトしたい部分だけを収めた情報」は自身で管理しているデータベースに格納されているということですが、それを変更することは可能ですか?
私なら、「ハイライトしたい部分だけを収めた情報」のデータ構造を見直します。

具体的には、

1.「ルビはあるけどハイライトのない文章」の行番号を持たせる
2.「HTMLタグ単位」でハイライトしたい単語ごとに分割する

というようなことをします。

以下のような感じですね。

【ルビはあるけどハイライトのない文章】(ルビを<>で記載)

親譲<おやゆず>りの無鉄砲<むてっぽう>で小供の時から損ばかりしている。
小学校に居る時分<じぶん>学校の二階から飛び降りて一週間ほど腰<こし>を抜かした事がある。

【自身のデータベースに存在するデータ】

1/親譲
1/無鉄砲
2/時分
2/腰

これで、プログラム側で「ルビはあるけどハイライトのない文章」のうちどの文字列をハイライトすれば良いかが分かります。
あとはコーディングすることになりますが、すみません、具体的なコードは提示できないのですが手順としてはたとえば以下のようになるかと思います。

1.「ルビはあるけどハイライトのない文章」を1行読み込む
2.1のとき、「現在の行番号」をカウントしてプログラム側で行数を把握する。
3.「自身のデータベースに存在するデータ」のうち2に該当する行番号に関する部分のみを読み込み、ハイライトすべき箇所を把握する(1行目であれば「親譲」、「無鉄砲」のみを読み込む)
4.1で読み込んだ文章のうち、3で把握した箇所をハイライトするよう変更する

というようなイメージになると思います。
回答になっていますでしょうか・・・。

投稿2017/03/26 06:13

akabee

総合スコア1947

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

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

0

ベストアンサー

こういうことでしょうか?

CSS

1rb { 2 background-color: rgba(255, 200, 190, 0.3); 3 color: red; 4 padding: 0.7em 0.5em 0.2em; 5}

HTML

1<p><ruby><rb>親譲</rb><rp>(</rp><rt>おやゆず</rt><rp>)</rp></ruby>りの<ruby><rb>無鉄砲</rb><rp>(</rp><rt>むてっぽう</rt><rp>)</rp></ruby>で小供の時から損ばかりしている。小学校に居る時分学校の二階から飛び降りて一週間ほど<ruby><rb><span class=highlight>腰</span></rb><rp>(</rp><rt>こし</rt><rp>)</rp></ruby><span class=highlight>を</span><ruby><rb><span class=highlight>抜</span></rb><rp>(</rp><rt>ぬ</rt><rp>)</rp></ruby><span class=highlight>かした事がある。</span>なぜそんな<ruby><rb>無闇</rb><rp>(</rp><rt>むやみ</rt><rp>)</rp></ruby>をしたと聞く人があるかも知れぬ。</p> 2```**動くサンプル:**[https://jsfiddle.net/xgjv9ttf/](https://jsfiddle.net/xgjv9ttf/)

投稿2017/03/25 16:53

kei344

総合スコア69444

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

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

totomaru483838

2017/03/25 18:30

ご回答ありがとうございます。質問が言葉足らずだったので追記しました。質問内容を勘違いさせてしまい申し訳ございません。
kei344

2017/03/25 18:55 編集

「ルビのある文字文字列をハイライトしたい」ではなく「ルビの振られたHTMLからルビを無視して文字列をマッチさせたい」とかかなぁ、日本語って難しい。 「ハイライト」の対象は例えば「譲り」のようにルビの途中から始まるものもありますか? また、同じ文字列が来たら全てハイライト対象にするのでしょうか。
totomaru483838

2017/03/25 22:03

「譲り」のようにルビの途中から始まるものもあります。 同じ文字列が来た場合、すべてハイライトしてもいいですし、最初の一か所だけハイライトでも構いません。実現しやすいほうを採用したいと思っています。
totomaru483838

2017/03/25 22:06

タイトル案を採用させていただきました。ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問