一部のHTMLタグを通すフィルタ
Posted feedbacks - C#
この課題、非常に勉強になります。閉じタグ忘れに対応。 他の方ので、"<!--" がエスケープされないのがいくつか上がってる気がします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | using System;
using System.Text;
using System.Text.RegularExpressions;
class HtmlFilter {
private Regex _regFilter;
public HtmlFilter() {
_regFilter = new Regex(@"(<(?<begin>\w+)(?:\s+(?<attr>\w+\s*=\s*"
+ "(?:'[^']*'|\"[^\"]*\")" + @"\s*)*)?/?>)|(</(?<end>\w+)\s*>)",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
}
public string escape(string s) {
return s.Replace("&", "&").Replace("<", "<").Replace(">", ">");
}
public string filter(string input) {
bool tagA = false;
int index = 0, tagStrong = 0;
StringBuilder sb = new StringBuilder(input.Length * 2);
for (Match m = _regFilter.Match(input); m.Success; m = _regFilter.Match(input, index)) {
sb.Append(escape(input.Substring(index, m.Index - index)));
index = m.Index + m.Length;
if (m.Groups["begin"].Success) {
switch (m.Groups["begin"].Value.ToLower()) {
case "a":
string href = "";
foreach (Capture capture in m.Groups["attr"].Captures) {
string[] attribute = capture.Value.Split('=');
if (attribute[0].Trim().Equals("href", StringComparison.OrdinalIgnoreCase)) {
href = " href=" + attribute[1].Trim();
break;
}
}
sb.Append(tagA ? "</a><a" : "<a").Append(href).Append(">");
tagA = true;
break;
case "strong":
tagStrong++;
sb.Append("<strong>");
break;
case "br":
sb.Append("<br/>");
break;
default:
sb.Append(escape(m.Value));
break;
}
} else {
switch (m.Groups["end"].Value.ToLower()) {
case "a":
if (tagA) {
sb.Append("</a>");
tagA = false;
} else {
sb.Append(escape(m.Value));
}
break;
case "strong":
if (tagStrong > 0) {
tagStrong--;
sb.Append("</strong>");
} else {
sb.Append(escape(m.Value));
}
break;
default:
sb.Append(escape(m.Value));
break;
}
}
}
sb.Append(escape(input.Substring(index, input.Length - index)));
while (tagStrong-- > 0) sb.Append("</strong>");
if (tagA) sb.Append("</a>");
return sb.ToString();
}
}
class Program {
static void Main(string[] args) {
HtmlFilter f = new HtmlFilter();
string text = System.IO.File.ReadAllText("hoge.txt");
Console.WriteLine(f.filter(text));
}
}
|


にしお
#3410()
Rating0/0=0.00
このお題はperezvonさんの提案を元にしています。ありがとうございました。 ただ、いきなりだと難しいかと思ったので、肝の部分以外を先に出題しました。このお題は続編で徐々に難しくなっていきます。
追記:属性に<や>が含まれてしまうケースに漏れのある解答が多いようなのでテストケースを追加します。 これは「この出力なら十分」という意味です。この出力の通りでなければいけないという意味ではありません。 <script foo="<script>alert('bar')</script>">alert('foo')</script> <script foo="<script>alert('bar')</script>">alert('foo')</script> <script foo="<a href='link'>link</a>">alert('foo')</script> <script foo="<a href='link'>link</a>">alert('foo')</script> <a href='www.g>oogle.com'>link</a> <a href="./www.g%3Eoogle.com">link</a>[ reply ]