WinMergeのHTML形式レポートファイルから差分をプログラム上で取得する方法(Javaによる例あり)

　エビデンスとしてWinMergeでHTML形式のレポートファイルを作成することがあると思います。
　この記事では出力したHTMLファイルから差分となった行をプログラム上で取得する方法について説明します。
<b>WinMergeによるHTML形式のレポートファイル出力</b>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/846337/7230ab05-5efc-1d57-a87c-35cc4ea7892f.png)
　レポートファイルの差分を比較する部分は4列のtable要素で構成されてます。
<b>WinMergeにより出力されたHTMLレポートファイル</b>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/846337/e2c153b5-b362-923b-8d74-91f0700729f6.png)
　1-2列目はWinMergeの左側、3-4列目は右側です。それぞれ行番号の列と比較ファイルの内容の列で構成されてます。
　WinMergeの「表示>行番号を表示」を指定していないと行番号の列に行番号が入りません。
　比較ファイルの内容はcode要素とcode要素の中に塗りつぶし箇所を指定するspan要素で構成されてます。
　WinMergeの「編集>設定」のオプション(色>差異)で指定した色がspan要素のbackground-color属性として埋め込まれています。
<b>WinMergeの差異色指定画面</b>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/846337/fbcd805e-a0f6-f317-c274-9a895992a586.png)
　したがって、差異の色(デフォルトの場合、`#efcb05` `#c0c0c0` `#ef7774`等)をbackground-color属性に指定している行を取り出せば差分となっている内容を取得することができます。


java(Java1.8)によるサンプルコードは以下の通りです。
```java
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Sample {
	public static void main(String[] args) {

		try {
			// 解析する対象のファイル名
			String reportFile = "reportFile.htm";
			// code要素の中身を取得するためのパターン
			final Pattern CODE_PTN = Pattern.compile("<code>.*</code>");
			// WinMergeにおける差分行のbackground-colorの値
			final Pattern MERGE_SABUN_PTN = Pattern.compile("(#efcb05|#c0c0c0|#ef7774)");
			// タグを消去するためにタグを抽出するパターン
			final Pattern TAG_DEL_PTN = Pattern.compile("<[^<>]*>");
			// ファイルの読み込み
			List<String> lines = Files.readAllLines(Paths.get(reportFile));
			// WinMergeの左側の行を格納するリスト
			List<String> leftLines = new ArrayList<String>();
			// WinMergeの右側の行を格納するリスト
			List<String> rightLines = new ArrayList<String>();

			for (String line : lines) {
				// WinMergeの比較列の抽出
				//"<td"ではじまる奇数列が左側のもの、偶数列が右側のもの
				if (line.startsWith("<td")) {
					if ((leftLines.size() + rightLines.size()) % 2 == 0) {
						// 奇数列が左側のもの
						leftLines.add(line);
					} else {
						// 偶数列が右側のもの
						rightLines.add(line);
					}
				}
			}

			System.out.println("左側の差分の出力");
			for (String line : leftLines) {
				// 差分行のbackground-colorが含まれてるかの検証
				if (MERGE_SABUN_PTN.matcher(line).find()) {
					// <code>要素の中身を取得
					Matcher matcher = CODE_PTN.matcher(line);
					matcher.find();
					String content = matcher.group();
					// WinMergeのHTMLレポートファイル用のタグを除去して標準出力
					System.out.println(TAG_DEL_PTN.matcher(content).replaceAll(""));
				}
			}
			System.out.println("右側の差分");
			for (String line : rightLines) {
				// 差分行のbackground-colorが含まれてるかの検証
				if (MERGE_SABUN_PTN.matcher(line).find()) {
					Matcher matcher = CODE_PTN.matcher(line);
					matcher.find();
					String content = matcher.group();
					// WinMergeのHTMLレポートファイル用のタグを除去して標準出力
					System.out.println(TAG_DEL_PTN.matcher(content).replaceAll(""));
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}

	}
}

```
　上記コードは指定したWinMergeのHTMLレポートファイルから差分となっている行を標準出力に出力します。
　`#efcb05` `#c0c0c0` `#ef7774`が存在するファイルの比較の場合、本文に埋め込まれてる行も差分として検出してしまうことにご留意ください。
　以上です。