• ベストアンサー

メタキャラクタのエスケープについて

がんばって調べているんですが、わからないので質問します。 HTMLでのメタキャラクタ(「<」「>」「&」「"」など)を エスケープしたいんですが、うまくいきません。 試した内容は、こんな感じです。 Stringクラスのreplace(char oldChar, char newChar) を使えば、上手くいくかなと思ったのですが、文字列の 長さが変わってしまう為、使えませんでした。 1文字と1文字の変換だとうまく行くのですが、今回の 場合、1文字を4文字に変換したい為、使えません^^; < → &lt; 次に考えたのが、文字列のバッファの長さを増やせる Stringbufferクラスの replace(int start, int end, String str) だと、位置を指定しなければならなくて、どうやったら 良いのかわかりません。 みなさん、どのようにしているのでしょうか? 考え方、サンプルなどありましたら、アドバイスお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • a-kuma
  • ベストアンサー率50% (1122/2211)
回答No.1

> Stringbufferクラスの > replace(int start, int end, String str) > だと、位置を指定しなければならなくて、どうやったら > 良いのかわかりません。 位置は探してゆけば良いですね。例えば、こんな感じ。 StringBuffer buf = new StringBuffer(対象の文字列); for (int i = 0 ; i < buf.length() ; ++i) {  if ( buf.charAt(i) == '<' ) {   buf.replace(i, i+1, "&lt;");   i += 3;  } } もっとスマートな解が在りそうな気がするので、自信無しとして置きます (^^; 標準の範囲を超えてしまいますが、参考URLのようなライブラリを使えればメソッド一発ですね。

参考URL:
http://www.ingrid.org/jajakarta/regexp/jakarta-regexp-1.2/doc-jp/api/org/apache/regexp/RE.html
HELPMAN
質問者

お礼

補足部分で、足りない部分と、間違いがあったので、 お礼に書かせてもらいます。 あわてんぼうで、すいません^^; String str = "<script>test</script>犬&猫<a href=\"http://www.aaa.com\">AAAA</a>"; StringBuffer sb = new StringBuffer(str); try{  for(int i = 0 ; i < sb.length() ; ++i){   if(sb.charAt(i)=='<'){    sb.replace(i, i+1,"&lt;");    i+=3;   }   if(sb.charAt(i)=='>'){    sb.replace(i, i+1,"&gt;");    i+=3;   }   if(sb.charAt(i)=='&'){    sb.replace(i, i+1,"&amp;");    i+=4;   }   if(sb.charAt(i)=='\''){    sb.replace(i, i+1,"&apos;");    i+=5;   }   if(sb.charAt(i)=='\"'){    sb.replace(i, i+1,"&quot;");    i+=5;   }  } }catch(IndexOutOfBoundsException ex){ }

HELPMAN
質問者

補足

素早いご回答ありがとうございます。 考え方がすごいわかりやすかったです。 そして、さらに質問になりますが、「i+=3」の部分 なんですが、「&lt;」って4文字なんで、「i+=4」 にならないのでしょうか? 微妙に混乱しています^^; また、色々なメタキャラクタをエスケープするように 作ってみました。現在、「クロスサイトスクリプティング」に ついて対策を考えているのですが、ひとつわからない事が あります。 「<」「>」「&」「"」の四つの文字については、 エスケープに成功しました。しかし、「'」(シングル クォーテーション)だけは、エスケープできません。 画面に「&apos;」と出てしまいます。(IE5.5で確認) シングルクォーテーションのエスケープの仕方が間違って いるんでしょうか? それとも、シングルクォーテーションは、普通エスケープ しないのでしょうか? クロスサイトスクリプティングの場合は、シングルクォーテーション は、エスケープしなくても良いのでしょうか? かなりたくさん、質問となってしまいますので、ご存知 の部分だけでもわかりましたら、よろしくお願いします。 あと、作成したソースを載せますので、書き方などの 注意もありましたら、よろしくお願いします。 try{ for(int i = 0 ; i < sb.length() ; ++i){ if(sb.charAt(i)=='<'){ sb.replace(i, i+1,"&lt;"); i+=3; } if(sb.charAt(i)=='>'){ sb.replace(i, i+1,"&gt;"); i+=3; } if(sb.charAt(i)=='&'){ sb.replace(i, i+1,"&amp;"); i+=4; } if(sb.charAt(i)=='\''){ sb.replace(i, i+1,"&apos;"); i+=5; } if(sb.charAt(i)=='<'){ sb.replace(i, i+1,"&quot;"); i+=5; } } }catch(IndexOutOfBoundsException ioobe){ }

その他の回答 (2)

noname#16216
noname#16216
回答No.3

個人的にHTMLタグを変換する機会が多いので、以下のような関数を 持ったクラスを作って利用してます。 単純にif~elseになるべきところを、switchを使っているだけですが。。。 static public String replaceTag(String argOriginalStr) {  StringBuffer returnStr = new StringBuffer();  for (int i = 0; i < argOriginalStr.length(); i++) {   char ch = argOriginalStr.charAt(i);    switch(ch) {     case '<':      returnStr.append("&lt;");      break;     case '>':      returnStr.append("&gt;");      break;     default:      returnStr.append(ch);      break;    }   }   return new String(returnStr);  }

HELPMAN
質問者

お礼

ご回答ありがとうございます。 switchで条件分岐するやり方もありましたね! ほんと、勉強になります。 if文は、結構使用しますが、switch文は、if文に 比べると使用頻度が少なく思います。 ちょっと忘れ気味でした。

  • a-kuma
  • ベストアンサー率50% (1122/2211)
回答No.2

> そして、さらに質問になりますが、「i+=3」の部分 > なんですが、「&lt;」って4文字なんで、「i+=4」 > にならないのでしょうか? for() で +1 されるので、+=3 としています。考え方は4文字だから4増やすで良いです。 > しかし、「'」(シングル > クォーテーション)だけは、エスケープできません。 「お礼」にあったソースで良いと思いますけどね。シングルクォートもきちんと変換できますよね。 ただ、StringBuffer#replace() で置換した後の i を増やすところでは、";" を指しているので、 if の連続ではなく、if ~ else if と続けた方が良いかも。これでも大丈夫ですけど。

HELPMAN
質問者

お礼

またまた、回答ありがとうございます。 >for() で +1 されるので、+=3 としています。 あっ!なるほどです。 合計4増えるんですね。 一人で考えてたら、+=4にして、失敗する所でした。 if~elseの方がいいかもしれませんね。 if~elseに変えて、使ってみたいと思います。 大変、勉強になりました。 最後まで、付き合って頂いて、感謝しております。 ありがとうございました。 「a-kuma」さんの名前は、「あ~熊さん」なのか、 「ええ熊さん」なのか、すごい気になりますが、 「ええ熊さん」だと思っておきます。 「優しい熊さん」という意味で。 すぐに締め切っても良いのですが、他の方で違った アドバイスがあるよって人がいるかもしれませんので、 明日締め切らせていただきます。 ご了承ください^^