Как сделать глубокую копию элемента в LINQ to XML? - PullRequest
62 голосов
/ 16 октября 2008

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

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

Ответы [ 5 ]

117 голосов
/ 10 декабря 2008

Нет необходимости в повторной обработке. Один из конструкторов 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);
}
8 голосов
/ 16 октября 2008

Похоже, метод ToString и метод повторного анализа - лучший способ. Вот код:

XElement copy = XElement.Parse(original.ToString());
3 голосов
/ 17 октября 2008

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

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

0 голосов
/ 16 августа 2013

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

var copy = new XElement(original.Name, original.Attributes(),
                        original.Elements() );
0 голосов
/ 16 октября 2008

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...