我想制作一个LINQ to XML XElement的深层副本。我想这样做的原因是文档中有一些节点我想创建(在同一文档中)的修改副本。我没有看到这样做的方法。
我可以将元素转换为XML字符串,然后重新解析它,但我想知道是否有更好的方法。
答案 0 :(得分:117)
无需重新分析。 XElement的一个构造函数接受另一个XElement并对其进行深层复制:
XElement original = new XElement("original");
XElement deepCopy = new XElement(original);
以下是一些单元测试来证明:
[TestMethod]
public void XElementShallowCopyShouldOnlyCopyReference()
{
XElement original = new XElement("original");
XElement shallowCopy = original;
shallowCopy.Name = "copy";
Assert.AreEqual("copy", original.Name);
}
[TestMethod]
public void ShouldGetXElementDeepCopyUsingConstructorArgument()
{
XElement original = new XElement("original");
XElement deepCopy = new XElement(original);
deepCopy.Name = "copy";
Assert.AreEqual("original", original.Name);
Assert.AreEqual("copy", deepCopy.Name);
}
答案 1 :(得分:8)
看起来像ToString和重新分析方法是最好的方法。这是代码:
XElement copy = XElement.Parse(original.ToString());
答案 2 :(得分:3)
将节点或属性添加到元素(无论是通过功能构造还是Add方法)时,节点或属性的Parent属性将设置为该元素。一个节点只能有一个父元素:如果将已有父节点添加到第二个父节点,则会自动深度克隆该节点。在以下示例中,每个客户都有一个单独的地址副本:
var address = new XElement ("address",
new XElement ("street", "Lawley St"),
new XElement ("town", "North Beach")
);
var customer1 = new XElement ("customer1", address);
var customer2 = new XElement ("customer2", address);
customer1.Element ("address").Element ("street").Value = "Another St";
Console.WriteLine (
customer2.Element ("address").Element ("street").Value); // Lawley St
这种自动复制使X-DOM对象实例化无副作用 - 这是函数式编程的另一个标志。
答案 3 :(得分:0)
这应该有效:
var copy = new XElement(original.Name, original.Attributes(),
original.Elements() );
答案 4 :(得分:-2)
我不相信存在允许您执行XNode样式树的深层副本的现有机制。我认为你有两种选择。
访客模式当然是可能的,但是需要大量的工作才能进行测试。我认为你最好的选择是#1。