1 // Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information. 2 3 using System.IO; 4 using System.Net; 5 using System.Reflection; 6 using System.Text.RegularExpressions; 7 using System.Web.WebPages; 8 using System.Xml; 9 using System.Xml.Resolvers; 10 using Xunit; 11 12 namespace System.Web.Helpers.Test 13 { 14 // see: http://msdn.microsoft.com/en-us/library/hdf992b8(v=VS.100).aspx 15 // see: http://blogs.msdn.com/xmlteam/archive/2008/08/14/introducing-the-xmlpreloadedresolver.aspx 16 public class XhtmlAssert 17 { 18 const string Xhtml10Wrapper = "<html xmlns=\"http://www.w3.org/1999/xhtml\"><head></head><body>{0}</body></html>"; 19 const string DOCTYPE_XHTML1_1 = "<!DOCTYPE {0} PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"xhtml11-flat.dtd\">\r\n"; 20 Validate1_0(object result, bool addRoot = false)21 public static void Validate1_0(object result, bool addRoot = false) 22 { 23 string html = null; 24 if (addRoot) 25 { 26 html = String.Format(Xhtml10Wrapper, GetHtml(result)); 27 } 28 else 29 { 30 html = GetHtml(result); 31 } 32 33 Validate1_0(html); 34 } 35 Validate1_1(object result, string wrapper = null)36 public static void Validate1_1(object result, string wrapper = null) 37 { 38 string root; 39 string html = GetHtml(result); 40 if (String.IsNullOrEmpty(wrapper)) 41 { 42 root = GetRoot(html); 43 } 44 else 45 { 46 root = wrapper; 47 html = String.Format("<{0}>{1}</{0}>", wrapper, html); 48 } 49 Validate1_1(root, html); 50 } 51 GetHtml(object result)52 private static string GetHtml(object result) 53 { 54 Assert.True((result is IHtmlString) || (result is HelperResult), "Helpers should return IHTMLString or HelperResult"); 55 return result.ToString(); 56 } 57 GetRoot(string html)58 private static string GetRoot(string html) 59 { 60 Regex regex = new Regex(@"<(\w+)[\s>]"); 61 Match match = regex.Match(html); 62 Assert.True(match.Success, "Could not determine root element"); 63 Assert.True(match.Groups.Count > 1, "Could not determine root element"); 64 return match.Groups[1].Value; 65 } 66 Validate1_0(string html)67 private static void Validate1_0(string html) 68 { 69 XmlReaderSettings settings = new XmlReaderSettings(); 70 settings.DtdProcessing = DtdProcessing.Parse; 71 settings.XmlResolver = new XmlPreloadedResolver(XmlKnownDtds.Xhtml10); 72 73 Validate(settings, html); 74 } 75 Validate1_1(string root, string html)76 private static void Validate1_1(string root, string html) 77 { 78 var settings = new XmlReaderSettings { DtdProcessing = DtdProcessing.Parse, ValidationType = ValidationType.DTD, XmlResolver = new AssemblyResourceXmlResolver() }; 79 80 string docType = String.Format(DOCTYPE_XHTML1_1, root); 81 Validate(settings, docType + html); 82 } 83 Validate(XmlReaderSettings settings, string html)84 private static void Validate(XmlReaderSettings settings, string html) 85 { 86 using (StringReader sr = new StringReader(html)) 87 { 88 using (XmlReader reader = XmlReader.Create(sr, settings)) 89 { 90 while (reader.Read()) 91 { 92 // XHTML element and attribute names must be lowercase, since XML is case sensitive. 93 // The W3C validator detects this, but we must manually check since the XmlReader does not. 94 // See: http://www.w3.org/TR/xhtml1/#h-4.2 95 if (reader.NodeType == XmlNodeType.Element) 96 { 97 string element = reader.Name; 98 Assert.True(element == element.ToLowerInvariant()); 99 if (reader.HasAttributes) 100 { 101 for (int i = 0; i < reader.AttributeCount; i++) 102 { 103 reader.MoveToAttribute(i); 104 string attribute = reader.Name; 105 Assert.True(attribute == attribute.ToLowerInvariant()); 106 } 107 // move back to element node 108 reader.MoveToElement(); 109 } 110 } 111 } 112 } 113 } 114 } 115 116 private class AssemblyResourceXmlResolver : XmlResolver 117 { 118 public override ICredentials Credentials 119 { 120 set { throw new NotSupportedException(); } 121 } 122 GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn)123 public override object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn) 124 { 125 Assembly assembly = typeof(XhtmlAssert).Assembly; 126 return assembly.GetManifestResourceStream("System.Web.Helpers.Test.TestFiles.xhtml11-flat.dtd"); 127 } 128 } 129 } 130 } 131