2017-03-24 6 views
0

私のASP.NET MVC 5アプリケーションでは、正規表現を使用する空白を削除するための従来のHTML縮小属性があります。マークアップには、空白を保存する必要があるtextareaまたはpreが含まれているため、それ以外の場合は例外です。ASP.NETで完全な応答をフィルタリングする方法は?

最後の2日間、無限の質問と何かを使って細分化を行う方法についての答えを読んだ後、私はHtmlAgilityPackを使用して解決しました。これはLINQPadで私が欲しいの結果を生成するので

var html = GetHtml(); 
var document = new HtmlAgilityPack.HtmlDocument(); 

document.LoadHtml(html); 

var spans = document.DocumentNode.Descendants().Where(
    d => 
     d.NodeType == HtmlNodeType.Element 
     && d.Name == "span").SelectMany(
    d => d.ChildNodes.Where(
     cn => cn.NodeType == HtmlNodeType.Text)).ToList(); 

// Some spans have content that needs to be trimmed. 
foreach (var span in spans) { 
    span.InnerHtml = span.InnerHtml.Trim(); 
} 

var nodes = document.DocumentNode.Descendants().Where(
    d => 
     (d.NodeType == HtmlNodeType.Text 
     && d.InnerText.Trim().Length == 0) 
     || (d.NodeType == HtmlNodeType.Comment 
     && d.InnerText.Trim() != "<!DOCTYPE html>")).Select(
    d => d).ToList(); 

foreach (var node in nodes) { 
    node.Remove(); 
} 

using (var stream = new MemoryStream()) { 
    document.Save(stream); 

    stream.Seek(0, SeekOrigin.Begin); 

    using (var reader = new StreamReader(stream)) { 
     reader.ReadToEnd().Dump(); 
    } 
} 

だから、私は私にそれを上書きコピー:LINQPadを使用して、私は、私の知る限り、今言うことができるように、私が欲しい、まさに生成コードをつなぎ合わせそれは私がすぐにはそれほど簡単ではないことを発見した場所です。 Response.Filterはチャンクで書いているので、応答が単一のチャンクより大きい場合は大きな混乱を招きます。

私が理解したところでは、フィルタからの完全な応答をキャプチャしてから、上記のコードで空白を削除し、それをフィルタに書き戻す必要があります。不幸にも、私はそのプロセス全体にどのようにアプローチするのかちょっと混乱しています。私はチャンクからフルストリームをキャプチャする方法を知っていますが、その後は何をすべきかわかりません。私は何をしたいのかを完成させるためのあらゆる助けを求める。前もって感謝します!

これは、現在存在する属性クラスとストリームクラスです。私は正直なところ、特定のコードが必要なのかどうかはまだ分かりません...私が以前に言ったように、これはレガシーコードであり、少なくとも5年間変化しています。

[AttributeUsage(AttributeTargets.Class, Inherited = false)] 
internal sealed class MinifyHtmlAttribute : 
    ActionFilterAttribute { 
    public override void OnActionExecuted(
     ActionExecutedContext filterContext) { 
     if (filterContext != null 
      && !filterContext.IsChildAction) { 
      filterContext.HttpContext.Response.Filter = new MinifyHtmlStream(filterContext.HttpContext); 
     } 
    } 
} 

internal sealed class MinifyHtmlStream : 
    MemoryStream { 
    private readonly HttpContextBase Context; 
    private readonly Stream Stream; 

    public MinifyHtmlStream(
     HttpContextBase httpContextBase) { 
     Context = httpContextBase; 
     Stream = httpContextBase.Response.Filter; 
    } 

    public override void Write(
     byte[] buffer, 
     int offset, 
     int count) { 
     var source = Encoding.UTF8.GetString(buffer); 

     if (Context.Response.ContentType == "text/html") { 
      var document = new HtmlDocument(); 

      document.LoadHtml(source); 

      var spans = document.DocumentNode.Descendants().Where(
       d => 
        d.NodeType == HtmlNodeType.Element 
        && d.Name == "span").SelectMany(
       d => d.ChildNodes.Where(
        cn => cn.NodeType == HtmlNodeType.Text)).ToList(); 

      // Some spans have content that needs to be trimmed. 
      foreach (var span in spans) { 
       span.InnerHtml = span.InnerHtml.Trim(); 
      } 

      var nodes = document.DocumentNode.Descendants().Where(
       d => 
        (d.NodeType == HtmlNodeType.Text 
        && d.InnerText.Trim().Length == 0) 
        || (d.NodeType == HtmlNodeType.Comment 
        && d.InnerText.Trim() != "<!DOCTYPE html>")).Select(
       d => d).ToList(); 

      foreach (var node in nodes) { 
       node.Remove(); 
      } 

      document.Save(Stream); 
     } 
    } 
} 

答えて

1

私は満足している解決策を考え出しました。私はMemoryStreamを追加してすべてのチャンクをバッファリングし、次にそれを細分化して最終的にフィルタに戻しました。解析と細分化のパフォーマンスは私にとっては問題ありませんが、私のアプリケーションは少量のユーザーで内部使用するためのものです。ここで私が作ってみた最終的なコードです:私はそれを行うことができ

[AttributeUsage(AttributeTargets.Class, Inherited = false)] 
internal sealed class MinifyHtmlAttribute : 
    ActionFilterAttribute { 
    public override void OnActionExecuted(
     ActionExecutedContext filterContext) { 
     if (filterContext == null 
      || filterContext.IsChildAction) { 
      return; 
     } 

     filterContext.HttpContext.Response.Filter = new MinifyHtmlStream(filterContext.HttpContext); 
    } 
} 

internal sealed class MinifyHtmlStream : 
    MemoryStream { 
    private readonly MemoryStream BufferStream; 
    private readonly HttpContextBase Context; 
    private readonly Stream FilterStream; 

    public MinifyHtmlStream(
     HttpContextBase httpContextBase) { 
     BufferStream = new MemoryStream(); 
     Context = httpContextBase; 
     FilterStream = httpContextBase.Response.Filter; 
    } 

    public override void Flush() { 
     BufferStream.Seek(0, SeekOrigin.Begin); 

     if (Context.Response.ContentType != "text/html") { 
      BufferStream.CopyTo(FilterStream); 

      return; 
     } 

     var document = new HtmlDocument(); 

     document.Load(BufferStream); 

     var spans = document.DocumentNode.Descendants().Where(
      d => 
       d.NodeType == HtmlNodeType.Element 
       && d.Name == "span").SelectMany(
      d => d.ChildNodes.Where(
       cn => cn.NodeType == HtmlNodeType.Text)).ToList(); 

     // Some spans have content that needs to be trimmed. 
     foreach (var span in spans) { 
      span.InnerHtml = span.InnerHtml.Trim(); 
     } 

     var nodes = document.DocumentNode.Descendants().Where(
      d => 
       (d.NodeType == HtmlNodeType.Text 
       && d.InnerText.Trim().Length == 0) 
       || (d.NodeType == HtmlNodeType.Comment 
       && d.InnerText.Trim() != "<!DOCTYPE html>")).Select(
      d => d).ToList(); 

     foreach (var node in nodes) { 
      node.Remove(); 
     } 

     document.Save(FilterStream); 
    } 

    public override void Write(
     byte[] buffer, 
     int offset, 
     int count) { 
     BufferStream.Write(buffer, offset, count); 
    } 
} 
0

ストリームの代わりにTextWriterを使用してみてください。次にreplaceメソッドを使用して、空白をstring.emptyで削除してドキュメントを保存します。

+0

は、私はそれはそれは空白を取り除くになる主ことを、私が正規表現から避けるようにしようとしている同じ結果が得られます想像します実際には 'textarea'や' pre'要素の内容のように保存する必要があります。 HTMLを解析することによって、空白ノードを見つけ出し、それらを削除して、縮小されたHTMLを戻すことができます。偶然、私が見つけたコードは、空白のノードを見つけ、 'textarea'と' pre'タグの空白を無視します。実際のノードではないからです。 – Gup3rSuR4c

関連する問題