Check if an element exists in XML - c#

XML:
<CONFIGURATION>
<Files>
<File>D:\Test\TestFolder\TestFolder1\TestFile.txt</File>
<File>D:\Test\TestFolder\TestFolder1\TestFile01.txt</File>
<File>D:\Test\TestFolder\TestFolder1\TestFile02.txt</File>
<File>D:\Test\TestFolder\TestFolder1\TestFile03.txt</File>
<File>D:\Test\TestFolder\TestFolder1\TestFile04.txt</File>
</Files>
<SizeMB>3</SizeMB>
<BackupLocation>D:\Log backups\File backups</BackupLocation>
</CONFIGURATION>
Code:
private void btnLinq_Click(object sender, EventArgs e)
{
queryData(#"D:\WatchMe1\backupconfig1.xml");
}
static void queryData(string xmlFile)
{
var xdoc = XDocument.Load(xmlFile);
var configuration = xdoc.Element("CONFIGURATION");
string sizeMB = configuration.Element("SizeMB").Value;
string backupLocation = configuration.Element("BackupLocation").Value;
//need a code here to check if element <File> exist before executing the file array
string[] files = configuration.Element("Files").Elements("File").Select(c => c.Value).ToArray();
foreach (string file in files)
{
Console.WriteLine(file);
}
}
I have an xml writer program that edits the above xml. The Files element can be changed to Folder element. I have another program that reads the values(file locations) and do something with it, I have to check first if the element is a Files or Folders element.

You can check for element existence with something like
if(configuration.Elements("...").Any()){...}
But i'm not sure what you are asking here exactly...

This may be what you want to do:
if(configutation.Elements.First("Files") != null)
{
string[] files = configuration.Element("Files").Elements("File").Select(c => c.Value).ToArray();
}
Hope this helps!

Related

What is the best way to update an App.Config file for C# in Visual Studio? [duplicate]

This question already has answers here:
What is App.config in C#.NET? How to use it?
(7 answers)
Closed 3 years ago.
I have been working on a file conversion project in C# using Visual Studio 2019. I have been asked to revise my code so that any file paths are replaced with variables that are called via the App.Config file. I am new to this method, as I was never taught how to do this before. I am looking for some guidance or examples if anyone could assist. I have tried any related articles or videos, but am still struggling. My code is below. I have updated any serve/db names to generic ones. Thanks in advance.
class Program
{
static void Main(string[] args)
{
string fromPath = string.Empty;
string toPath = string.Empty;
// set path where the source xls file is
string sourcePath = #"\\server\Data\subfolder\subfolder2\";
// determine target filename from today's date
string sourceFile = DateTime.Now.ToString("MM.dd.yy") + ".xls";
// determine if the target file exists
fromPath = sourcePath + sourceFile; // gives us the full path and filename to open
if (System.IO.File.Exists(fromPath))
{
// file exists, so process it
// make our output file
toPath = sourcePath + "import.csv";
// do the conversion to csv
CsvHelper csv = new CsvHelper();
csv.XlsToCsv(fromPath, toPath);
// renames one column to say 'idn_prod1'
var file1 = #"\\server\Data\subfolder\subfolder2\import.csv";
var lines = System.IO.File.ReadAllLines(file1);
var columnHeaders = lines[0];
var textToReplace = "idn_prod";
var newText = "idn_prod1";
var indexToReplace = columnHeaders
.LastIndexOf("idn_prod");//LastIndex ensures that you pick the second idn_prod
columnHeaders = columnHeaders
.Remove(indexToReplace, textToReplace.Length)
.Insert(indexToReplace, newText);//removes the second idn_prod and replaces it with the updated value.
using (System.IO.StreamWriter sw = new System.IO.StreamWriter(file1))
{
sw.WriteLine(columnHeaders);
foreach (var str in lines.Skip(1))
{
sw.WriteLine(str);
}
sw.Flush();
}
// archive xls file to prevent buildup in this directory
if (Directory.Exists(#"\\server\Data\subfolder\subfolder2\"))
{
foreach (var file in new DirectoryInfo(#"C:\Users\myName\Documents\Projects\").GetFiles())
{
file.MoveTo($#"{ #"\\server\Data\subfolder\subfolder2\Archive"}\{file.Name}");
}
}
}
}
//Move data in CSV file to a DataTable
private static System.Data.DataTable GetDataTabletFromCSVFile(string csv_file_path = #"\\server\Data\subfolder\subfolder2\import.csv")
{
System.Data.DataTable csvData = new System.Data.DataTable();
try
{
using (TextFieldParser csvReader = new TextFieldParser(csv_file_path))
{
csvReader.SetDelimiters(new string[] { "," });
csvReader.HasFieldsEnclosedInQuotes = true;
string[] colFields = csvReader.ReadFields();
foreach (string column in colFields)
{
DataColumn datecolumn = new DataColumn(column);
datecolumn.AllowDBNull = true;
csvData.Columns.Add(datecolumn);
}
while (!csvReader.EndOfData)
{
string[] fieldData = csvReader.ReadFields();
//Making empty value as null
for (int i = 0; i < fieldData.Length; i++)
{
if (fieldData[i] == "")
{
fieldData[i] = null;
}
}
csvData.Rows.Add(fieldData);
}
}
}
catch (Exception ex)
{
return null;
}
return csvData;
}
//import DataTable into Server and database table
static void InsertDataIntoSQLServerUsingSQLBulkCopy(System.Data.DataTable csvFileData)
{
using (SqlConnection dbConnection = new SqlConnection("Data Source=server;Initial Catalog=Database;Integrated Security=SSPI;"))
{
dbConnection.Open();
using (SqlBulkCopy s = new SqlBulkCopy(dbConnection))
{
s.DestinationTableName = "Table";
foreach (var column in csvFileData.Columns)
s.ColumnMappings.Add(column.ToString(), column.ToString());
s.WriteToServer(csvFileData);
}
}
}
}
Below is my App.Config currently. Sorry for the issues prior.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0"
sku=".NETFramework,Version=v4.5.2" />
</startup>
<appSettings>
<!-- Name of the application-->
<add key="ApplicationName" value="xlsTocsv"/>
<!-- Archive directory for XLS files-->
<add key="MoveTo"
value="#\\server\Data\subfolder\subfolder2\Archive"/>
<!-- Server Name for import-->
<add key="Data Source" value="Server"/>
</appSettings>
</configuration>
In Visual Studio:
right-click your project,
choose Add->New Item.
In the search box, type "config".
Choose "Application Configuration Item". This will add a boiler-plate XML file to your project named "App.config"
Add an <appSettings></appSettings> element as a direct child of the main <configuration> node
Within the appSetting element, create child elements that look like:
<add key="someKey" value ="Some value as a string, it could be a number, or whatever"/>
Add a reference to System.Configuration to your project if there isn't one.
In each file where you are going to access your app settings, add using System.Configuration; to the top of the file.
To get the setting, use code like:
var someKeySetting = ConfigurationManager.AppSettings["someKey"];
At this point, someKeySetting will be a string that contains the setting you gave it in the config file. If the setting doesn't exist in the config file, then someKeySetting will be null. If you want to use numbers, dates, or enums, you will have to parse the string that results (preferably using the appropriate TryParse call.
You're going to want to put your values in the app.config file like so
<configuration> //this is probably already in your app.config file
<appSettings>
<add key="variable1Name" value="/mypathgoeshere/example" />
....
</appSettings>
</configuration>
To access these variables you need these
Namespace: System.Configuration
Assemblies: System.Configuration.dll,
System.Configuration.ConfigurationManager.dll
and then in your file you want to access it like this.
using System.Configuration;
public class Program
{
public static void Main()
{
string configvalue1 = ConfigurationManager.AppSettings["variable1Name"];
//returns the value of "/mypathgoeshere/example"
}
}

XML to ListView

I have made a script in C# that should load data from a XML file into a ListView.
This is the XML file I used to test :
<?xml version="1.0" encoding="utf-8"?>
<Items>
<wordExample languageOne="Пока" languageTwo="Doei" languageThree="Goodbye" />
<wordExample languageOne="1" languageTwo="2" languageThree="3" />
<wordExample languageOne="4" languageTwo="5" languageThree="6" />
<wordExample languageOne="7" languageTwo="8" languageThree="9" />
</Items>
Now I get an error when I try to load the XMl into the ListView and I really don't know what it could be, this is actually the first time I try to use XML in C#.
This is the code used to load the XML into the ListView :
public void ImportXMLToListView(ListView listview)
{
DialogResult dr = OPEN_FILE_DIA.ShowDialog();
if (dr == DialogResult.OK)
{
XDocument doc = XDocument.Load(OPEN_FILE_DIA.FileName);
int counter = 0;
foreach (var dm in doc.Descendants("Items"))
{
string tmpOne = dm.Attribute("languageOne").Value;
string tmpTwo = dm.Attribute("languageTwo").Value;
string tmpThree = dm.Attribute("languageThree").Value;
counter++;
ListViewItem lvi;
lvi = new ListViewItem(tmpOne);
lvi.SubItems.Add(tmpTwo);
lvi.SubItems.Add(tmpThree);
listview.Items.Add(lvi);
}
}
}
Am I doing something wrong??
This is the error I get : (Object reference not set to an instance of an object.)
Please tell me what I do wrong I really try to understand :S
language attributes belongs to your wordExample items. You need doc.Descendants("wordExample")
foreach (var dm in doc.Descendants("wordExample"))
{
string tmpOne = (string)dm.Attribute("languageOne");
string tmpTwo = (string)dm.Attribute("languageTwo");
string tmpThree = (string)dm.Attribute("languageThree");
...
}
And you can use explicit cast instead of directly accessing Value property to avoid NullReferenceException.

C#: Creating XML document using Linq having not proper output?

I'm trying to create xml data from my data, creation was successfull but the output is bad how can I fix this issue?
Here is my code:
private void btnGenerate_Click(object sender, EventArgs e)
{
XElement xml = new XElement("Navigation",
new XElement("NavigationSets"));
foreach (DataRow row_navs in GetNavigationSets().Rows)
{
xml.Add(new XElement("NavigationName", row_navs["name"].ToString()));
foreach (DataRow row_sets in GetMenusInNavigationSetByNavigation(2).Rows)
{
if (int.Parse(row_sets["id"].ToString()) == int.Parse(row_navs["id"].ToString()))
{
foreach (DataRow row_menus in GetMenuById(int.Parse(row_sets["menu_id"].ToString())).Rows)
{
xml.Add(new XElement("MenuName", row_menus["name"].ToString()));
}
}
}
}
xml.Save("data.xml");
}
Im expecting an output like this
<?xml version="1.0" encoding="utf-8"?>
<Navigation>
<NavigationSets>
<NavigationName>
<MenuName></MenuName>
</NavigationName>
<NavigationSets/>
</Navigation>
In my current code my output is like this
<?xml version="1.0" encoding="utf-8"?>
<Navigation>
<NavigationSets/>
<NavigationName></NavigationName>
<MenuName></MenuName>
</Navigation>
To add to Jon Skeets answer,
You can also use
using System.Xml.Linq;
to loop through lists so it is all one statement,
new XElement("NavigationSets",
menus.Select(menu => new XElement("MenuName"))
)
Look at when you're adding elements:
xml.Add(new XElement("NavigationName", row_navs["name"].ToString()));
xml.Add(new XElement("MenuName", row_menus["name"].ToString()));
Where xml is this element:
XElement xml = new XElement("Navigation",
new XElement("NavigationSets"));
That means xml is the Navigation element, not the NavigationSets element. I suspect you want something like:
XElement outer = new XElement("Navigation");
XElement inner = new XElement("NavigationSets");
outer.Add(inner);
... then add to inner.

Reading XML file via XML nodes

I have this XML document I am trying to read in and insert into a data base. There will only ever be one GamePlay node however GamePlayStep may repeat so I have created a node list for this. For some reason GamePlayStep isn't receiving data. Here is the XML file:
<?xml version="1.0" encoding="utf-8" ?>
<GameData>
<GamePlay>
<type>add</type>
<GamePlayID>1</GamePlayID>
<ParticipantID>1</ParticipantID>
<GameID>1</GameID>
<GameDifficultyID>1</GameDifficultyID>
<Start>2012-08-06T12:19:33.154Z</Start>
<End>2012-08-06T12:30:33.154Z</End>
<Success>False</Success>
</GamePlay>
<GamePlayStep>
<GamePlayStepID>1</GamePlayStepID>
<Start>2012-08-06T12:19:33.154Z</Start>
<End>2012-08-06T12:30:33.154Z</End>
<SortOrder>1</SortOrder>
<Score>1</Score>
<hintUsed>True</hintUsed>
<GamePause>
<GamePauseID>1</GamePauseID>
<Start>2012-08-06T12:19:33.154Z</Start>
<End>2012-08-06T12:30:33.154Z</End>
<Order>1</Order>
<Duration>05:01</Duration>
</GamePause>
</GamePlayStep>
</GameData>
Here is my code:
public static void start()
{
string[] filePaths = Directory.GetFiles(System.Configuration.ConfigurationManager.ConnectionStrings["filePath"].ConnectionString);
List<GamePlay> gameObj = new List<GamePlay>();
List<GamePlayStep> gameStepObj = new List<GamePlayStep>();
foreach (string value in filePaths)
{
XmlDocument xd = new XmlDocument();
XmlNodeList GameSteps;
xd.Load(value);
XmlNode documentNode = xd.SelectSingleNode("/GameData/GamePlay");
GameSteps = xd.SelectNodes("/GameData/GamePlay/GamePlayStep");
GamePlay newGamePlay = new GamePlay();
newGamePlay.setType(Convert.ToString(documentNode.SelectSingleNode("type").InnerText));
newGamePlay.setGamePlayID(Convert.ToInt32(documentNode.SelectSingleNode("GamePlayID").InnerText));
newGamePlay.setParticipantID(Convert.ToInt32(documentNode.SelectSingleNode("ParticipantID").InnerText));
newGamePlay.setGameDifficultyID(Convert.ToInt32(documentNode.SelectSingleNode("GameDifficultyID").InnerText));
newGamePlay.setGameID(Convert.ToInt32(documentNode.SelectSingleNode("GameID").InnerText));
newGamePlay.setStartDateTime(Convert.ToDateTime(documentNode.SelectSingleNode("Start").InnerText));
newGamePlay.setEndDateTime(Convert.ToDateTime(documentNode.SelectSingleNode("End").InnerText));
newGamePlay.setSuccess(Convert.ToBoolean(documentNode.SelectSingleNode("Success").InnerText));
newGamePlay.setFile(value);
newGamePlay.addNewGamePlay();
foreach (XmlNode documentNode2 in GameSteps)
{
GamePlayStep newGamePlayStep = new GamePlayStep();
newGamePlayStep.setGamePlayStepID(Convert.ToInt32(documentNode2.SelectSingleNode("GamePlayStepID").InnerText));
newGamePlayStep.setGamePlayID(newGamePlay.getGamePlayID());
newGamePlayStep.setStartDateTime(Convert.ToDateTime(documentNode2.SelectSingleNode("Start").InnerText));
newGamePlayStep.setEndDateTime(Convert.ToDateTime(documentNode2.SelectSingleNode("End").InnerText));
newGamePlayStep.setOrderPlayed(Convert.ToInt32(documentNode2.SelectSingleNode("SortOrder").InnerText));
newGamePlayStep.setScore(Convert.ToInt32(documentNode2.SelectSingleNode("Score").InnerText));
newGamePlayStep.setHintUsed(Convert.ToBoolean(documentNode2.SelectSingleNode("hintUsed").InnerText));
newGamePlayStep.addNewGamePlayStep();
}
}
}
The GamePlay is filling the variables properly and inserting into the database however the GamePlaySteps in the NodeList are not. Does anyone see the problem or how I can improve this?
Thanks.
Your XPath for accessing the GamePlayStep is incorrect;
It should be:
GameSteps = xd.SelectNodes("/GameData/GamePlayStep");
As GamePlayStep is a child of GameData, not GamePlay, in your document.
Use LINQ2XML....its simple and cool
XElement doc=XElement.Load("yourXml");
newGamePlay.setType(doc.Descendants("GameData").Element("GamePlay").Element("type").Value);
....
foreach (Element eml in doc.Descendants("GameData").Elements("GamePlayStep"))
{
GamePlayStep newGamePlayStep = new GamePlayStep();
newGamePlayStep.setGamePlayStepID(Convert.ToInt32(elm.Element("GamePlayStepID").Value));
newGamePlayStep.setStartDateTime(Convert.ToDateTime(elm.Element("Start").Value));
.....
}

Error loading contents from a XML file into a dropdownlist

private void BindCountry()
{
XmlDocument doc = new XmlDocument();
doc.Load(Server.MapPath("countries.xml"));
foreach (XmlNode node in doc.SelectNodes("//country"))
{
usrlocationddl.Items.Add(new ListItem(node.InnerText, node.Attributes["codes"].InnerText));
}
}
The above code am using for loading countries List from an xml file into a dropdown list. But while doing so am encountering a Null Reference error.
Object reference not set to an
instance of an object.
Contents of the xml file:
<countries>
<country code="AF" iso="4">Afghanistan</country>
<country code="AL" iso="8">Albania</country>
</countries>
Where in the code should I be changing, so that I can escape the error.
I suspect the problem is that you've got a country with no "codes" attribute. You could avoid that like this:
private void BindCountry()
{
XmlDocument doc = new XmlDocument();
doc.Load(Server.MapPath("countries.xml"));
foreach (XmlNode node in doc.SelectNodes("//country"))
{
XmlAttribute attr = node.Attributes["codes"];
if (attr != null)
{
usrlocationddl.Items.Add(new ListItem(node.InnerText, attr.Value));
}
}
}
If that doesn't help, I suggest you write a simple console application to try to load the XML and write out each entry you'd select - that should make it easier to work out what's going wrong.

Categories