Подтвердить что ты не робот

Как сделать глубокую копию элемента в LINQ to XML?

Я хочу сделать глубокую копию LINQ to XML XElement. Причина, по которой я хочу это сделать, - это некоторые узлы в документе, которые я хочу создать измененные копии (в том же документе). Я не вижу метода для этого.

Я мог бы преобразовать элемент в строку XML, а затем повторить его, но мне интересно, есть ли лучший способ.

4b9b3361

Ответ 1

Нет необходимости переписывать. Один из конструкторов 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);
}

Ответ 2

Похоже, что метод ToString и reparse - лучший способ. Вот код:

XElement copy = XElement.Parse(original.ToString());

Ответ 3

Поднят непосредственно из С# 3.0 в двух словах:

Когда к элементу добавляется node или атрибут (через функциональную конструкцию или метод Add), свойство node или атрибут Parent устанавливается в этот элемент. A node может иметь только один родительский элемент: если вы добавите уже родившийся node ко второму родительскому элементу, node будет автоматически глубоко клонирован. В следующем примере каждый клиент имеет отдельную копию адреса:

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 без побочных эффектов - еще один признак функционального программирования.

Ответ 4

Это должно работать:

var copy = new XElement(original.Name, original.Attributes(),
                        original.Elements() );

Ответ 5

Я не верю, что существует существующий механизм, который позволяет вам выполнять глубокую копию дерева стилей XNode. Я думаю, у вас осталось два варианта.

  • Сделайте так, как вы предложили преобразовать в строку, а затем вернуться в дерево
  • Напишите на себя с шаблоном посетителя.

Шаблон посетителя, безусловно, возможен, но для его тестирования потребуется много работы. Я думаю, что ваш лучший вариант - № 1.