Kasrak
Kasrak

Reputation: 1561

Insert a node into a XML file

I am trying to add a single line/node (provided below) into an XML:

<Import Project=".www\temp.proj" Condition="Exists('.www\temp.proj')" />

The line could be under the main/root node of the XML:

<Project Sdk="Microsoft.NET.Sdk">

The approach I used:

        XmlDocument Proj = new XmlDocument();
        Proj.LoadXml(file);
        XmlElement root = Proj.DocumentElement;
        // Not sure about the next steps
        root.SetAttribute("not sure", "not sure", "not sure");

Though I don't exactly know how to add that line in the XML, cause it was my first try on directly editing XML files, the error caused an extra problem over it.

I get this error on my first attempt:

C# "loadxml" 'Data at the root level is invalid. Line 1, position 1.'

Know this error was a famous one, which some provided a variety of approaches in this link:

xml.LoadData - Data at the root level is invalid. Line 1, position 1

Unfortunately, most of the solutions are outdated, the answer didn't work on this case, and I don't know how to apply others on this case.

Provided/accepted answer on the link for that issue:

string _byteOrderMarkUtf8 = Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble());
if (xml.StartsWith(_byteOrderMarkUtf8))
{
    xml = xml.Remove(0, _byteOrderMarkUtf8.Length);
}

Basically it didn't work, cause xml.StartsWith seems not existing anymore, at the same time xml.Remove also doesn't exist.


Can you please provide a piece of code that bypass the error and add the line to the XML?

Edit: The sample XML file is provided in the comments section.

Upvotes: 1

Views: 1021

Answers (2)

Mohammed Sajid
Mohammed Sajid

Reputation: 4903

For the Xml posted in the comment, I have used two approachs :

1 - XmlDocument

XmlDocument Proj = new XmlDocument();
Proj.Load(file);
XmlElement root = Proj.DocumentElement;
//Create node
XmlNode node = Proj.CreateNode(XmlNodeType.Element, "Import", null);

//create attributes
XmlAttribute attrP = Proj.CreateAttribute("Project");
attrP.Value = ".www\\temp.proj";

XmlAttribute attrC = Proj.CreateAttribute("Condition");
attrC.Value = "Exists('.www\\temp.proj')";

node.Attributes.Append(attrP);
node.Attributes.Append(attrC);

//Get node PropertyGroup, the new node will be inserted before it
XmlNode pG = Proj.SelectSingleNode("/Project/PropertyGroup");
root.InsertBefore(node, pG);

Console.WriteLine(root.OuterXml);

2 - Linq To Xml, by using XDocument

XDocument xDocument = XDocument.Load(file);

xDocument.Root.AddFirst(new XElement("Import", 
    new XAttribute[] 
    { 
        new XAttribute("Project", ".www\\temp.proj"), 
        new XAttribute("Condition", "Exists('.www\\temp.proj')") 
    }));

Console.WriteLine(xDocument);

Namespace to add for XDocument:

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

Both solutions give the same result, but the last one is simple.

I hope you find this helpful.

Upvotes: 2

halliba
halliba

Reputation: 319

Would it be possible for you to use the official MSBuild libraries?(https://www.nuget.org/packages/Microsoft.Build/)
I'm not sure which nuget package is actually required to read and edit project files only.

I've tried to programatically edit MSBuild project files directly and can not recommend it. It broke regulary due to unexpected changes... The MSBuild library does a good job in editing project files and e.g. adding Properties, Items or Imports.

Upvotes: 0

Related Questions