Search code examples
c#xmldocument

Why XmlDocument declaration variable A change when B XmlDocument declared variable is modified?


I receive a base XML file, I need to create N XmlFiles with different content values. basically I do a copy, change some node values and create the new file without modifying the base one.

I add every XML document to a list of documents to do other processes and then to interact and create the N Files. after my code executes I end up with all the files having the same info, even the base one is modified. I create a basic code to demonstrate it. thanks for any explanation about why is it happening.

    // file1.xml
<?xml version="1.0" encoding="UTF-16"?>
<BOM>
    <BO>
        <AdmInfo>
            <Object>2</Object>
            <Version>2</Version>
        </AdmInfo>
        <BusinessPartners>
            <row>
                <CardCode>111111</CardCode>
                <CardName>MADERAS DE AGUADULCE, S.A</CardName>
                <GroupCode>P-Locales</GroupCode>
            </row>
        </BusinessPartners>

    </BO>
</BOM>
// C# code - method that change the value into the xmlFile.
     public XmlDocument ChangeValues(XmlDocument document, List<Tuple<string, string>> AtriValues )
        {

            XmlDocument NewXMLDocument = new XmlDocument();
            // pass the content to another XmlDocument 

            NewXMLDocument = document;

            foreach (var Atribute in AtriValues)
            {
                XmlElement root = NewXMLDocument.DocumentElement;
                XmlNodeList elemList = root.GetElementsByTagName(Atribute.Item1.ToString());
                IEnumerator ienum = elemList.GetEnumerator();
                while (ienum.MoveNext())
                {
                    XmlNode title = (XmlNode)ienum.Current;
                    // Console.WriteLine(title.InnerText);
                    title.InnerText = Atribute.Item2.ToString();

                    //xn[Atribute.Item1.ToString()].InnerText = Atribute.Item2.ToString();
                }
            }

            return NewXMLDocument;
        }
    // C# code- the main prg
static void Main(string[] args)
        {
            Util2 Util = new Util2();
            List<XmlDocument> Documents = new List<XmlDocument>();
            XmlDocument  xmlDocument = new XmlDocument();



            // load the XML file 
            xmlDocument.Load(@"C:\WIP\BaSe\TEST\file1.xml");

            // Save the base file 
            Documents.Add(xmlDocument);

            // Change the content of the document to create document A

            List<Tuple<string, string>> AtriValuesA = new List<Tuple<string, string>>();

            AtriValuesA.Add(new Tuple<string, string>("CardCode", "9999"));
            AtriValuesA.Add(new Tuple<string, string>("GroupCode", "AA"));

            Documents.Add(Util.ChangeValues(xmlDocument, AtriValuesA));




            // Change the content of the document to create document B

            List<Tuple<string, string>> AtriValuesB = new List<Tuple<string, string>>();

            AtriValuesB.Add(new Tuple<string, string>("CardCode", "2222"));
            AtriValuesB.Add(new Tuple<string, string>("GroupCode", "BB"));

            Documents.Add(Util.ChangeValues(xmlDocument, AtriValuesB));


            // get the document and then save then 

            Documents[0].Save(@"C:\WIP\BaSe\TEST\base.xml");
            Documents[1].Save(@"C:\WIP\BaSe\TEST\DOCA.xml");
            Documents[2].Save(@"C:\WIP\BaSe\TEST\DOCB.xml");

        }



Solution

  • When you use NewXMLDocument = document; you are assigning a reference to the original XmlDocument object, so any changes apply to the original object.

    Instead of assigning a reference, you need to clone the original object. I think you want something like this:

    public XmlDocument ChangeValues(XmlDocument document, List<Tuple<string, string>> AtriValues )
    {
      // Create the new document using the contents of the existing document.
      XmlDocument NewXMLDocument = (XmlDocument)document.CloneNode(true);
    
      foreach (var Atribute in AtriValues)
      {
        XmlElement root = NewXMLDocument.DocumentElement;
        XmlNodeList elemList = root.GetElementsByTagName(Atribute.Item1.ToString());
        IEnumerator ienum = elemList.GetEnumerator();
        while (ienum.MoveNext())
        {
          XmlNode title = (XmlNode)ienum.Current;
          // Console.WriteLine(title.InnerText);
          title.InnerText = Atribute.Item2.ToString();
    
          //xn[Atribute.Item1.ToString()].InnerText = Atribute.Item2.ToString();
        }
      }
      return NewXMLDocument;
    }
    

    See https://learn.microsoft.com/en-us/dotnet/api/system.xml.xmldocument.clonenode