Pablo Costa
Pablo Costa

Reputation: 125

XElement with LINQ add node after specific node

I've got this XML:

<?xml version="1.0" encoding="utf-8"?>
<JMF SenderID="InkZone-Controller" Version="1.2">
  <Command ID="cmd.00695" Type="Resource">
    <ResourceCmdParams ResourceName="InkZoneProfile" JobID="K_41">
      <InkZoneProfile ID="r0013" Class="Parameter" Locked="false" Status="Available" PartIDKeys="SignatureName SheetName Side Separation" DescriptiveName="Schieberwerte von DI" ZoneWidth="32">
        <InkZoneProfile SignatureName="SIG1">
          <InkZoneProfile Locked="False" SheetName="S1">
            <InkZoneProfile Side="Front">
              <ColorPool Class="Parameter" DescriptiveName="Colors for the job" Status="Available">
                <InkZoneProfile Separation="PANTONE 647 C" ZoneSettingsX="0 0,003 " />
              </ColorPool>
            </InkZoneProfile>
          </InkZoneProfile>
        </InkZoneProfile>
      </InkZoneProfile>
    </ResourceCmdParams>
  </Command>
</JMF>

I'm trying to add a node after a specific node() , using XElement and Linq. But my LINQ query always returns me null. Tried this:

            XElement InkZonePath = XmlDoc.Element("JMF").Elements("InkZoneProfile").Where(z => z.Element("InkZoneProfile").Attribute("Side").Value == "Front").SingleOrDefault();

And this:

            XmlDoc.Element("JMF")
                   .Elements("InkZoneProfile").Where(InkZoneProfile => InkZoneProfile.Attribute("Side")
                   .Value == "Front").FirstOrDefault().AddAfterSelf(new XElement("InkZoneProfile",
                   new XAttribute("Separation", x.colorname),
                   new XAttribute("ZoneSettingsX", x.colorvalues)));

I've built this queries following those examples:

Select XElement where child element has a value

Insert XElements after a specific node

LINQ-to-XML XElement query NULL

But it didn't worked as expected. What is wrong with the LINQ Query ? From what i've read it should work (logically reading the expression i can understand it).

Thanks

EDIT-1: Entire writexml Method

public void writexml(xmldatalist XMLList, variables GlobalVars)
        {

            XmlWriterSettings settings = new XmlWriterSettings
            {
                Indent = true,
                IndentChars = "\t",
                NewLineChars = Environment.NewLine,
                NewLineHandling = NewLineHandling.Replace,
                Encoding = new UTF8Encoding(false)
            };

            string DesktopFolder = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
            string FileExtension = ".xml";
            string PathString = Path.Combine(DesktopFolder, "XML");
            System.IO.Directory.CreateDirectory(PathString);


            foreach (List<xmldata> i in XMLList.XMLArrayList)
            {
                int m = 0;
                foreach (var x in i)
                {

                    string XMLFilename = System.IO.Path.GetFileNameWithoutExtension(x.xml_filename);                    
                    GlobalVars.FullPath = Path.Combine(PathString, XMLFilename + FileExtension);


                    if (!File.Exists(GlobalVars.FullPath))
                    {
                        XDocument doc = new XDocument(
                         new XDeclaration("1.0", "utf-8", "yes"),

                         new XElement("JMF",
                             new XAttribute("SenderID", "InkZone-Controller"),
                             new XAttribute("Version", "1.2"),
                        new XElement("Command",
                             new XAttribute("ID", "cmd.00695"),
                             new XAttribute("Type", "Resource"),
                        new XElement("ResourceCmdParams",
                            new XAttribute("ResourceName", "InkZoneProfile"),
                            new XAttribute("JobID", "K_41"),
                        new XElement("InkZoneProfile",
                            new XAttribute("ID", "r0013"),
                            new XAttribute("Class", "Parameter"),
                            new XAttribute("Locked", "False"),
                            new XAttribute("Status", "Available"),
                            new XAttribute("PartIDKeys", "SignatureName SheetName Side Separation"),
                            new XAttribute("DescriptiveName", "Schieberwerte von DI"),
                            new XAttribute("ZoneWidth", "32"),
                        new XElement("InkZoneProfile",
                            new XAttribute("SignatureName", "SIG1"),
                        new XElement("InkZoneProfile",
                            new XAttribute("Locked", "false"),
                            new XAttribute("SheetName", "S1"),
                        new XElement("InkZoneProfile",
                            new XAttribute("Side", "Front"),
                        new XElement("ColorPoolClass",
                            new XAttribute("Class", "Parameter"),
                            new XAttribute("DescriptiveName", "Colors for the job"),
                            new XAttribute("Status", "Available")
                            )))))))));
                        doc.Save(GlobalVars.FullPath);

                        XDocument XmlDoc = new XDocument();
                        XmlDoc = XDocument.Load(GlobalVars.FullPath);
                        XElement InkZonePath = XmlDoc.Root.Descendants("InkZoneProfile").Where(z => (string)z.Attribute("Side") == "Front").SingleOrDefault();

                        if (InkZonePath != null)
                        {
                            InkZonePath.AddAfterSelf(new XElement("InkZoneProfile",
                                   new XAttribute("Separation", x.colorname),
                                   new XAttribute("ZoneSettingsX", x.colorvalues)));

                        }
                        XmlDoc.Save(GlobalVars.FullPath);

                        }//Closing !FileExists
                    }//Closing inner foreach


            }//Closing outer foreach


        }//Closing writexml method

Upvotes: 1

Views: 4436

Answers (3)

Rahul Singh
Rahul Singh

Reputation: 21795

The problem with your current code is here : Element("JMF").Elements("InkZoneProfile") Since InkZoneProfile is not a direct child of JMF it will not return anything. Use Descendants instead.

Check difference between Elements & Descendants.

This should give you correct result:-

 XElement InkZonePath = xdoc.Element("JMF").Descendants("InkZoneProfile")
                            .SingleOrDefault(z => (string)z.Attribute("Side") == "Front")

After this you can add whatever node you want to add using AddAfterSelf. Also note I have used SingleOrDefault here, but you may get exception if you have multiple matching nodes with this, In that case consider using FirstOrDefault.

Update:

To add new node:-

if (InkZonePath != null)
{
    InkZonePath.AddAfterSelf(new XElement("InkZoneProfile",
                             new XAttribute("Separation", "Test"),
                             new XAttribute("ZoneSettingsX", "Test2")));
}
//Save XDocument                              
xdoc.Save(@"C:\Foo.xml");

Upvotes: 2

Viru
Viru

Reputation: 2246

you can use Descendants instead.

var node  = XmlDoc.Descendants("InkZoneProfile").Where(x=> x.Attribute("Side") !=null && x.Attribute("Side").Value == "Front").FirstorDefault();

Upvotes: 1

ocuenca
ocuenca

Reputation: 39326

You need to use Descendants method instead Elements:

XElement InkZonePath = XmlDoc.Root.Descendants("InkZoneProfile").Where(z => (string)z.Attribute("Side") == "Front").SingleOrDefault();

if(InkZonePath !=null)
   InkZonePath.AddAfterSelf(new XElement("InkZoneProfile",
               new XAttribute("Separation", x.colorname),
               new XAttribute("ZoneSettingsX", x.colorvalues)));

Upvotes: 1

Related Questions