public void ParseHtml(object sender, RoutedEventArgs e) { Tokens.Items.Clear(); ReconstructedHTML.Clear(); ParseErrors.Items.Clear(); using (TextReader stringReader = new StringReader(HtmlInput.Text)) { using (HtmlTokenizer tokenizer = new Tokenizer( Fragment.IsChecked.HasValue && Fragment.IsChecked.Value ? new HtmlTextTokenizer(stringReader, FragmentContainer.Text) : new HtmlTextTokenizer(stringReader), Tokens)) { using (HtmlReader reader = new HtmlReader(tokenizer)) { reader.ParseError += new EventHandler<ParseErrorEventArgs>(reader_ParseError); while (reader.Read()) { switch (reader.NodeType) { case XmlNodeType.Text: case XmlNodeType.Whitespace: case XmlNodeType.SignificantWhitespace: ReconstructedHTML.AppendText(reader.Value); break; case XmlNodeType.Comment: ReconstructedHTML.AppendText("<!--"); ReconstructedHTML.AppendText(reader.Value); ReconstructedHTML.AppendText("-->"); break; case XmlNodeType.Element: ReconstructedHTML.AppendText("<"); ReconstructedHTML.AppendText(reader.Name); if (reader.MoveToFirstAttribute()) { do { ReconstructedHTML.AppendText(" "); ReconstructedHTML.AppendText(reader.Name); ReconstructedHTML.AppendText("="); ReconstructedHTML.AppendText(reader.QuoteChar.ToString()); ReconstructedHTML.AppendText(reader.Value); ReconstructedHTML.AppendText(reader.QuoteChar.ToString()); } while (reader.MoveToNextAttribute()); } ReconstructedHTML.AppendText(">"); break; case XmlNodeType.EndElement: ReconstructedHTML.AppendText("</"); ReconstructedHTML.AppendText(reader.Name); ReconstructedHTML.AppendText(">"); break; default: ReconstructedHTML.AppendText("###"); ReconstructedHTML.AppendText(Enum.GetName(typeof(XmlNodeType), reader.NodeType)); ReconstructedHTML.AppendText("###"); break; } } } } } }
private void DoTest(string input, string fragmentContainer, string expectedOutput, string[] parseErrors) { expectedOutput.Trim(); input = input.Replace("\n", Environment.NewLine); expectedOutput = expectedOutput.Replace("\n", Environment.NewLine); Trace.WriteLine("Input:"); Trace.WriteLine(input); Trace.WriteLine(""); if (parseErrors == null || parseErrors.Length == 0) { Trace.WriteLine("No expected error."); } else { Trace.WriteLine("Expected errors:"); foreach (string parseError in parseErrors) { Trace.WriteLine(parseError); } } Trace.WriteLine(""); Trace.WriteLine("Expected:"); Trace.WriteLine(expectedOutput); StringBuilder actualOutput = new StringBuilder(expectedOutput.Length); try { HtmlReader htmlReader; if (fragmentContainer == null) { htmlReader = new HtmlReader(new StringReader(input)); } else { htmlReader = new HtmlReader(new StringReader(input), fragmentContainer); } using (htmlReader) { htmlReader.ParseError += new EventHandler<ParseErrorEventArgs>(htmlReader_ParseError); using (XmlReader reader = new LintXmlReader(htmlReader)) { while (reader.Read()) { if (reader.NodeType == XmlNodeType.EndElement) { continue; } actualOutput.Append("| "); if (reader.Depth > 0) { actualOutput.Append(' ', reader.Depth * 2); } switch (reader.NodeType) { case XmlNodeType.DocumentType: actualOutput.Append("<!DOCTYPE"); //if (reader.Name.Length > 0) { actualOutput.Append(' ').Append(reader.Name); //} //string publicId = reader.GetAttribute("PUBLIC"); //string systemId = reader.GetAttribute("SYSTEM"); //if (publicId != null) { // actualOutput.Append("PUBLIC ") // .Append('"').Append(publicId.Replace("\n", Environment.NewLine)).Append('"'); //} else if (systemId != null) { // actualOutput.Append("SYSTEM"); //} //if (systemId != null) { // actualOutput.Append(' ').Append('"').Append(systemId.Replace("\n", Environment.NewLine)).Append('"'); //} actualOutput.Append('>'); break; case XmlNodeType.Element: actualOutput.Append("<").Append(reader.Name).Append('>'); if (reader.MoveToFirstAttribute()) { do { actualOutput.AppendLine(); actualOutput.Append("| "); actualOutput.Append(' ', reader.Depth * 2); actualOutput.Append(reader.Name).Append("=\"").Append(reader.Value.Replace("\n", Environment.NewLine).Replace("\"", """)).Append('"'); } while (reader.MoveToNextAttribute()); reader.MoveToElement(); } break; case XmlNodeType.EndElement: throw new InvalidOperationException("EndElement should have been handled above !?"); case XmlNodeType.Comment: actualOutput.Append("<!-- ").Append(reader.Value.Replace("\n", Environment.NewLine)).Append(" -->"); break; case XmlNodeType.Whitespace: case XmlNodeType.Text: actualOutput.Append('"').Append(reader.Value.Replace("\n", Environment.NewLine).Replace("\"", """)).Append('"'); break; default: Assert.Fail("Unexpected token type: {0}", reader.NodeType); break; } actualOutput.AppendLine(); } } } Assert.AreEqual(expectedOutput, actualOutput.ToString().Trim()); Assert.AreEqual(parseErrors == null ? 0 : parseErrors.Length, this.parseErrors); } catch (NotImplementedException nie) { // Amnesty for those that confess Trace.WriteLine(""); Trace.WriteLine(nie); #if NUNIT Assert.Ignore("Not Implemented"); #else Assert.Inconclusive("Not Implemented"); #endif } finally { if (this.parseErrors == 0) { Trace.WriteLine(""); Trace.WriteLine("No actual error."); } Trace.WriteLine(""); Trace.WriteLine("Actual:"); Trace.WriteLine(actualOutput); } }