public static void AssertByLine(this XDocument expected, XDocument actual) { // MH comparing XML by string sucks... but this is usable for my porpoises var str1 = expected.Normalize().ToString(); var str2 = actual.Normalize().ToString(); var expectedLines = str1.Split(new[] {'\r', '\n'}, StringSplitOptions.RemoveEmptyEntries); var actualLines = str2.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); var smallest = Math.Min(expectedLines.Count(), actualLines.Count()); for (var i = 0; i < smallest; i++) Assert.That( expectedLines[i].Equals(actualLines[i], StringComparison.OrdinalIgnoreCase), string.Format("Xml differs at line {0}.\r\n{1}\r\n{2}", (i+1), expectedLines[i], actualLines[i])); Assert.AreEqual(expectedLines.Count(), actualLines.Count(), "Xml has a different number of lines"); }
/// <summary> /// Check an XElement against some expected XML. /// <para> /// The supplied node is copied and normalized to get actual differences. /// </para> /// </summary> /// <param name="expected">XElement to use</param> /// <param name="candidate">XML to compare against.</param> /// <param name="fullComparison">Whether to do a full comparison using prefix/namespace</param> /// <param name="diffFilePath">Where/whether to write out the HTML difference</param> public static string CheckXml(this XElement expected, XElement candidate, bool fullComparison = true, string diffFilePath = "") { // Xml's are normalized before comparision, so that we can get actual difference when we turn on Namespaces & Prefix's differnces var source = new XDocument(expected); source = source.Normalize(); var expectedNode = source.ToXmlDocument().SelectSingleNode("/*"); var target = new XDocument(candidate); target = target.Normalize(); var candidateNode = target.ToXmlDocument().SelectSingleNode("/*"); using (var stringWriter = new StringWriter()) { bool areDifferent; using (var xmlWriter = new XmlTextWriter(stringWriter) { Formatting = Formatting.Indented }) { // Default engine ignores prefix/namespace so we need to enable if we are doing a full comparison. var diff = DefaultDiffEngine(); diff.IgnorePrefixes = !fullComparison; diff.IgnoreNamespaces = !fullComparison; areDifferent = !diff.Compare(expectedNode, candidateNode, xmlWriter); } if (areDifferent) { if (!string.IsNullOrEmpty(diffFilePath)) { var diffgram = stringWriter.GetStringBuilder().ToString(); WriteDiffFile(diffFilePath, diffgram, expectedNode); } return string.Format( "Xml differs.{0}Expected:{0}{1}{0}{0}Actual:{0}{2}{0}{0}Diff:{0}{3}", Environment.NewLine, expectedNode.ToXmlString(), candidateNode.ToXmlString(), stringWriter); } } return string.Empty; }