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(); } } } }