Browse Source

XML Parser: Added canonical XML pretty printer needed for tests

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4696 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
David Srbecký 16 years ago
parent
commit
1a7e1e8b59
  1. 42
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit.Tests/XmlParser/W3C.cs
  2. 1
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj
  3. 117
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/CanonicalPrintAXmlVisitor.cs

42
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit.Tests/XmlParser/W3C.cs

@ -19,6 +19,7 @@ using NUnit.Framework; @@ -19,6 +19,7 @@ using NUnit.Framework;
namespace ICSharpCode.AvalonEdit.Xml.Tests
{
[TestFixture]
[Ignore]
public class W3C
{
readonly string zipFileName = @"XmlParser\W3C.zip";
@ -47,38 +48,44 @@ namespace ICSharpCode.AvalonEdit.Xml.Tests @@ -47,38 +48,44 @@ namespace ICSharpCode.AvalonEdit.Xml.Tests
return new StreamReader(stream).ReadToEnd();
}
/// <remarks> Also excludes "/out/" files </remarks>
IEnumerable<ZipEntry> GetXmlFilesStartingWith(string directory)
{
return files.Where(f => f.Name.StartsWith(directory) && f.Name.EndsWith(".xml"));
return files.Where(f => f.Name.StartsWith(directory) && f.Name.EndsWith(".xml") && !f.Name.Contains("/out/"));
}
[Test]
public void Valid()
{
string exlucde = "ibm32v02"; // Too long enity name
TestFiles(GetXmlFilesStartingWith("ibm/valid/").Where(f => !f.Name.Contains(exlucde)), true);
string[] exclude = {
};
TestFiles(GetXmlFilesStartingWith("ibm/valid/"), true, exclude);
}
[Test]
public void Invalid()
{
TestFiles(GetXmlFilesStartingWith("ibm/invalid/"), true);
string[] exclude = {
};
TestFiles(GetXmlFilesStartingWith("ibm/invalid/"), true, exclude);
}
[Test]
[Ignore]
public void NotWellformed()
{
TestFiles(GetXmlFilesStartingWith("ibm/not-wf/"), false);
string[] exclude = {
};
TestFiles(GetXmlFilesStartingWith("ibm/not-wf/"), false, exclude);
}
StringBuilder errorOutput;
void TestFiles(IEnumerable<ZipEntry> files, bool areWellFormed)
void TestFiles(IEnumerable<ZipEntry> files, bool areWellFormed, string[] exclude)
{
errorOutput = new StringBuilder();
int testsRun = 0;
foreach (ZipEntry file in files) {
if (exclude.Any(exc => file.Name.Contains(exc))) continue;
testsRun++;
TestFile(file, areWellFormed);
}
@ -86,7 +93,7 @@ namespace ICSharpCode.AvalonEdit.Xml.Tests @@ -86,7 +93,7 @@ namespace ICSharpCode.AvalonEdit.Xml.Tests
Assert.Fail("Test files not found");
}
if (errorOutput.Length > 0) {
Assert.Fail(errorOutput.ToString());
Assert.Fail(errorOutput.Replace("]]>", "]]~NUNIT~>").ToString());
}
}
@ -109,6 +116,25 @@ namespace ICSharpCode.AvalonEdit.Xml.Tests @@ -109,6 +116,25 @@ namespace ICSharpCode.AvalonEdit.Xml.Tests
errorOutput.AppendLine();
}
if (isWellFormed) {
string canonicalFilename = fileName.Replace("/ibm", "/out/ibm");
ZipEntry canonicalFile = files.FirstOrDefault(f => f.Name == canonicalFilename);
if (canonicalFile != null) {
string canonicalContent = Decompress(canonicalFile);
string canonicalPrint = CanonicalPrintAXmlVisitor.Print(document);
if (canonicalContent != canonicalPrint) {
errorOutput.AppendFormat("Canonical XML for \"{0}\" does not match the excpected.\n", fileName);
errorOutput.AppendFormat("Expected:\n{0}\n", Indent(canonicalContent));
errorOutput.AppendFormat("Seen:\n{0}\n", Indent(canonicalPrint));
errorOutput.AppendFormat("File content:\n{0}\n", Indent(content));
errorOutput.AppendLine();
}
} else {
errorOutput.AppendFormat("Can not find canonical file for \"{0}\"", fileName);
errorOutput.AppendLine();
}
}
bool hasErrors = document.SyntaxErrors.FirstOrDefault() != null;
if (isWellFormed && hasErrors) {
errorOutput.AppendFormat("Syntax error(s) in well formed file \"{0}\":\n", fileName);

1
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj

@ -326,6 +326,7 @@ @@ -326,6 +326,7 @@
<Compile Include="Xml\AXmlParser.cs" />
<Compile Include="Xml\AXmlTag.cs" />
<Compile Include="Xml\AXmlText.cs" />
<Compile Include="Xml\CanonicalPrintAXmlVisitor.cs" />
<Compile Include="Xml\TrackedSegmentCollection.cs">
<DependentUpon>AXmlParser.cs</DependentUpon>
</Compile>

117
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/CanonicalPrintAXmlVisitor.cs

@ -0,0 +1,117 @@ @@ -0,0 +1,117 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Linq;
using System.Text;
namespace ICSharpCode.AvalonEdit.Xml
{
/// <summary>
/// Converts the XML tree back to text in canonical form.
/// See http://www.w3.org/TR/xml-c14n
/// </summary>
public class CanonicalPrintAXmlVisitor: AbstractAXmlVisitor
{
StringBuilder sb = new StringBuilder();
/// <summary>
/// Gets the pretty printed text
/// </summary>
public string Output {
get {
return sb.ToString();
}
}
/// <summary> Create canonical text from a document </summary>
public static string Print(AXmlDocument doc)
{
CanonicalPrintAXmlVisitor visitor = new CanonicalPrintAXmlVisitor();
visitor.VisitDocument(doc);
return visitor.Output;
}
/// <summary> Visit RawDocument </summary>
public override void VisitDocument(AXmlDocument document)
{
foreach(AXmlObject child in document.Children) {
AXmlTag tag = child as AXmlTag;
// Only procssing instructions or elements
if (tag != null && tag.IsProcessingInstruction && tag.Name != "xml") {
VisitTag(tag);
} else if (child is AXmlElement) {
VisitElement((AXmlElement)child);
}
}
}
/// <summary> Visit RawElement </summary>
public override void VisitElement(AXmlElement element)
{
base.VisitElement(element);
}
/// <summary> Visit RawTag </summary>
public override void VisitTag(AXmlTag tag)
{
if (tag.IsStartOrEmptyTag) {
sb.Append('<');
sb.Append(tag.Name);
foreach(AXmlAttribute attr in tag.Children.OfType<AXmlAttribute>().OrderBy(a => a.Name)) {
VisitAttribute(attr);
}
sb.Append('>');
if (tag.IsEmptyTag) {
// Use explicit start-end pair
sb.AppendFormat("</{0}>", tag.Name);
}
} else if (tag.IsEndTag) {
sb.AppendFormat("</{0}>", tag.Name);
} else if (tag.IsProcessingInstruction) {
sb.Append("<?");
sb.Append(tag.Name);
foreach(AXmlText text in tag.Children.OfType<AXmlText>()) {
sb.Append(text.Value);
}
sb.Append("?>");
} else if (tag.IsCData) {
foreach(AXmlText text in tag.Children.OfType<AXmlText>()) {
sb.Append(Escape(text.Value));
}
}
}
/// <summary> Visit RawAttribute </summary>
public override void VisitAttribute(AXmlAttribute attribute)
{
sb.Append(' ');
sb.Append(attribute.Name);
sb.Append("=");
sb.Append('"');
sb.Append(Escape(attribute.Value));
sb.Append('"');
}
/// <summary> Visit RawText </summary>
public override void VisitText(AXmlText text)
{
sb.Append(Escape(text.Value));
}
string Escape(string text)
{
return text
.Replace("&", "&amp;")
.Replace("<", "&lt;")
.Replace(">", "&gt;")
.Replace("\"", "&quot;")
.Replace("\u0009", "&#9;")
.Replace("\u000A", "&#10;")
.Replace("\u000D", "&#13;");
}
}
}
Loading…
Cancel
Save