anjel
anjel

Reputation: 1376

append cloned node to same xml document

Am trying to append a clone node lets say

<Property Id="3" Name="Deadline"></Property>

into the same document with class name "AlphaCertificationsIndividual" but the compiler gives me this error: The node to be inserted is from a different document context

<Root>
  <Class Name="ECMInstruction" Style="Top">
    <Entity Id="1" Name="DocumentInformation" />
    <Entity Id="2" Name="CustomerInformation" />
    <Property Id="1" Name="DocumentTitle">
    </Property>
    <Property Id="2" Name="DateCreated">
      <Lists>
        <ListName>ws_Users</ListName>
        <ListName>dfdfdfd</ListName>
      </Lists>
    </Property>
    <Property Id="3" Name="Deadline">
    </Property>
  </Class>
  <Class Name="AlphaCertificationsIndividual" Style="Top">
    <Entity Id="1" Name="DocumentInformation" />
    <Property Id="1" Name="DocumentTitle">
    </Property>
    <Property Id="2" Name="DateCreated">
      <Lists>
        <ListName>ws_Users</ListName>
        <ListName>dfdfdfd</ListName>
      </Lists>
    </Property>
    <Property Id="3" Name="Deadline">
    </Property>
  </Class>
</Root>

the code am using:

    XmlDocument xmldoc = new XmlDocument();
    xmldoc.Load("sample.xml");
    foreach (string id in properties)
    {
        XmlNode props = xmldoc.DocumentElement.SelectSingleNode("//Class[@Name='" + curClass + "']/Property[@Id='" + id + "']");

        XmlNode cloneNode = props.CloneNode(true);

        foreach (var item in dcList.SelectedItems)
        {
            XmlNodeList classes = commonMethods.LoadDocument(xml).DocumentElement.SelectNodes("//Class[@Name='" + item + "']/Property[last()]");
            foreach (XmlNode c in classes)
            {
                String propertyid = c.Attributes["Id"].Value.ToString();
                int.TryParse(propertyid, out value);
                value = value + 1;
                cloneNode.Attributes["Id"].Value = value.ToString();
                c.ParentNode.AppendChild(xmldoc.ImportNode(cloneNode,true));
                xmldoc.Save("sample.xml");
            }
        }
    }

Upvotes: 0

Views: 2280

Answers (2)

Matthijs
Matthijs

Reputation: 3170

I took the liberty of rewriting your code to an extension method which allows you to put in the fileName, originalClassName, newClassName, the name of the node to copy and its ID-attributevalue.

public static bool CopyNode(string fileName, string originalClassName, string newClassName, string nodeName, string ID)
{
    XDocument doc = XDocument.Load(fileName);

    if(doc == null)
        throw new ArgumentNullException("doc");

    XElement originalClassElement = doc.Root.Descendants().FirstOrDefault(e => e.Name == "Class" && e.Attribute("Name").Value == originalClassName);
    if (originalClassElement == null)
        return false;

    XElement elementToCopy = originalClassElement.Elements().FirstOrDefault(e => e.Name == nodeName && e.Attribute("Id").Value == ID);
    if (elementToCopy == null)
        return false;

    XElement newClassElement = doc.Root.Descendants().FirstOrDefault(e => e.Name == "Class" && e.Attribute("Name").Value == newClassName);
    if (newClassElement == null)
        return false;

    newClassElement.Add(elementToCopy);
    doc.Save(fileName);
    return true;
}

The method returns true if the node has been copied correctly. You have gained some extensibility and can copy nodes to and from classes with any names; and also any nodes you want to copy (note that they do have to have an ID).

Upvotes: 0

Drazen
Drazen

Reputation: 66

I'm not sure if it's a typo, but it seems that you are calling the commonMethods.LoadDocument method on a variable called xml and get classes variable. Then, ImportNode is being called on the xmlDoc before appending. Node needs to be imported into the document object that the child will be appended to. So, you should be importing into xmlDoc, if you want to append to xmlDoc.

Upvotes: 1

Related Questions