Visual StudioのWebテストの結果をブラウザで参照可能にする2005版

上のサンプルは、Visual Studio2008のtrxファイル用だったので、2005向けのサンプル
trxファイルの構造が若干変わっている

using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
using System.IO.Compression;
using System.Xml;
namespace Asuka
{
    public class Converter
    {
        private Encoding defaultEncoding = Encoding.GetEncoding("Shift-JIS");

        private Regex srcRegex = new Regex("src=\"(?<url>[^\"]+)\"", RegexOptions.Compiled | RegexOptions.IgnoreCase);
        private Regex hrefRegex = new Regex("href=\"(?<url>[^\"]+)\"", RegexOptions.Compiled | RegexOptions.IgnoreCase);


        /// <summary>
        /// trxファイルの内容を解析し、レスポンスの内容をファイルに書き出す
        /// その際、リンク先のurlは書き出した内容に合わせて修正する
        /// </summary>
        /// <param name="inputFileName">trxファイルの場所</param>
        /// <param name="outputDirName">出力ファイルの置き場所</param>
        public void Convert(string inputFileName, string outputDirName)
        {
            XmlDocument xmldoc = new XmlDocument();
            xmldoc.Load(inputFileName);

            //XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmldoc.NameTable);
            //nsmgr.AddNamespace("a", "http://microsoft.com/schemas/VisualStudio/TeamTest/2006");

            List<WebRequestResult> reqResults = new List<WebRequestResult>();

            foreach (XmlNode node in xmldoc.SelectNodes("//WebTestResult/m_requestResults/element"))
            {
                WebRequestResult reqresult = new WebRequestResult();
                XmlNode m_responseBytesHandle = node.SelectSingleNode("m_responseBytesHandle");
                reqresult.ResponseHandle = m_responseBytesHandle.InnerText;

                XmlNode m_requestUrl = node.SelectSingleNode("m_requestUrl");
                reqresult.Url = m_requestUrl.InnerText;

                XmlNode m_responseContentType = node.SelectSingleNode("m_responseContentType");
                reqresult.ContentType = m_responseContentType.InnerText;
                reqResults.Add(reqresult);
            }

            Dictionary<string, byte[]> mapHandleToBytes = new Dictionary<string, byte[]>();
            XmlNode m_mapHandleToBytes = xmldoc.SelectSingleNode("//m_mapHandleToBytes");
            for (int i = 0; i < m_mapHandleToBytes.ChildNodes.Count; i++)
            {
                string key = m_mapHandleToBytes.ChildNodes[i].InnerText;
                i++;
                string valueString = m_mapHandleToBytes.ChildNodes[i].InnerText;
                MemoryStream ms = new MemoryStream();
                foreach (string s in valueString.Split(new char[] { ',' }))
                {
                    byte b = byte.Parse(s);
                    ms.WriteByte(b);
                }
                ms.Close();
                mapHandleToBytes.Add(key, ms.ToArray());
            }

            foreach (WebRequestResult reqresult in reqResults)
            {
                string handle = reqresult.ResponseHandle;
                reqresult.EncodedResponse = mapHandleToBytes[handle];
            }


            foreach (WebRequestResult reqresult in reqResults)
            {
                string outFileName = outputDirName + "\\" + reqresult.fileName;
                using (FileStream fs = new FileStream(outFileName, FileMode.Create))
                {
                    if (!reqresult.ContentType.StartsWith("text"))
                    //if (true)
                    {
                        byte[] bytes = reqresult.Response;
                        fs.Write(bytes, 0, bytes.Length);
                        fs.Close();
                    }
                    else
                    {
                        Encoding enc = null;
                        if (reqresult.Charset != string.Empty)
                        {
                            enc = Encoding.GetEncoding(reqresult.Charset);
                        }
                        else
                        {
                            enc = defaultEncoding;
                        }

                        string body = enc.GetString(reqresult.Response, 0, reqresult.Response.Length);
                        Dictionary<string, string> urlMap = new Dictionary<string, string>();

                        MatchCollection srcMatches = srcRegex.Matches(body);
                        foreach (Match match in srcMatches)
                        {
                            string src = match.Groups["url"].Value;
                            if (!urlMap.ContainsKey(src))
                            {
                                for (int i = 0; i < reqResults.Count; i++)
                                {
                                    if (reqResults[i].Url.EndsWith(src))
                                    {
                                        urlMap.Add(src, reqResults[i].fileName);
                                        break;
                                    }
                                }
                            }

                            if (src.StartsWith("/") || src.StartsWith("."))
                            {
                                Uri uri = new Uri(new Uri(reqresult.Url), src);
                                if (!urlMap.ContainsKey(src))
                                {
                                    for (int i = 0; i < reqResults.Count; i++)
                                    {
                                        if (reqResults[i].Url.EndsWith(uri.AbsoluteUri))
                                        {
                                            urlMap.Add(src, reqResults[i].fileName);
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                        MatchCollection hrefMatches = hrefRegex.Matches(body);
                        foreach (Match match in hrefMatches)
                        {
                            string src = match.Groups["url"].Value;
                            if (!urlMap.ContainsKey(src))
                            {
                                for (int i = 0; i < reqResults.Count; i++)
                                {
                                    if (reqResults[i].Url.EndsWith(src))
                                    {
                                        urlMap.Add(src, reqResults[i].fileName);
                                        break;
                                    }
                                }
                            }

                            if (src.StartsWith("/") || src.StartsWith("."))
                            {
                                Uri uri = new Uri(new Uri(reqresult.Url), src);
                                if (!urlMap.ContainsKey(src))
                                {
                                    for (int i = 0; i < reqResults.Count; i++)
                                    {
                                        if (reqResults[i].Url.EndsWith(uri.AbsoluteUri))
                                        {
                                            urlMap.Add(src, reqResults[i].fileName);
                                            break;
                                        }
                                    }
                                }
                            }
                        }

                        foreach (string beforeUrl in urlMap.Keys)
                        {
                            Regex regex1 = new Regex("src=\"" + beforeUrl + "\"", RegexOptions.IgnoreCase);
                            Regex regex2 = new Regex("href=\"" + beforeUrl + "\"", RegexOptions.IgnoreCase);

                            body = regex1.Replace(body, "src=\"" + urlMap[beforeUrl] + "\"");
                            body = regex2.Replace(body, "href=\"" + urlMap[beforeUrl] + "\"");
                        }

                        byte[] converted = enc.GetBytes(body);
                        fs.Write(converted, 0, converted.Length);
                        fs.Close();

                    }
                }
            }
        }
    }

    internal class WebRequestResult
    {
        private static Regex charsetRegex = new Regex(@"charset=(?<charsetName>.+)", RegexOptions.Compiled);
        public string Charset
        {
            get
            {
                MatchCollection matches = charsetRegex.Matches(this.contentType);
                if (matches.Count > 0)
                {
                    return matches[0].Groups["charsetName"].Value;
                }
                return string.Empty;
            }
        }

        private string contentType;
        public string ContentType
        {
            get { return this.contentType; }
            set { this.contentType = value; }
        }

        private string url;
        public string Url
        {
            get { return this.url; }
            set { this.url = value; }
        }

        private string guid = Guid.NewGuid().ToString();
        public string fileName
        {
            get
            {
                string name = Url;
                name = name.Replace("//", "_");
                name = name.Replace('/', '_');
                name = name.Replace(':', '_');
                name = name.Replace('*', '_');
                name = name.Replace('"', '_');
                name = name.Replace('<', '_');
                name = name.Replace('>', '_');
                name = name.Replace('|', '_');
                name = name.Replace('?', '_');
                if (name.EndsWith("\\"))
                {
                    name = name.Substring(0, name.Length - 1);
                }
                if (name.Length > 100)
                {
                    return this.guid;
                }
                return name;
            }
        }

        private string responseHandle;
        public string ResponseHandle
        {
            get { return this.responseHandle; }
            set { this.responseHandle = value; }
        }

        private byte[] encodedResponse;
        public byte[] EncodedResponse
        {
            get { return this.encodedResponse; }
            set { this.encodedResponse = value; }
        }

        public byte[] Response
        {
            get
            {
                if (this.encodedResponse == null || this.encodedResponse.Length ==0)
                {
                    return new byte[0];
                }
                byte[] compressed = this.encodedResponse;
                MemoryStream ms = new MemoryStream();
                ms.Write(compressed, 0, compressed.Length);
                ms.Position = 0;
                GZipStream gzipStream = new GZipStream(ms, CompressionMode.Decompress, true);

                MemoryStream msOut = new MemoryStream();
                int uncompressedByte = -1;
                while ((uncompressedByte = gzipStream.ReadByte()) != -1)
                {
                    msOut.WriteByte((byte)uncompressedByte);
                }
                return msOut.ToArray();
            }
        }
    }
}