diff --git a/samples/XmlDOM/XmlDOM.sln b/samples/XmlDOM/XmlDOM.sln
index 13ac78bf26..402ef647d5 100644
--- a/samples/XmlDOM/XmlDOM.sln
+++ b/samples/XmlDOM/XmlDOM.sln
@@ -1,11 +1,13 @@
Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 10
-# SharpDevelop 4.0.0.4567
+# SharpDevelop 4.0.0.4664
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XmlDOM", "XmlDOM.csproj", "{AF8CA20E-58AC-423E-95A8-5AA464938D19}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.AvalonEdit", "..\..\src\Libraries\AvalonEdit\ICSharpCode.AvalonEdit\ICSharpCode.AvalonEdit.csproj", "{6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.AvalonEdit.Tests", "..\..\src\Libraries\AvalonEdit\ICSharpCode.AvalonEdit.Tests\ICSharpCode.AvalonEdit.Tests.csproj", "{6222A3A1-83CE-47A3-A4E4-A018F82D44D8}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -20,5 +22,9 @@ Global
{6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}.Release|Any CPU.Build.0 = Release|Any CPU
{6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6222A3A1-83CE-47A3-A4E4-A018F82D44D8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6222A3A1-83CE-47A3-A4E4-A018F82D44D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6222A3A1-83CE-47A3-A4E4-A018F82D44D8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6222A3A1-83CE-47A3-A4E4-A018F82D44D8}.Release|Any CPU.ActiveCfg = Release|Any CPU
EndGlobalSection
EndGlobal
diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit.Tests/ICSharpCode.AvalonEdit.Tests.csproj b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit.Tests/ICSharpCode.AvalonEdit.Tests.csproj
index 4db9bbb049..98d39ca526 100644
--- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit.Tests/ICSharpCode.AvalonEdit.Tests.csproj
+++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit.Tests/ICSharpCode.AvalonEdit.Tests.csproj
@@ -82,7 +82,7 @@
-
+
Always
diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit.Tests/XmlParser/SimpleTests.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit.Tests/XmlParser/SimpleTests.cs
deleted file mode 100644
index 202881d3ee..0000000000
--- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit.Tests/XmlParser/SimpleTests.cs
+++ /dev/null
@@ -1,116 +0,0 @@
-//
-//
-//
-//
-// $Revision$
-//
-
-using System;
-using System.Linq;
-using System.Diagnostics;
-using System.IO;
-using System.Text;
-
-using ICSharpCode.AvalonEdit.Xml;
-using ICSharpCode.SharpZipLib.Zip;
-using NUnit.Framework;
-
-namespace ICSharpCode.AvalonEdit.Xml
-{
- [TestFixture]
- [Ignore("XML parser API changes not complete")]
- public class SimpleTests
- {
- string tmpPath;
-
- [TestFixtureSetUp]
- public void PrepareFiles()
- {
- try {
- tmpPath = Path.Combine(Path.GetTempPath(), "XMLTestCases" + new Random().Next(0, 100));
- Directory.CreateDirectory(tmpPath);
- UncompressZip("XmlParser\\testcases.zip", tmpPath);
- } catch (Exception) {
- Directory.Delete(tmpPath, true);
- }
- }
-
- static void UncompressZip(string fileName, string outputFolder)
- {
- ZipInputStream zipIn = new ZipInputStream(File.OpenRead(fileName));
- ZipEntry entry;
- while ((entry = zipIn.GetNextEntry()) != null) {
- string path = Path.Combine(outputFolder, entry.Name);
- if (entry.IsDirectory) {
- Directory.CreateDirectory(path);
- continue;
- }
- FileStream streamWriter = File.Create(path);
- long size = entry.Size;
- byte[] data = new byte[size];
- while (true) {
- size = zipIn.Read(data, 0, data.Length);
- if (size > 0)
- streamWriter.Write(data, 0, (int) size);
- else
- break;
- }
- streamWriter.Close();
- }
- }
-
- [TestFixtureTearDown]
- public void DisposeFiles()
- {
- Directory.Delete(tmpPath, true);
- }
-
- [Test]
- public void FullParseTests()
- {
- foreach (FileInfo file in new DirectoryInfo(Path.Combine(tmpPath, "valid")).GetFiles("*.xml")) {
- FullParseTest(file.FullName, true);
- }
- }
-
- [Test]
- public void FullParseTestsInvalid()
- {
- foreach (FileInfo file in new DirectoryInfo(Path.Combine(tmpPath, "invalid")).GetFiles("*.xml")) {
- FullParseTest(file.FullName, true);
- }
- }
-
- [Test]
- public void FullParseTestsNotWellformed()
- {
- foreach (FileInfo file in new DirectoryInfo(Path.Combine(tmpPath, "not-wellformed")).GetFiles("*.xml")) {
- FullParseTest(file.FullName, false);
- }
- }
-
- void FullParseTest(string fileName, bool isWellFormed)
- {
- Console.WriteLine(fileName);
- string content = File.ReadAllText(fileName);
- AXmlParser parser = new AXmlParser(content);
- parser.EntityReferenceIsError = false;
- var document = parser.Parse();
- PrettyPrintAXmlVisitor printer = new PrettyPrintAXmlVisitor();
- printer.VisitDocument(document);
-
- StringBuilder errorsOutput = new StringBuilder();
- int count = 0;
- foreach (var error in document.GetSelfAndAllChildren().SelectMany(c => c.SyntaxErrors)) {
- count++;
- errorsOutput.AppendFormat("({0}-{1}): {2}\nError at: {3}\n", error.StartOffset, error.EndOffset, error.Message, content.Substring(error.StartOffset));
- }
- if (isWellFormed && count != 0)
- Assert.Fail("Syntax error in well formed file \"{0}\":\n{1}\nFile content:\n{2}", fileName, errorsOutput.ToString(), content);
- else if (!isWellFormed && count == 0)
- Assert.Fail("No syntax error reported for mallformed file \"{0}\"\nFile Content:\n{1}", fileName, content);
-
- Assert.AreEqual(content, printer.Output, "Output of pretty printed xml for '{0}' does not match the original.\nOriginal:\n{1}\nPretty printed:\n{2}", fileName, content, printer.Output);
- }
- }
-}
diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit.Tests/XmlParser/XmlParserTests.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit.Tests/XmlParser/XmlParserTests.cs
new file mode 100644
index 0000000000..4e7987ad0c
--- /dev/null
+++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit.Tests/XmlParser/XmlParserTests.cs
@@ -0,0 +1,101 @@
+//
+//
+//
+//
+// $Revision$
+//
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Diagnostics;
+using System.IO;
+using System.Text;
+
+using ICSharpCode.AvalonEdit.Xml;
+using ICSharpCode.SharpZipLib.Zip;
+using NUnit.Framework;
+
+namespace ICSharpCode.AvalonEdit.Xml.Tests
+{
+ [TestFixture]
+ public class XmlParserTests
+ {
+ readonly string zipFileName = @"XmlParser\testcases.zip";
+
+ ZipFile zipFile;
+ List files = new List();
+
+ [TestFixtureSetUp]
+ public void OpenZipFile()
+ {
+ zipFile = new ZipFile(zipFileName);
+ files.AddRange(zipFile.Cast().Where(zip => zip.IsFile));
+ }
+
+ string Decompress(ZipEntry zipEntry)
+ {
+ byte[] data = new byte[zipEntry.Size];
+ Stream stream = zipFile.GetInputStream(zipEntry);
+ string text = new StreamReader(stream).ReadToEnd();
+ return text;
+ }
+
+ IEnumerable GetFiles(string directory)
+ {
+ return files.Where(f => f.Name.StartsWith(directory + @"/") && f.Name.EndsWith(".xml"));
+ }
+
+ [Test]
+ public void Valid()
+ {
+ foreach (ZipEntry file in GetFiles("valid")) {
+ if (file.Name == "valid/042.xml") continue; // Long entity reference
+ if (file.Name == "valid/056.xml") continue; // Long entity reference
+ ParseTest(file, true);
+ }
+ }
+
+ [Test]
+ public void Invalid()
+ {
+ foreach (ZipEntry file in GetFiles("invalid")) {
+ ParseTest(file, true);
+ }
+ }
+
+ [Test]
+ [Ignore("Unfinished")]
+ public void NotWellformed()
+ {
+ foreach (ZipEntry file in GetFiles("not-wellformed")) {
+ ParseTest(file, false);
+ }
+ }
+
+ void ParseTest(ZipEntry zipEntry, bool isWellFormed)
+ {
+ string fileName = zipEntry.Name;
+ System.Diagnostics.Debug.WriteLine("\nTesting " + fileName + "...");
+ string content = Decompress(zipEntry);
+ AXmlParser parser = new AXmlParser(content);
+ parser.EntityReferenceIsError = false;
+ var document = parser.Parse();
+ string printed = PrettyPrintAXmlVisitor.PrettyPrint(document);
+
+ int errorCount = 0;
+ StringBuilder errorsOutput = new StringBuilder();
+ foreach (var error in document.SyntaxErrors) {
+ errorCount++;
+ string followingText = content.Substring(error.StartOffset, Math.Min(16, content.Length - error.StartOffset));
+ errorsOutput.AppendFormat("Error ({0}-{1}): {2}\nFollowing text: {3}\n", error.StartOffset, error.EndOffset, error.Message, followingText);
+ }
+ if (isWellFormed && errorCount != 0)
+ Assert.Fail("Syntax error(s) in well formed file \"{0}\":\n{1}File content:\n{2}\n\n", fileName, errorsOutput, content);
+ if (!isWellFormed && errorCount == 0)
+ Assert.Fail("No syntax error reported for mallformed file \"{0}\"\nFile Content:\n{1}\n\n", fileName, content);
+
+ Assert.AreEqual(content, printed, "Output of pretty printed XML for \"{0}\" does not match the original.", fileName);
+ }
+ }
+}
diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/AXmlTag.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/AXmlTag.cs
index 236610152f..c96c323ac3 100644
--- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/AXmlTag.cs
+++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/AXmlTag.cs
@@ -71,9 +71,6 @@ namespace ICSharpCode.AvalonEdit.Xml
Assert(OpeningBracket != null, "Null OpeningBracket");
Assert(Name != null, "Null Name");
Assert(ClosingBracket != null, "Null ClosingBracket");
- foreach(AXmlObject child in this.Children) {
- Assert(child is AXmlText || child is AXmlAttribute, "Only attribute or text children allowed");
- }
base.DebugCheckConsistency(checkParentPointers);
}
diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/PrettyPrintAXmlVisitor.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/PrettyPrintAXmlVisitor.cs
index 5a8a693da4..02b2d4250d 100644
--- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/PrettyPrintAXmlVisitor.cs
+++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/PrettyPrintAXmlVisitor.cs
@@ -26,6 +26,14 @@ namespace ICSharpCode.AvalonEdit.Xml
}
}
+ /// Create XML text from a document
+ public static string PrettyPrint(AXmlDocument doc)
+ {
+ PrettyPrintAXmlVisitor visitor = new PrettyPrintAXmlVisitor();
+ visitor.VisitDocument(doc);
+ return visitor.Output;
+ }
+
/// Visit RawDocument
public override void VisitDocument(AXmlDocument document)
{
diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/TagMatchingHeuristics.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/TagMatchingHeuristics.cs
index 216c528eb3..f425f3256e 100644
--- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/TagMatchingHeuristics.cs
+++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/TagMatchingHeuristics.cs
@@ -151,10 +151,10 @@ namespace ICSharpCode.AvalonEdit.Xml
IEnumerable Split(AXmlElement elem)
{
int myIndention = GetIndentLevel(elem);
- // If has virtual end and is indented
- if (!elem.HasEndTag && myIndention != -1) {
+ // Has start tag and no end tag ? (other then empty-element tag)
+ if (elem.HasStartOrEmptyTag && elem.StartTag.IsStartTag && !elem.HasEndTag && myIndention != -1) {
int lastAccepted = 0; // Accept start tag
- while (lastAccepted + 1 < elem.Children.Count - 1 /* no end tag */) {
+ while (lastAccepted + 1 < elem.Children.Count) {
AXmlObject nextItem = elem.Children[lastAccepted + 1];
if (nextItem is AXmlText) {
lastAccepted++; continue; // Accept
@@ -168,15 +168,15 @@ namespace ICSharpCode.AvalonEdit.Xml
}
}
// Accepted everything?
- if (lastAccepted + 1 == elem.Children.Count - 1) {
+ if (lastAccepted + 1 == elem.Children.Count) {
yield return elem;
yield break;
}
- AXmlParser.Log("Splitting {0} - take {1} of {2} nested", elem, lastAccepted, elem.Children.Count - 2);
+ AXmlParser.Log("Splitting {0} - take {1} of {2} nested", elem, lastAccepted, elem.Children.Count - 1);
AXmlElement topHalf = new AXmlElement();
topHalf.HasStartOrEmptyTag = elem.HasStartOrEmptyTag;
topHalf.HasEndTag = elem.HasEndTag;
- topHalf.AddChildren(elem.Children.Take(lastAccepted + 1)); // Start tag + nested
+ topHalf.AddChildren(elem.Children.Take(1 + lastAccepted)); // Start tag + nested
topHalf.StartOffset = topHalf.FirstChild.StartOffset;
topHalf.EndOffset = topHalf.LastChild.EndOffset;
TagReader.OnSyntaxError(topHalf, topHalf.LastChild.EndOffset, topHalf.LastChild.EndOffset,
@@ -185,7 +185,7 @@ namespace ICSharpCode.AvalonEdit.Xml
AXmlParser.Log("Constructed {0}", topHalf);
trackedSegments.AddParsedObject(topHalf, null);
yield return topHalf;
- for(int i = lastAccepted + 1; i < elem.Children.Count - 1; i++) {
+ for(int i = lastAccepted + 1; i < elem.Children.Count; i++) {
yield return elem.Children[i];
}
} else {
diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/TagReader.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/TagReader.cs
index 400baf09bc..76fa5bbc78 100644
--- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/TagReader.cs
+++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/TagReader.cs
@@ -103,6 +103,8 @@ namespace ICSharpCode.AvalonEdit.Xml
OnSyntaxError(tag, "Element name expected");
}
tag.Name = name;
+ } else {
+ tag.Name = string.Empty;
}
if (tag.IsStartOrEmptyTag || tag.IsEndTag) {
@@ -429,7 +431,7 @@ namespace ICSharpCode.AvalonEdit.Xml
}
const int maxEntityLength = 12; // The longest build-in one is 10 ("")
- const int maxTextFragmentSize = 8;
+ const int maxTextFragmentSize = 64;
const int lookAheadLenght = (3 * maxTextFragmentSize) / 2; // More so that we do not get small "what was inserted" fragments
///