tags:

views:

461

answers:

4

I have an XmlWriter as follows

XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
settings.NewLineHandling = NewLineHandling.Entitize;
using (XmlWriter currentWriter = XmlWriter.Create(filePath, settings))
{
    workingXmlDocument.WriteTo(currentWriter);
    currentWriter.Flush();
} // using (XmlWriter xw = XmlWriter.Create(FilePath))

I have programmatically created an Xml Document that I am trying to write with this, and it is writting just fine, except that I have a block of elements that are created in a loop and it is putting all these elements onto one line. If you need to see any other code from the program let me know and I can put it here. I welcome any ideas even if they aren't full solutions.

Update - the complete method where the problem is happening

private void XMLReaderUtil(string filePath)
    {
        XDocument workingXmlDocument;

        using (XmlReader currentReader = XmlReader.Create(filePath))
        {

            workingXmlDocument = XDocument.Load(currentReader);

            foreach (KeyValuePair<string, string> currentIteration in logDataRaw)
            {
                FileInfo currentEntry = new FileInfo(currentIteration.Value);

                string testString = currentEntry.Directory.Name;

                if (testString.Contains(" ")) { testString = testString.Replace(" ", "_"); }

                IEnumerable<XElement> list = from XElement e in workingXmlDocument.Descendants(wixNS + testString)
                                             select e;

                DirectoryInfo temp = currentEntry.Directory;

                while (list.Count() == 0 && !temp.Name.Contains(":"))
                {
                    testString = temp.Name;

                    if (testString.Contains(" ")) { testString = testString.Replace(" ", "_"); }

                    list = from XElement e in workingXmlDocument.Descendants(wixNS + testString)
                           select e;
                    temp = temp.Parent;
                } // while (list.Count() == 0 && !temp.Name.Contains(":"))

                if (list.Count() == 0)
                {
                    IEnumerable<XElement> targetDirectory =
                        from XElement e in workingXmlDocument.Descendants(wixNS + "Directory")
                        where e.Attribute("Id").Value == "TARGETDIR"
                        select e;

                    var outXml = new XElement("root");
                    foreach (var item in targetDirectory)
                    {
                        item.Add(new XElement(
                             "Directory",
                             new XAttribute("new", 1)));

                        outXml.Add(item);
                    }

                    outXml.Save(@"c:\users\adkins\desktop\temp.wxs", SaveOptions.None);

                }
            } // foreach (KeyValuePair<string, string> kvp in xmlDataChanged)
            // return workingXmlDocument;
        } // using (XmlReader sr = XmlReader.Create(FilePath))

        IEnumerable<XElement> cleanup =
            from XElement e in workingXmlDocument.Descendants(wixNS + "Directory")
            select e;
        Collection<string> keep = new Collection<string>();
        XElement[] blah;
        blah = cleanup.ToArray();

        for (int i = 0; i < blah.Length; i++)
        {
            if (!keep.Contains(blah[i].Attribute("Id").Value))
            {
                keep.Add(blah[i].Attribute("Id").Value);
            }
            else
            {
                blah[i].Remove();
            }
        }

        workingXmlDocument.Save(filePath, SaveOptions.None);

        // XMLWriter attempt
        //XmlWriterSettings settings = new XmlWriterSettings();
        //settings.Indent = true;
        //settings.IndentChars = "\t";
        //settings.NewLineHandling = NewLineHandling.Entitize;
        //settings.NewLineChars = "\n";
        //settings.CloseOutput = true;
        //settings.Encoding = System.Text.Encoding.UTF8;
        //using (XmlWriter currentWriter = XmlWriter.Create(filePath, settings))
        //{
        //    workingXmlDocument.WriteTo(currentWriter);
        //    currentWriter.Flush();
        //} // using (XmlWriter xw = XmlWriter.Create(FilePath))

        //TextWriter test run - nothing changed
        //XmlTextWriter writer = new XmlTextWriter(filePath, System.Text.Encoding.UTF8);
        //writer.Formatting = Formatting.Indented;
        //writer.IndentChar = '\t';
        //writer.Indentation = 1;

        //workingXmlDocument.WriteTo(writer);
        //writer.Flush();
        //writer.Close();

    }

Here is the complete problem method. It includes my attempts at various forms of saving the file. It is a complete mess due to my efforts to solve this problem and problems that I encountered before getting to this one. Any help would be greatly appreciated!

The variable "logDataRaw" is a dictionary containing the name of a file and the path to where it is stored. If you need any other clarification please let me know.

+1  A: 

Why not just use XElement.Save() instead of XmlWriter?

http://msdn.microsoft.com/en-us/library/bb538458.aspx

EDIT:

I just ran the following bit of code

        var xml = new XElement("root",
                               new XElement("node",
                                            new XAttribute("index", 1)
                                ),
                               new XElement("node",
                                            new XAttribute("index", 2)
                                ),
                               new XElement("node",
                                            new XAttribute("index", 3)
                                ),
                               new XElement("node",
                                            new XAttribute("index", 4)
                                )
            );

        IEnumerable<XElement> ieXml =
            from XElement e in xml.Elements()
            select e;

        var outXml = new XElement("root");
        foreach (var item in ieXml)
        {
            item.Add(new XElement(
                 "Directory",
                 new XAttribute("new", 1)));

            outXml.Add(item);
        }


        outXml.Save(@"d:\foo.xml", SaveOptions.None);

and the result is formatted

<?xml version="1.0" encoding="utf-8"?>
<root>
  <node index="1">
    <Directory new="1" />
  </node>
  <node index="2">
    <Directory new="1" />
  </node>
  <node index="3">
    <Directory new="1" />
  </node>
  <node index="4">
    <Directory new="1" />
  </node>
</root>

I don't know what you're doing differently, but this works.

Chad
@Chad: I believe the OP wants to serialize the entire document, not just an element. So, might I suggest you recomment `XDocument.Save()` instead. Though I suspect that just uses `XmlWriter` under the hood.
Jeff Yates
@Chad: I tried that with XDocument instead of XElement, but got the same output.
Adkins
@Jeff, what are the save options you are using?http://msdn.microsoft.com/en-us/library/system.xml.linq.saveoptions.aspxAs it should keep it
Chad
@Chad: XElement.Save uses XmlWriter under the hood so it doesn't fix the problem. You can look at this yourself using .NET Reflector.
Jeff Yates
@Adkins, it should maintain formatting, see my example
Chad
@Chad: I have some XML code that was created the same way and is formatted perfectly, but if you look at the second code block that I pasted, that is the one causing a problem. When I add elements in the middle through the use of a loop they are all staying on the same line.
Adkins
Yes: Just use (XElement/XDocument).Save. Don't even import System.XML :D
Rob Fonseca-Ensor
@Rob: I already tried it and the outcome was the same.
Adkins
@Chad: While it *should* work. It doesn't. Hence the OPs question. Using XmlWriter directly or via the Save method doesn't make much difference. It doesn't work in this particular scenario either way.
Jeff Yates
@Jeff, rather than criticizing my responses, you could attempt to be useful and look for a solution... as criticizing me, doesn't help Adkins at all
Chad
@Adkins, I changed the code again, to be more similar to what you are doing. The key difference is in your foreach loop, add the "now" variable to an XElement (or XDocument) and save that. I don't understand why you're using an IEnumerable of XElements instead of an XElement with child XElements
Chad
@Chad: I'm sorry. I wasn't criticizing you, personally. I was merely responding to your points and highlighting that the call did the same thing. I have been helping Adkins (I even suggested he raise this question) and I was stuck. I'm sorry that you took it personally when I pointed out this solution wouldn't work.
Jeff Yates
I have updated my post to include the entire method that is causing the problem. I have left in the XMLTextWriter attempt, and the XMLWriter attempt. I am not sure where the problem is coming from. Thank you so much for your continued help and thought into this problem.
Adkins
A: 

Use XmlTextWriter and the XmlTextWriter.Indendation property.

http://msdn.microsoft.com/en-us/library/system.xml.xmltextwriter.aspx

Moron
@Moron: I tried that but it didn't make any difference. Thanks for the idea though.
Adkins
A: 

You might just need to use an XmlTextWriter with default encoding instead of XmlWriter and set the Formatting property of the Writer object to Formatting.Indented

SubPortal
I have tried that. I updated my code to show what all I have tried for saving.
Adkins
+1  A: 

The problem was that I was loading the XML file through an XMLReader. Once I removed that and just loaded it directly into my XDocument than everything worked fine.

Adkins