Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linq to XML - remove a node and add a new node at same place

Tags:

linq-to-xml

I have an XDocument and have to remove a node and add the very same node back again after some manipulation(my xelement node are complex and have inner nodes as well). Has anyone got a good way to do this as my new manipulated node is being added at the very end of the xmldocument. Any code snippets would be greatly appreciated.

like image 329
chugh97 Avatar asked Oct 29 '09 16:10

chugh97


3 Answers

If I understand you right, this should help you do it.

SolarSystem.xml:

<?xml version="1.0" encoding="UTF-8"?>
<SolarSystem>
  <Planets>
    <Planet Id="1">
      <Name>Mercury</Name>
    </Planet>
    <Planet Id="2">
      <Name>Venus</Name>
    </Planet>
    <Planet Id="3">
      <Name>Earth</Name>
    </Planet>
  </Planets>
</SolarSystem>

The code finds the <Planet> Mercury, adds an extra element to it, removes it, and reinserts it at the end of the <Planets> collection.

XDocument SolarSystem = XDocument.Load(Server.MapPath("SolarSystem.xml"));
IEnumerable<XElement> Planets = SolarSystem.Element("SolarSystem").Element("Planets").Elements("Planet");

// identify and change Mercury
XElement Mercury = Planets.Where(p => p.Attribute("Id").Value == "1").FirstOrDefault();
Mercury.Add(new XElement("YearLengthInDays", "88"));

// remove Mercury from current position, and add back in at the end
Mercury.Remove();
Planets.Last().AddAfterSelf(Mercury);

// save it as new file
SolarSystem.Save(Server.MapPath("NewSolarSystem.xml"));

which gives:

<?xml version="1.0" encoding="UTF-8"?>
   <SolarSystem>
     <Planets>
       <Planet Id="2">
         <Name>Venus</Name>
       </Planet>
       <Planet Id="3">
         <Name>Earth</Name>
       </Planet>
       <Planet Id="1">
         <Name>Mercury</Name>
         <YearLengthInDays>88</YearLengthInDays>
       </Planet>
     </Planets>
   </SolarSystem>
like image 84
Ralph Lavelle Avatar answered Nov 20 '22 16:11

Ralph Lavelle


If you're just editing the node, then why remove it at all? Just get a reference to it in the tree and edit it in-place.

If that's not an option for some reason, then one way to go about it is this: once you've found the XElement (or, in general, XNode) you need to replace in the tree, create a new XElement to serve as a replacement, and then use XNode.ReplaceWith method on the old element, passing new one as the argument.

like image 4
Pavel Minaev Avatar answered Nov 20 '22 14:11

Pavel Minaev


This just builds on @Ralph Lavelle's example above. I created a complete console app so I could play with the code & understand it better. Figured I'd share it. It uses the exact same sample XML from above, but I had to remove the references to Server.MapPath() as I couldn't figure out how to make them work. Here you go:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;

class LinqDemo
{
static void Main( )
    {
        XDocument SolarSystem = XDocument.Load("SolarSystem.xml");
        IEnumerable<XElement> Planets = SolarSystem.Element("SolarSystem").Element("Planets").Elements("Planet");

        // identify and change Mercury
        XElement Mercury = Planets.Where(p => p.Attribute("Id").Value == "1").FirstOrDefault();
        Mercury.Add(new XElement("YearLengthInDays", "88"));

        // remove Mercury from current position, and add back in at the end
        Mercury.Remove();
        Planets.Last().AddAfterSelf(Mercury);

        // save it as new file
        SolarSystem.Save("NewSolarSystem.xml");
    }
}

Maybe this'll help another LINQ noob like me.

like image 1
delliottg Avatar answered Nov 20 '22 15:11

delliottg