// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System; using System.Collections.Generic; using System.IO; using System.Text; using System.Xml; using System.Xml.Linq; using CoreXml.Test.XLinq; using Microsoft.Test.ModuleCore; using XmlCoreTest.Common; using Xunit; namespace XLinqTests { public class SaveWithFileName { [Fact] public void XDocumentSaveToFile() { SerializeWithSaveOptions(SerializeXDocumentSaveToFile, testXElement: false, testXDocument: true); } [Fact] public void XDocumentSave() { string markup = " "; using (TempFile temp = TempFile.Create()) { XDocument d = XDocument.Parse(markup, LoadOptions.PreserveWhitespace); d.Save(temp.Path); temp.AssertExists(); Assert.Equal("" + markup, NormalizeNewLines(temp.ReadAllText())); } } [Fact] public void XDocumentSave_SaveOptions() { string markup = " "; using (TempFile temp = TempFile.Create()) { XDocument d = XDocument.Parse(markup, LoadOptions.PreserveWhitespace); d.Save(temp.Path, SaveOptions.DisableFormatting); temp.AssertExists(); Assert.Equal("" + markup, temp.ReadAllText()); } } [Fact] public void XDocumentSave_NullParameter() { Assert.Throws(() => new XDocument().Save((string)null)); Assert.Throws(() => new XDocument().Save((string)null, SaveOptions.DisableFormatting)); Assert.Throws(() => new XDocument().Save((string)null, SaveOptions.None)); } [Fact] public void XElementSaveToFile() { SerializeWithSaveOptions(SerializeXElementSaveToFile, testXElement: true, testXDocument: false); } [Fact] public void XElementSave() { string markup = " "; using (TempFile temp = TempFile.Create()) { XElement e = XElement.Parse(markup, LoadOptions.PreserveWhitespace); e.Save(temp.Path); temp.AssertExists(); Assert.Equal("" + markup, NormalizeNewLines(temp.ReadAllText())); } } [Fact] public void XElementSave_SaveOptions() { string markup = " "; using (TempFile temp = TempFile.Create()) { XElement e = XElement.Parse(markup, LoadOptions.PreserveWhitespace); e.Save(temp.Path, SaveOptions.DisableFormatting); temp.AssertExists(); Assert.Equal("" + markup, temp.ReadAllText()); } } [Fact] public void XElementSave_NullParameter() { Assert.Throws(() => new XElement("e").Save((string)null)); Assert.Throws(() => new XElement("e").Save((string)null, SaveOptions.DisableFormatting)); Assert.Throws(() => new XElement("e").Save((string)null, SaveOptions.None)); } [Fact] public void XStreamingElementSave_NullParameter() { Assert.Throws(() => new XStreamingElement("e").Save((string)null)); Assert.Throws(() => new XStreamingElement("e").Save((string)null, SaveOptions.DisableFormatting)); Assert.Throws(() => new XStreamingElement("e").Save((string)null, SaveOptions.None)); } [Fact] public void XStreamingElementSave() { string markup = " "; using (TempFile temp = TempFile.Create()) { XElement e = XElement.Parse(markup, LoadOptions.PreserveWhitespace); XStreamingElement e2 = new XStreamingElement(e.Name, e.Attributes(), e.Nodes()); e2.Save(temp.Path); temp.AssertExists(); Assert.Equal("" + markup, NormalizeNewLines(temp.ReadAllText())); } } [Fact] public void XStreamingElementSave_SaveOptions() { string markup = " "; using (TempFile temp = TempFile.Create()) { XElement e = XElement.Parse(markup, LoadOptions.PreserveWhitespace); XStreamingElement e2 = new XStreamingElement(e.Name, e.Attributes(), e.Nodes()); e2.Save(temp.Path, SaveOptions.DisableFormatting); temp.AssertExists(); Assert.Equal("" + markup, temp.ReadAllText()); } } // // helpers // private static string SerializeXDocumentSaveToFile(XNode node) { string result; using (TempFile temp = TempFile.Create()) { ((XDocument)node).Save(temp.Path); using (TextReader tr = new StreamReader(temp.Path)) { result = StripOffXmlDeclaration(tr.ReadToEnd()); } temp.AssertExists(); } return result; } private static string SerializeXElementSaveToFile(XNode node) { string result; using (TempFile temp = TempFile.Create()) { ((XElement)node).Save(temp.Path); using (TextReader tr = new StreamReader(temp.Path)) { result = StripOffXmlDeclaration(tr.ReadToEnd()); } temp.AssertExists(); } return result; } private delegate string SerializeNode(XNode node); private static void SerializeWithSaveOptions(SerializeNode serialize, bool testXElement, bool testXDocument) { // Test both options at once as they don't really collide SaveOptions so = SaveOptions.DisableFormatting | SaveOptions.OmitDuplicateNamespaces; XElement root = XElement.Parse("text"); XElement child = root.Element("child"); XElement baby = child.Element("baby"); XNode text = baby.FirstNode; // Verify that without annotation the output gets indented and the duplicate ns decls are not removed if (testXElement) { Assert.Equal(NormalizeNewLines(serialize(child)), " text"); } // Now add annotation to the leaf element node // Even though it's in effect the output should stay the same (as there is only one namespace decl and mixed content). baby.AddAnnotation(so); if (testXElement) { Assert.Equal(serialize(baby), "text"); } // Now add annotation to the middle node child.AddAnnotation(so); if (testXElement) { // Verify that the options are applied correctly Assert.Equal(NormalizeNewLines(serialize(child)), "text"); // Verify that the root node is not affected as we don't look for the annotation among descendants Assert.Equal(NormalizeNewLines(serialize(root)), " text "); } // And now add the annotation to the root and remove it from the child to test that we can correctly skip over a node root.AddAnnotation(so); child.RemoveAnnotations(typeof(SaveOptions)); if (testXElement) { // Verify that the options are still applied to child Assert.Equal(serialize(child), "text"); // And they should be also applied to the root now Assert.Equal(serialize(root), "text"); } // Add a document node above it all to test that it works on non-XElement as well XDocument doc = new XDocument(root); // Add the annotation to the doc and remove it from the root doc.AddAnnotation(so); root.RemoveAnnotations(typeof(SaveOptions)); // Options should still apply to root as well as the doc if (testXElement) { Assert.Equal(serialize(root), "text"); } if (testXDocument) { Assert.Equal(serialize(doc), "text"); } } private static string StripOffXmlDeclaration(string s) { if (s.StartsWith("') + 1); if (s.StartsWith("\r\n")) { s = s.Substring(2); } } return s; } private static string NormalizeNewLines(string s) { s = s.Replace("\n", ""); s = s.Replace("\r", ""); return s; } } }