Update nested value in XML - c#

I'm trying to write a routine that updates values in an XML file and believe I'm close. Here's an example of the XML:
<?xml version="1.0" encoding="utf-8"?>
<!-- This file is generated by the GPS_Client program. -->
<Sites>
<Site>
<Id>A</Id>
<add key="landingName" value="Somewhere" />
<add key="landingLat" value="47.423719" />
<add key="landingLon" value="-123.011364" />
<add key="landingAlt" value="36" />
</Site>
<Site>
<Id>B</Id>
<add key="landingName" value="Somewhere Else" />
<add key="landingLat" value="45.629160" />
<add key="landingLon" value="-128.882934" />
<add key="landingAlt" value="327" />
</Site>
</Sites>
The key is that I need to update a specific key without updating the rest of the keys with the same name. Here's the current code:
private void UpdateOrCreateAppSetting(string filename, string site, string key, string value)
{
string path = "\"#" + filename + "\"";
XDocument doc = XDocument.Load(path);
var list = from appNode in doc.Descendants("appSettings").Elements()
where appNode.Attribute("key").Value == key
select appNode;
var e = list.FirstOrDefault();
// If the element doesn't exist, create it
if (e == null) {
new XElement(site,
new XAttribute(key, value));
// If the element exists, just change its value
} else {
e.Element(key).Value = value;
e.Attribute("value").SetValue(value);
}
}
I assume I need to concatenate site, Id and key in some way, but don't see how it's done.

Using this XmlLib, you can have it create the node if it doesn't exist automatically.
private void UpdateOrCreateAppSetting(string filename, string site,
string key, string value)
{
string path = "\"#" + filename + "\"";
XDocument doc = XDocument.Load(path);
XPathString xpath = new XPathString("//Site[Id={0}]/add[#key={1}]", site, key);
XElement node = doc.Root.XPathElement(xpath, true); // true = create if not found
node.Set("value", value, true); // set as attribute, creates attribute if not found
doc.Save(filename);
}

Related

Explain some code about dynamic connection string

So, I'm doing a website that does a lot of things and one of them is, doing a dynamic connection string... I already did it, but because I took the code from the internet, I'm kinda lost, so I was hoping that somebody could help and explain how it works and what each thing does...
Here's the code:
protected void Page_Load(object sender, EventArgs e)
{
AddUpdateConnectionString("ConString");
}
void AddUpdateConnectionString(string name)
{
bool isNew = false;
string path = Server.MapPath("~/Web.Config");
XmlDocument doc = new XmlDocument();
doc.Load(path);
XmlNodeList list = doc.DocumentElement.SelectNodes(string.Format("connectionStrings/add[#name='{0}']", name));
XmlNode node;
isNew = list.Count == 0;
if (isNew)
{
node = doc.CreateNode(XmlNodeType.Element, "add", null);
XmlAttribute attribute = doc.CreateAttribute("name");
attribute.Value = name;
node.Attributes.Append(attribute);
attribute = doc.CreateAttribute("connectionString");
attribute.Value = "";
node.Attributes.Append(attribute);
attribute = doc.CreateAttribute("providerName");
attribute.Value = "System.Data.SqlClient";
node.Attributes.Append(attribute);
}
else
{
node = list[0];
}
string conString = node.Attributes["connectionString"].Value;
SqlConnectionStringBuilder conStringBuilder = new SqlConnectionStringBuilder(conString);
conStringBuilder.InitialCatalog = TxtBaseDeDados.Text;
conStringBuilder.DataSource = TxtHost.Text;
conStringBuilder.IntegratedSecurity = false;
conStringBuilder.UserID = TxtUtilizador.Text;
conStringBuilder.Password = TxtPalavraPasse.Text;
node.Attributes["connectionString"].Value = conStringBuilder.ConnectionString;
if (isNew)
{
doc.DocumentElement.SelectNodes("connectionStrings")[0].AppendChild(node);
}
doc.Save(path);
}
protected void Button1_Click(object sender, EventArgs e)
{
AddUpdateConnectionString("ConString");
}
If you are wanting to load a connection string from the web.config file I would encourange you to use the ConfigurationManager class like this:
ConfigurationManager.ConnectionStrings["WingtipToys"].ConnectionString
WingtipToys would be stored like this in web.config
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<connectionStrings>
<add name="WingtipToys" connectionString="Data Source=(LocalDB)\v11.0;Initial Catalog=WingtipToys;Integrated Security=True;Pooling=False" />
</connectionStrings>
Here is more info: https://learn.microsoft.com/en-us/dotnet/api/system.configuration.configurationmanager?view=netframework-4.8
It creates or updates the setting in your web.config file used to store the details of how to connect to your back-end database. Config files are XML documents (which are laid out in hierarchical format), so the code finds the config, finds the right section inside of the config (creating it if it's not there), constructs a new connection string, stores it in the XML and saves the changes.

C# App.Config File Path combine

I'm trying without success to use app.config keys with file path based.
This is my App.Config:
<appSettings>
<add key="States" value="NY,CA,MA" />
<add key="SourceFile_NY" value="C:\NY\file.xlsx" />
<add key="SourceFile_CA" value="C:\CA\file.xlsx" />
<add key="SourceFile_MA" value="C:\MA\file.xlsx" />
Now, on the main class, i'd like to obtain the file for each state given:
static void Main(string[] args)
{
var states = "NY,CA,MA".Split(',');
foreach (var state in states)
{
new SomeMethodFromOtherClass().class(SourceFile_ + XX);
}
}
I'm trying to get the file path based on the state on the SourceFile_ + XX part, but i can't find any good way to accomplish the call to the app.config value for each state
Make sure you add a reference in your project to System.Configuration.
Then you just do:
var ny = ConfigurationManager.AppSettings[sourcefile + "_NY"];

XDocument create XElement with XML comment

I've been trying to select some XML comments like so:
XDocument doc = XDocument.Load(args[0]);
var comments = from node in doc.Elements().DescendantNodesAndSelf()
where node.NodeType == XmlNodeType.Comment
select node as XComment;
With this solution I'm getting all xml comment of the file, but I want to select only those comments and create XElement with it:
<Connections>
...
<!-- START Individual Account Authentication -->
<!--<authentication mode="None"/>
<roleManager enabled="false"/>
<profile enabled="false"/>-->
<!-- END Individual Account Authentication -->
...
</Connections>
Any solutions ? :S
Here is a sample:
XDocument doc = XDocument.Load("input.xml");
foreach (XComment start in doc.DescendantNodes().OfType<XComment>().Where(c => c.Value.StartsWith(" START")).ToList())
{
XComment end = start.NodesAfterSelf().OfType<XComment>().FirstOrDefault(c => c.Value.StartsWith(" END"));
if (end != null)
{
foreach (XComment comment in end.NodesBeforeSelf().OfType<XComment>().Intersect(start.NodesAfterSelf().OfType<XComment>()).ToList())
{
comment.ReplaceWith(XElement.Parse("<dummy>" + comment.Value + "</dummy>").Nodes());
}
// if wanted/needed
start.Remove();
end.Remove();
}
}
doc.Save("output.xml");
That gives me
<Connections>
...
<authentication mode="None" /><roleManager enabled="false" /><profile enabled="false" />
...
</Connections>

Write to just one XML attribute without affecting the rest

I have the following but its not working for me:
static void SaveVersion(string configFile, string Version)
{
XmlDocument config = new XmlDocument();
config.Load(configFile);
XmlNode appSettings = config.SelectSingleNode("configuration/appSettings");
XmlNodeList appKids = appSettings.ChildNodes;
foreach (XmlNode setting in appKids)
{
if (setting.Attributes["key"].Value == "AgentVersion")
setting.Attributes["value"].Value = Version;
}
config.Save(configFile);
}
The config file i'm loading up on config.Load(configFile) is the following:
<?xml version="1.0"?>
<configuration>
<startup>
<supportedRuntime version="v2.0.50727" />
</startup>
<appSettings>
<add key="AgentVersion" value="2.0.5" />
<add key="ServerHostName" value="" />
<add key="ServerIpAddress" value="127.0.0.1" />
<add key="ServerPort" value="9001" />
</appSettings>
</configuration>
Am I missing something? I figured it would edit just that particular attribute AgentVersion but its not really doing anything.
Are you aware of the ConfigurationManager class? You can use it to manipulate your app.config file without doing anything manually. I don't think you should reinvent the wheel unless you have a good reason to:
static void SaveVersion(string configFile, string version)
{
var myConfig = ConfigurationManager.OpenExeConfiguration(configFile);
myConfig.AppSettings.Settings["AgentVersion"].Value = version;
myConfig.Save();
}
Try this:
static void SaveVersion(string configFile, string Version)
{
var config = new XmlDocument();
config.Load(configFile);
var agentVersionElement = config.DocumentElement.SelectSingleNode("configuration/appSettings/add[#key = 'AgentVersion']") as XmlElement;
if (agentVersionElement != null)
agentVersionElement.SetAttribute("value", version);
config.Save(configFile);
}
Note that I'm doing the SelectSingleNode from the DocumentElement, not from the XmlDocument itself.

How can I change an attribute value of a XML file in c#?

I have a XML file(web.config) and I need to edit the value attribute of each tag, depend of the key name...
this is an example of the XML file:
<appSettings>
<add key="A1" value="Hi" />
<add key="B1" value="Hello" />
</appSettings>
I mean, How can I change the value "hi" & "hello" using the key attribute(A1 & B1) ??
Thanks alot
try this code, it works fine:
XmlDocument doc = new XmlDocument();
doc.Load("Your.xml");
XmlNodeList elementList = doc.GetElementsByTagName("add");
for (int i = 0; i < elementList.Count; i++)
{
if(elementList[i].Attributes["key"].Value == "A1")
elementList[i].Attributes["value"].Value = "NewValue";
}
if you just want to edit application configuration file
this function can help you
private static void SaveConfig(string KeyName, string value)
{
System.Configuration.ConfigurationManager.AppSettings[KeyName] = value;
System.Configuration.Configuration config = System.Configuration.ConfigurationManager.OpenExeConfiguration(System.Windows.Forms.Application.ExecutablePath);
System.Configuration.AppSettingsSection ass = config.AppSettings;
if (ass.Settings[KeyName] != null)
ass.Settings[KeyName].Value = value;
else
ass.Settings.Add(KeyName, value);
config.Save();
}
by calling SaveConfig("key","newvalue") you can chage the configvalue

Categories

Resources