0

I am trying to create nested xml elements to look like below however the created file only contains the first element from headingTags and then the first foreach loop is exited. Why is this happening?

<?xml version="1.0"?>
<ProductProfile>
    <ProfileVersion>input</ProfileVersion>
        <ProductInformation>
            <ApplicableProducts>input</ApplicableProducts>
            <ProductDescription>input</ProductDescription>
        </ProductInformation>
        <CustomerInformation>
            <Name>input</Name>
        </CustomerInformation>
        <ProductionSettings>
            <LabelType>input</LabelType>
            <LabelQuantity>input</LabelQuantity>
            <Settings>
                <SettingsSRegisters>input</SettingsSRegisters>
            </Settings>
        </ProductionSettings>
        <PostProduction>
            <ActivationStatus>input</ActivationStatus>
        </PostProduction>
</ProductProfile>

This has only started happening since I added the line tw.WriteEndElement(); after the first foreach. Without this line all of the end of elements were at the end of the file.

My code:

 Dictionary<string, int> tagNames = new Dictionary<string, int>()
{
    {"ProfileVersion", 0},
    {"ApplicableProducts", 1},
    {"ProductDescription", 1},
    {"Name", 2},
    {"LabelType", 3},
    {"LabelQuantity", 3},
    {"SettingsSRegisters", 4},
    {"ActivationStatus", 5}
};
    
public enum headingTags
{
    ProductProfile,     //0
    ProductInformation, //1
    CustomerInformation,//2
    ProductionSettings, //3
    Settings,           //4
    PostProduction      //5
}
public void SaveProfile_Click(object sender, RoutedEventArgs e)
{
    using (XmlTextWriter tw = new XmlTextWriter(path, Encoding.UTF8))
    {
        tw.Formatting = Formatting.Indented;
        // Opens the document  
        tw.WriteStartDocument();
        //tw.WriteComment("Configuration File");

        foreach (int headingValue in Enum.GetValues(typeof(dataTags.headingTags)))
        {
            MessageBox.Show("Heading value does not match Tag name" + headingValue + " " );
            string headingString = Enum.GetName(typeof(dataTags.headingTags), headingValue);

            // Write heading element  
            tw.WriteStartElement(headingString);
            tw.WriteString(txtSettingsSRegisters.Text);
            foreach (KeyValuePair<string, int> dictLine in tagNames)
            {
                if (headingValue == dictLine.Value)
                {
                    tw.WriteStartElement(dictLine.Key, "");
                    tw.WriteString("TextBoxInput");
                    tw.WriteEndElement();
                    tw.WriteWhitespace("/n");
                }
                else
                {
                    //MessageBox.Show("Heading value does not match Tag name" + headingValue + " " + dictLine.Value);
                }
            }
            //tw.WriteEndElement();
        }
        tw.WriteEndDocument();
        // close writer  
        tw.Close();
    }
}

UPDATE: I added a try catch to find the exception being thrown Error:Token StartElement in state Epilog would result in an invalid XML document. and just added this line after the foreach (int headingValue in Enum.GetValues(typeof(dataTags.headingTags))) to implement the correct format.

if (j != 0) { 
                            tw.WriteEndElement();
                        }
Ellak123
  • 25
  • 6
  • Ah I have fixed that typo now but when I include the line `tw.WriteEndElement();` it still exits the loop after the first element (`settingsTextBoxInput `) – Ellak123 Mar 28 '22 at 10:31
  • 1
    Are there any exceptions being thrown? – moreON Mar 28 '22 at 10:43
  • None at all as it creates the file and writes the first element then the form just closes. – Ellak123 Mar 28 '22 at 10:45
  • That was more of a hint than a question. It looked like a question, but I was being dishonest and hoping you would investigate the issue more thoroughly yourself. There is something happening that does throw an exception in there. – moreON Mar 28 '22 at 10:47
  • Thanks for pointing that out I should have thought to do that before posting. Added some try-catches to my code and found the exception `Error:Token StartElement in state Epilog would result in an invalid XML document.`. I will search around for fixes – Ellak123 Mar 28 '22 at 11:11
  • I'd strongly advise against using `XmlWriter` directly. It's a very low level API and it's very easy to make mistakes (as you've found). Consider creating your document using the LINQ to XML model instead. – Charles Mager Mar 28 '22 at 14:48
  • Hi Charles, I was trying to stick with c# as it is what I know but I will look into learning LINQ. I think I have found a way around it for now but if I run into more problems I will consider changing to LINQ instead. – Ellak123 Mar 28 '22 at 14:54
  • @Ellak123 LINQ is part of C#, and has been since 2007. See [this](https://learn.microsoft.com/en-us/dotnet/standard/linq/create-xml-trees) for an idea what the usage might look like. – Charles Mager Mar 29 '22 at 13:23
  • Ah I see now.. thanks for the direction @CharlesMager – Ellak123 Mar 29 '22 at 13:59

0 Answers0