【问题标题】:Why XmlDocument declaration variable A change when B XmlDocument declared variable is modified?为什么 XmlDocument 声明变量 A 改变时 B XmlDocument 声明变量被修改?
【发布时间】:2020-05-20 15:11:27
【问题描述】:

我收到一个基本 XML 文件,我需要创建 N 个具有不同内容值的 XmlFiles。基本上我会 一个副本,更改一些节点值并创建新文件而不修改基础文件。

我将每个 XML 文档添加到文档列表中以执行其他过程,然后进行交互并创建 N 个文件。 在我的代码执行之后,我最终得到了所有具有相同信息的文件,即使是基础文件也被修改了。 我创建了一个基本代码来演示它。感谢您解释为什么会发生这种情况。

    // 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");

        }


【问题讨论】:

    标签: c# xmldocument


    【解决方案1】:

    所有文件都在更改,因为您正在更改 ChangeValues 函数中的原始 xml 文档。下面的分配(新文档)无效,因为您正在将原始文档的引用分配给它。

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

    我想到的最快的解决方案是首先使用File.Copy 函数将原始文件复制到新文件名。 之后,只需将新文件加载到文档中并进行更改。

    按照您的示例,代码将如下所示:

    var baseFile = @"C:\WIP\BaSe\TEST\base.xml";
    
    var doc1 =  @"C:\WIP\BaSe\TEST\DOCA.xml";
    var doc2 =  @"C:\WIP\BaSe\TEST\DOCB.xml";
    
    File.Copy(baseFile, doc1);
    File.Copy(baseFile, doc2);
    
    // you might copy this to other function.
    
    XmlDocument  xmlDocument1 = new XmlDocument();
    xmlDocument1.Load(doc1);
    
    Util.ChangeValues(xmlDocument1, AtriValuesA);
    
    xmlDocument1.Save(doc1);
    

    【讨论】:

    • 感谢您的建议,我保存文件是为了演示我面临的问题,但文件永远不会保存到磁盘(我允许 reed 但不允许在磁盘上写入server host "), 有一个服务消耗最终的文档对象(包含列表中存储的所有 XML 文档)。有没有办法在不影响原始文档的情况下克隆它?
    • 那么它应该更容易。您可以将同一个文件读入不同的对象 - 这是简单的克隆。
    • 我这样做了,将所有相同的文件添加到 de list 我需要的所有时间,然后使用函数更改值,但我得到了相同的结果,因为它改变了第一个其他对象受到影响。即 = Documents.Add(Util.ChangeValues(Documents[1], AtriValuesA));
    【解决方案2】:

    当您使用NewXMLDocument = document; 时,您正在分配对原始 XmlDocument 对象的引用,因此任何更改都适用于原始对象。

    您需要克隆原始对象,而不是分配引用。我想你想要这样的东西:

    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;
    }
    

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

    【讨论】:

    • 谢谢,WileCau,您的贡献为我指明了正确的方向。我按照你的建议在函数 ChangeValues 上使用了它,我得到了同样的错误结果。但是在将其发送到函数之前使用它可以完美地工作。我以为我必须处理通过 val 或 ref 传递 var。但我不知道该怎么做。但这个解决方案也有效。
    • 发送到函数的行最终是这样的。 Documents.Add(Util.ChangeValues((XmlDocument)xmlDocument.CloneNode(true), AtriValuesA));
    猜你喜欢
    • 2017-08-06
    • 1970-01-01
    • 1970-01-01
    • 2020-09-04
    • 2014-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多