468


VS2013 .NetFramework4.0環境で、
HtmlAgilityPackを使用して煩雑なHTMLをパーズし、整形したHTMLに変換するプログラムを作成しています。

しかし、HtmlAgilityPackにはHTMLテキストをインデントする機能はないようでした。
XMLを自動インデントする方法はあるのですが、変換処理が必要になってしまう・preタグの中にインデント文字が入ってしまうなど少し面倒です。
C#でHTMLテキストをインデントする簡単な方法はありますでしょうか。HTML5のタグに対応しているものだとなお良いです。

よろしくお願い致します。


CC BY-SA 3.0
2014-12-08T04:00:11.330
436
2014-12-09T11:34:43.947
2014-12-09T11:34:43.947
438
438
question
.net c# html5 html-agility-pack
C#でHTMLテキストをインデントする方法はありませんか？


Html Agility Packでは出来ないらしいので、HtmlTidyPackを使うらしいです。  
<https://stackoverflow.com/questions/2593147/html-agility-pack-make-code-look-
neat>

[code]

    using System;
    using System.IO;
    using System.Net;
    using Mark.Tidy;
    
    namespace CleanupHtml{
    /// <summary>
    /// http://markbeaton.com/SoftwareInfo.aspx?ID=81a0ecd0-c41c-48da-8a39-f10c8aa3f931
    /// </summary>
        internal class Program
        {
            private static void Main(string[] args)
            {
                string html =
                    new WebClient().DownloadString(
                        "https://stackoverflow.com/questions/2593147/html-agility-pack-make-code-look-neat/2610903#2610903");
    
                using (Document doc = new Document(html))
                {
                    doc.ShowWarnings = false;
                    doc.Quiet = true;
                    doc.OutputXhtml = true;
                    doc.OutputXml = true;
                    doc.IndentBlockElements = AutoBool.Yes;
                    doc.IndentAttributes = false;
                    doc.IndentCdata = true;
                    doc.AddVerticalSpace = false;
                    doc.WrapAt = 120;
    
                    doc.CleanAndRepair();
    
                    string output = doc.Save();
                    Console.WriteLine(output);
                    File.WriteAllText("output.htm", output);
                }
            }
        }
    }
    
[/code]


CC BY-SA 3.0
2014-12-08T05:35:59.923
441
2014-12-08T05:35:59.923
2017-05-23T12:38:55.250
-1
525
436
answer


# HtmlTidyPackについて

[別の回答に含まれる英語版SOの回答](https://stackoverflow.com/a/2610903/718426)に書かれていたHtmlTidyPackのURLを開くと、

> This site is no longer being maintained. If you've arrived here via wherever
> and you're looking for some software, maybe these links will help:  
>  （このサイトはメンテナンスされていません。ソフトウェアなどをお探しでしたら、以下のリンクが参考になると思います（意訳））

とあり、当該githubのURLは[TidyManaged](https://github.com/markbeaton/TidyManaged)ですが5年以上メンテナンスされていないようです。  
（そもそも本家のtidyが2008年から更新されていないですので仕方ないですね）

# NuGet Package

そこで、[HtmlTidy](http://tidy.sourceforge.net/)のラッパである[HTML Tidy Library
Project](https://www.nuget.org/packages/libtidy/)または[TidyNetPortable](https://www.nuget.org/packages/TidyNetPortable/)を以下のように、NuGet経由でインストールするのがいいかなとおもいテストしてみました。

[code]

    Install-Package TidyNetPortable 
    
[/code]

結果、VS2013環境では両方使えませんでした...  
TidyNetPortableはそもそも実装が足りないのか、実装しても動かず、ドキュメントもありません。また、HTML Tidy Library
Projectは.Net Framework 4.0環境にはNuGetでインストールできませんでした。

# tidy wrapperを探してビルド

NuGetで提供されているパッケージがつかえないので、比較的新しめのプロジェクトを探してdllをビルドして使うしかないようです。さがしてみると[EfTidyNet:
.NET Wrapper for Tidy
library](http://www.codeproject.com/Articles/24105/EfTidyNet-NET-Wrapper-for-
Tidy-library)というのを発見しました。

  * Download EfTidy 1.0.2.0.source

とあるのをダウンロードし、Buildしてdllを生成します。このときx64環境であれば、構成がデフォルトでWin32になっていますので、環境に合わせて修正してbuildしてください。

dllを生成したら、ソリューションエクスプローラーのReferences（参照）上で右クリックして、Add
References(参照の追加)をしてください。

![参照の追加](https://i.stack.imgur.com/6yEHA.png)

次のようなダイアログが表示されますので、Browse（日本語版だと参照？）をクリックして、前の手順でビルドしたdllを選択します。  
![参照の追加ダイアログ](https://i.stack.imgur.com/MxQbh.png)

そして、次のようなプログラムを書きます。  
（ここでは、html5にtidy処理しています）

[code]

    ...
    using EfTidyNet;
    using System.Text.RegularExpressions;
    
    ...
    String text = File.ReadAllText("test.html");             
    
    TidyNet objTidyNet = new TidyNet();
    objTidyNet.Option.OutputType(EfTidyNet.EfTidyOpt.EOutputType.HtmlOut);
    objTidyNet.Option.NewBlockLevelTags("article aside audio details dialog figcaption figure footer header hgroup menutidy nav section source summary track video");
    objTidyNet.Option.NewInlineTags("command embed keygen source track wbr");
    objTidyNet.Option.NewEmptyTags("canvas command data datalist embed keygen mark meter output progress time wbr");
    objTidyNet.Option.Indent(EfTidyNet.EfTidyOpt.EIndentScheme.AUTOINDENT);
    objTidyNet.Option.IndentSpace(2);
    objTidyNet.Option.WrapLen(0);
    objTidyNet.Option.DropEmptyParas(true);
    objTidyNet.Option.TidyMark(false);
    objTidyNet.Option.Clean(true);
    
    String result = null;
    objTidyNet.TidyMemToMem(text, ref result);
    result = Regex.Replace(result, @"(\r\n){2}", "\r\n"); //tidyのオプションでどうしても消せず...
    this.textBox1.Text = result;
    
[/code]

test.htmlは次のような内容です。

[code]

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=Edge">
        <title>xxxxxxxxxx</title>
        <!--[if IE]>
        <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
        <![endif]-->
        <style>
            article, aside, dialog, figure, footer, header,
            hgroup, menu, nav, section {
                display: block;
            }
        </style>
    </head>
    <body>
        <article><h1>xxxxxxxxxx</h1><p>xxxx</p><aside><h3>xxx</h3><ul class="referenceLinks"><li><a href="http://xx.html" target="_blank">http://xxx.html</a></li><li><a href="http://xxxxx.html" target="_blank">http://xx.html</a></li></ul></aside><section><h2>yyyyyy</h2><p>Pyyyyy</p></section><section><h2>zzzzzzz</h2><p>Pzzzzzzz<strong>ssss</strong><strong>aaaaa</strong><strong>ssss</strong>zzzzzz</p><figure><figcaption>zzzzzz</figcaption><img src="aaa.png" alt="aaaaa"></figure><p>bbbbb</p></section></article>
    </body>
    </html>
    
[/code]

上記プログラムに食わせると、以下のような出力を得られます。

[code]

    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
      <meta http-equiv="X-UA-Compatible" content="IE=Edge">
      <title>xxxxxxxxxx</title><!--[if IE]>
        <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
        <![endif]-->
      <style type="text/css">
          article, aside, dialog, figure, footer, header,
            hgroup, menu, nav, section {
                display: block;
            }
      </style>
    </head>
    <body>
      <article>
        <h1>xxxxxxxxxx</h1>
        <p>xxxx</p>
        <aside>
          <h3>xxx</h3>
          <ul class="referenceLinks">
            <li><a href="http://xx.html" target="_blank">http://xxx.html</a></li>
            <li><a href="http://xxxxx.html" target="_blank">http://xx.html</a></li>
          </ul>
        </aside>
        <section>
          <h2>yyyyyy</h2>
          <p>Pyyyyy</p>
        </section>
        <section>
          <h2>zzzzzzz</h2>
          <p>Pzzzzzzz<strong>ssss</strong><strong>aaaaa</strong><strong>ssss</strong>zzzzzz</p>
          <figure>
            <figcaption>zzzzzz</figcaption><img src="aaa.png" alt="aaaaa">
          </figure>
          <p>bbbbb</p>
        </section>
      </article>
    </body>
    </html>
    
[/code]

というわけで無事beautifyされました。  
tidyのオプションの詳細については、[HTML Tidy Configuration
Options](http://tidy.sourceforge.net/docs/quickref.html)を確認して下さい。


CC BY-SA 3.0
2014-12-08T19:24:21.720
468
2014-12-08T20:24:49.000
2020-06-17T08:14:45.997
-1
351
436
answer