为什么 XmlDocument 声明的变量 A 在修改 B XmlDocument 声明的变量时发生变化?
Why XmlDocument declaration variable A change when B XmlDocument declared variable is modified?
我收到一个基础 XML 文件,我需要创建 N 个具有不同内容值的 XmlFile。基本上我做
一个副本,更改一些节点值并在不修改基础文件的情况下创建新文件。
我将每个 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");
}
所有文件都在更改,因为您正在更改 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);
当您使用 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
我收到一个基础 XML 文件,我需要创建 N 个具有不同内容值的 XmlFile。基本上我做 一个副本,更改一些节点值并在不修改基础文件的情况下创建新文件。
我将每个 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");
}
所有文件都在更改,因为您正在更改 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);
当您使用 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