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

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

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

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

正規表現

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

Q&A

解決済

2回答

2842閲覧

rubyでhtmlのタグ内にあるclassの文字列を削除する方法を教えてください

nasum

総合スコア64

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

正規表現

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

0グッド

0クリップ

投稿2015/02/24 06:35

編集2015/02/24 06:35

Rubyを用いてhtmlのタグが書かれている文書を整形するとき、タグのclass名にNGワードが入っていたらそれを削除する機能をつけたいのですが、どういう正規表現で削除すればいいのかわかりませんでした。

文書には以下のようなタグが含まれているとします。

lang

1<div class="XXX ngword-1"></div> 2<div class="ngword-2 XXX"></div> 3<div class="XXX ngword-1 ngword-2"></div>

この文書を

lang

1<div class="XXX"></div> 2<div class="XXX"></div> 3<div class="XXX"></div>

のようにngword-1とngword-2を削除したいと思っています。

正規表現でやればよいと考えてはいますが、もしそれ以外の方法で可能であればそれを教えていただけると幸いです。またNGワードの削除が目的なので、最悪スペースが残っていてもかまいません。

よろしくお願いします。

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

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

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

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

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

guest

回答2

0

ベストアンサー

正規表現で手を付けようとしましたが、諦めました。非常に面倒だからです。
正規表現を作る方針をこのページの HTML を例にしてみます。
このようなタグがありました。

lang

1<button title="クリップすると、知りたい質問を追いかけることができます。" class="btnUnderstandWant js-addClip mod-icn btnAddClip" value="1" 2 type="image" key="7140">クリップ</button>

というタグがありました。
正規表現を作る方針ですが、「タグ内の class 属性内の NG ワードを削除する」ので、まずタグを見つける正規表現を作ります。そしてその中で class 属性を見つけます。さらに class 属性の内容を抜き出します。
HTML ですから class 属性の位置はタグ内のどこでも任意に決められますのでそれまでの部分の属性名・属性値は飛ばさなきゃいけませんし、その部分には漢字を含めハイフン・コロン・セミコロン・ピリオドなどを含め色々な文字が含まれています。また class 属性の属性値を指定する文字はシングルクオートであったりダブルクオートであったりする可能性があります。そしてシングルクオートやダブルクオートがエスケープされていたりしたら、もう目も当てられません。

つまり、 HTML の自由度のせいで、正規表現が非常に面倒になります。そして、場合によっては上記の例のようにタグ途中で改行されていたりすることもあります。

結論としては「書けますが面倒」です。 nokogiri などの HTML/XML パーサを使ってください。
もちろん、前提条件がお示しのタグぐらい統一されていて簡略であれば簡単ですけどね。
(もしも、対象となるタグの前提条件が明確になっているならば、それに合わせた程度で書くこともできますので、ご連絡ください。ただし、結果として正規表現が面倒になりそうであれば、その旨ご返答します。)


nokogiri でのパース方法を追記します。
タグが一つだけであることを前提としています(修正すれば複数タグでも扱えますので、必要があればやってみてください)。

lang

1ng_words = %w[ngword-1 ngword-2] 2str = %[<div class="XXX ngword-1 ngword-2"></div>] 3 4elem = Nokogiri::HTML.parse(str).xpath('/html/body/*').first 5classes = elem[:class].split 6classes -= ng_words 7elem[:class] = classes.join(" ") 8tag = elem.to_html 9puts tag #=> <div class="XXX"></div>

NG ワードは配列に入れておきます。
タグは Nokogiri::HTML.parse すると html タグと body タグにラップされるので、 xpath('/html/body/*') メソッドでラップを剥がして目的とするタグのみを含むインスタンス elem を抜き出します(div タグに限らず、どのようなタグでも使えるように書いています)。
続いて class 属性値を抜き出して文字列そして配列にし、 NG ワードを取り除いてから文字列に戻し、再度 class 属性値に設定しています。
あとは to_html メソッドで戻せばいいだけです。

投稿2015/02/24 09:55

編集2015/02/24 13:59
riocampos

総合スコア241

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

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

nasum

2015/02/24 10:05

コメントありがとうございます。 やはり正規表現でやるのは難しそうですね。いろいろ調べていただいたようで頭が下がります。 入力されるHTMLタグはユーザに入力してもらうもののため例に示したような簡単なものにはなりません。ここはやはりHTMLパーサを使う方向で行こうかと思います。 回答ありがとうございました。
riocampos

2015/02/24 13:56

nokogiri でのパース方法を追記しました。
guest

0

HTMLを正規表現で処理するのは面倒ですし、イレギュラーなケースでおかしな挙動をすることも考えられます。

Nokogiriのような、HTMLを処理するライブラリがありますので、そういうのを使ったほうがいいでしょう。

投稿2015/02/24 07:20

maisumakun

総合スコア145184

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

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

nasum

2015/02/24 08:08

素のHTMLならNokogiriが一番なんですが、問題なのは文書中にHTMLがあってその中のclassをいじりたいということなんです。 ちょっと質問が説明不足でした、すみません。 nokogiriでもうまくいけばよさそうです。ただHTML化する過程でDOCTYPEなどが追加されているのでそれをうまく削除できれば何とかなりそうな気がします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問