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