How to read and update value of nodes in an XElement - c#

I have an xml document (actually a config file) loaded into an XDocument object, that contains an element like this:
<ScheduledTasks>
<add key="RelativePath" value="..\Scheduler\Tasks"/>
<add key="SearchPauseInSeconds" value="10"/>
<add key="MatrixAccount" value="95755UE93ZEb3fRZUSZ753K9FRS3O9DaDrJxtdiiZnm"/>
<add key="MatrixPassword" value="95755UE93ZEb3fRZUSZ753K9FRS3O9DaDgKrn2e71"/>
</ScheduledTasks>
How can I best retrieve (and update) the value of RelativePath, SeachPauseInseconds etc? They aren't XElements.
TIA.

var attribute =
xDocument.Root.Elements()
.Single(element => element.Attribute("key").Value == "RelativePath")
.Attribute("value");
string oldValue = attribute.Value; // to retrieve
attribute.Value = newValue; // to update

They are attributes. Use XElement.Attribute("attributeName") to get them.
var items = (from i in scheduledTasksElement.Elements("add")
select new
{
KeyAttribute = i.Attribute("key"),
Key = (string)i.Attribute("key"),
ValueAttribute = i.Attribute("value"),
Value = (string)i.Attribute("value")
}).ToList();
As you can see, you can easily cast XAttribute to other types like you can do with XElement.
You can also update the value:
items[0].KeyAttribute.Value = "newValue";

You can, for example, create an extension method that will do it
public static void FindAndReplace(this XDocument doc, string key, string newValue)
{
var elem = doc.Descendants("add")
.FirstOrDefault(d => d.Attribute("key").Value == key);
if (elem != null)
elem.Attribute("value").Value = newValue;
}
and use it like
doc.FindAndReplace("RelativePath", "..\Tasks");

Related

C# - Can I select the value of an XML attribute by searching for a second attribute?

I want to select the value of the "data" attribute where the "key" attribute matches a specific search.
The XML file will look like this.
<connections>
<production>
<connection key="KEY1" data="value1" />
<connection key="KEY2" data="value2" />
<connection key="KEY3" data="value3" />
</production>
</connections>
So is there a way to return the value of the data attribute by searching for key = key1 for example?
You could do something like this if you wanted to avoid using XPath.
using System.Xml.Linq;
var xmlStr = File.ReadAllText("Testfile.xml");
XElement root = XElement.Parse(xmlStr);
var data = root.Element("production")
.Elements().Where(x => x.Attribute("key").Value == "KEY1")
.Select(x=>x.Attribute("data").Value)
.First();
Console.WriteLine(data);
Try this, using System.Xml you can read the xml file in question and iterate through the nodes to look for your value.
private void YOUR_METHOD_NAME()
{
// Call GetXml method which returns the result in the form of string
string result = GetXml("xmlfile.xml", "KEY2");
Debug.WriteLine(result);
}
private string GetXml(string filePath, string searchKey)
{
XmlDocument doc = new XmlDocument();
doc.Load(filePath);
XmlNodeList nodes = doc.SelectSingleNode("//connections/production").ChildNodes;
string output = string.Empty;
foreach (XmlNode node in nodes)
{
if (node.Attributes["key"].Value == searchKey)
{
output = node.Attributes["data"].Value;
}
else
{
continue;
}
}
return output;
}

Parsing XML using C#, getting attribute value

I have the following (simplified) notepad file, which from what I understand is XML text:
<?xml version="1.0" encoding="utf-8"?>
<appSettings>
<add key="Active_01" value="1">
</add>
</appSettings>
I am trying to parse it using C#.
So far I have the following:
public class RFIDScanner
{
public void GetScannerConfigFile()
{
string File = ConfigurationManager.AppSettings["RFIDScannerConfiguration"];
XmlDocument doc = new XmlDocument();
doc.Load(File);
XmlNode node = doc.DocumentElement.SelectSingleNode("/appSettings");
String nodename = node.Name;
}
}
So far I know this is all correct, as:
nodename = appSettings
Which is as it should be.
My problem is, how do I retrieve the value "1" from the field "Active_01".
I now know that the node "add" is a child of the node "appSettings", and a trying to work out how to get the value stored in it.
Not sure if you wish to parse the '1' from the key Active_01, or get the 1 from the value. In Any case, you can use the following code:
public void GetScannerConfigFile()
{
string File = ConfigurationManager.AppSettings["RFIDScannerConfiguration"];
XmlDocument doc = new XmlDocument();
doc.Load(File);
var yourFile = doc.DocumentElement;
if (yourFile == null) return;
// Here you'll get the attribute key: key = Active_01 - which can be simply parsed for getting only the "1"
string key = yourFile.ChildNodes[0].Attributes["key"].Value;
// Here you'll get the number "1" from the value attribute.
string value = yourFile.ChildNodes[0].Attributes["value"].Value;
}
There are many ways, one is to use the XPath using the function you use above:
var value = doc.DocumentElement.SelectSingleNode("/appSettings/add/#value");
Another option is to use xml serialization:
You'd define classes as follows:
public class add
{
[XmlAttribute]
public string key;
[XmlAttribute]
public int value;
}
public class appSettings
{
public add add;
}
And then deserialize as follows:
var ser = new XmlSerializer(typeof(appSettings));
var xmlReader = new XmlTextReader(new StringReader(s));
appSettings settings = (appSettings) ser.Deserialize(xmlReader);
xmlReader.Close();
You can then get the values from settings
I have used this way in my code to add values to xml
may be it will help
var surveyTypeList = new XElement("SurveyTypes");
foreach (var item in modelData.SurveyTypeList)
{
if (item.IsSelected)
{
var surveyType = new XElement("SurveyType");
var id = new XElement("Id");
id.Add(item.Value);
// **var i= id.Value**
surveyType.Add(id);
surveyTypeList.Add(surveyType);
}
}
you can get value by var i= id.Value in your code;

Extracting XML inner node elements in C#

I have an XML document that looks like this:
<root>
<key>
<id>v1</id>
<val>v2</val>
<iv>v3</iv>
</key>
</root>
How do I extract the v2 values and v3 values of a key node using its v1 value in C#?
Use Linq.
var myXml = XDocument.Parse("<root>
<key>
<id>v1</id>
<val>v2</val>
<iv>v3</iv>
</key>
</root>").Root.Elements("key")
.FirstOrDefault(x=> x.Element("id").Value == value);
if (myXml != null)
{
var myObject = new
{
id = myXml.Element("id").Value,
val = myXml.Element("val").Value,
iv = myXml.Element("iv").Value
});
}
Of course, you need to check for missing elements, etc, if required.
Use xpath:
/root/key[id='v1']/val
/root/key[id='v1']/iv
so something like
myXmlDoc.SelectSingleNode("/root/key[id='v1']/val").Value
myXmlDoc.SelectSingleNode("/root/key[id='v1']/iv").Value
I like using LINQ to XML for processing XML:
var xml = XElement.Parse(#"<root>
<key>
<id>v1</id>
<val>v2</val>
<iv>v3</iv>
</key>
</root>");
var key = xml.Elements("key").First(x => x.Element("id").Value == "v1");
Console.WriteLine("val: " + key.Element("val").Value);
Console.WriteLine(" iv: " + key.Element("iv").Value);
I have ignored all error checking for brevity.
For example First() would throw an exception if the element is not found. You might want to use FirstOrDefault() and check for null if you are expecting that or handle edge cases a bit more gracefully.
Same goes for Element() calls. They might return null so calling .Value could result in a System.NullReferenceException. To avoid clutter I usually use extension methods to do these checks:
static class XElementUtilities
{
public static string GetValue(this XElement xml, string name)
{
var element = xml.Element(name);
return element == null ? null : element.Value;
}
public static bool ValueEqual(this XElement xml, string name, string value)
{
var element = xml.Element(name);
return element != null && value != null && element.Value == value;
}
}

how to parse a markup element?

I have a string like this:
var str = "<University id="1396677467961079" name="Oxford"/>";
I want to get value of id, so I could do this:
var id = str.Substring(16, 16);
but it is not a good way to get it. How can I get the value in a safer way?
You can use Linq to XML like this:
var str = "<University id=\"1396677467961079\" name=\"Oxford\"/>";
var el = XElement.Parse(str);
var attr = el.Attribute("id");
var id = attr != null ? attr.Value : string.Empty;
For an overview of Linq to Xml see this link.

Reading XML nested node values

Having an issue grabbing values in an XML file
The structure is as followed
<configuration>
<settings>
<add key="folder" value = "c:\...." />
</settings>
</configuration>
i want to be able to read the value from folder.
string val = string.Empty;
foreach (XElement element in XElement.Load(file).Elements("configuration"))
{
foreach (XElement element2 in element.Elements("settings"))
{
if (element2.Name.Equals("folder"))
{
val = element2.Attribute(key).Value;
break;
}
}
}
return val;
The name of the element isn't folder... that's the value of the key attribute. Also note that as you've used XElement.Load, the element is the configuration element - asking for Elements("configuration") will give you an empty collection. You could either load an XDocument instead, or just assume you're on a configuration element and look beneath it for settings.
I think you want:
return XElement.Load(file)
.Elements("settings")
.Elements("add")
.Where(x => (string) x.Attribute("key") == "folder")
.Select(x => (string) x.Attribute("value"))
.FirstOrDefault();
You can use XPath:
var folder = XElement.Load(file)
.XPathSelectElements("/settings/add[#key='folder']")
.Select(a => (string)a.Attribute("value"))
.FirstOrDefault();

Categories