I currently have an xml file named PrioritizationSettings.config and I need to consolidate this into Web.config.
I have moved this directly into the Web.config as it is the same across all configurations.
I noticed that the project is using this old file path that no longer exists because I moved the XML directly into Web.config.
public static PrioritizationSettings LoadPrioritizeSettings()
{
return LoadPrioritizeSettings(AppDomain.CurrentDomain.BaseDirectory + "__Configs\\PrioritizationSettings.config");
}
I would like to be able to access the PrioritizationSettings inside of Web.config from here. So that instead of passing the entire XML file, I can just pass in the section of XML that now exists in Web.Config
Is there another way to do this without using ConfigurationManager.GetSection()? I have looked at this an I fear it may be far more involving. I just need to extract the XML.
This appears to be doing what I would like.
public static PrioritizationSettings LoadPrioritizeSettings()
{
return LoadPrioritizeSettings(AppDomain.CurrentDomain.BaseDirectory + "Web.config");
}
I now pass the entire Web.config file in. Inside of the LoadPrioritizeSettings I have the following code:
public static PrioritizationSettings LoadPrioritizeSettings(string configFile)
{
XmlReader xmlReader;
try { xmlReader = XmlReader.Create(configFile); }
catch (Exception ex) { throw ex; }
if (xmlReader == null)
return null;
XmlDocument xmlDoc = new System.Xml.XmlDocument();
xmlReader.Read();
xmlDoc.Load(xmlReader);
xmlReader.Close();
XmlNode xmlConfiguration = xmlDoc["configuration"];
if (xmlConfiguration == null)
throw new Exception("The root element (PrioritizationSettings) of the config file could not be found.");
XmlNode xmlPrioritizeSettings = xmlConfiguration["PrioritizationSettings"];
return prioritizeSettings;
}
So I am able to get the PrioritizationSetting node from the web.config.
I'm trying to learn how to read a XML file and do changes using C#.
Problem:
The XMLfile already exists. I would like to read the file and search for a specific element which has another element with an attribute:
<ELement>
<Element2 Attribute = "Value" />
</Element>
The problem is if this element "Element2" does not exist in the xml file I would like to create it under the same path.
Here is my actual code.
private void UpdateConfig(string configPath, string serverName)
{
string oldServername = null;
XElement config = XElement.Load(configPath);
CreateConfigBackup(configPath);
try
{
//which could be Null if the element does not exist in xml file.
oldServername = config.Element("WebGUI").Element("ServerIP").Attribute("Value").Value.ToString();
oldServername = oldServername.Split(':').FirstOrDefault();
// Config updaten
config.Element("WebGUI").Element("ServerIP").Attribute("Value").SetValue(serverName);
}
else
{
XElement ELM = new XElement("ServerIP");
ELM.SetAttributeValue("Value",serverName);
config.Element("WebGUI").Add(ELM);
}
}
catch (Exception ex)
{
if (oldServername == null)
{
MessageBox.Show(configPath+ "enthält nicht das Element Server in der Web-Konfigurationsdatei.");
}
}
SaveConfig(config, configPath);
}
I have a master XML schema that has three classes in
<jobs>
<job>
<id>123-123-123-123</id>
<aspect1>
<...></...>
</aspect1>
<aspect2>
<...></...>
</aspect2>
<aspect3>
<...></...>
</aspect3>
</job>
</jobs>
The receiver classes are all set up fine (if all three aspects elements are filled with their respective properties, it's read in without an issue). The issue comes if (say) aspect2 is missing from the object when I get a XmlException thrown.
My XML reader is a simple affair
public static Jobs JobData;
public static bool ProcessData()
{
try
{
var s = new XmlSerializer(typeof(Jobs));
var r = new StreamReader(jobsapp.Singleton.AppContext.Assets.Open("schemaJobsV101.xml"));
JobData = (Jobs)s.Deserialize(r);
r.Close();
return true;
}
catch (FileNotFoundException)
{
Console.Write("file not found");
return false;
}
catch (InvalidOperationException)
{
Console.WriteLine("invalid operation");
return false;
}
}
Is there a way to read the XML file to allow me to have just one element (aspect1, 2 or 3)?
I am storing logs in an xml file...
In a traditional straight text format approach, you would typically just have a openFile... then writeLine method...
How is it possible to add a new entry into the xml document structure, like you would just with the text file approach?
use an XmlWriter.
example code:
public class Quote
{
public string symbol;
public double price;
public double change;
public int volume;
}
public void Run()
{
Quote q = new Quote
{
symbol = "fff",
price = 19.86,
change = 1.23,
volume = 190393,
};
WriteDocument(q);
}
public void WriteDocument(Quote q)
{
var settings = new System.Xml.XmlWriterSettings
{
OmitXmlDeclaration = true,
Indent= true
};
using (XmlWriter writer = XmlWriter.Create(Console.Out, settings))
{
writer.WriteStartElement("Stock");
writer.WriteAttributeString("Symbol", q.symbol);
writer.WriteElementString("Price", XmlConvert.ToString(q.price));
writer.WriteElementString("Change", XmlConvert.ToString(q.change));
writer.WriteElementString("Volume", XmlConvert.ToString(q.volume));
writer.WriteEndElement();
}
}
example output:
<Stock Symbol="fff">
<Price>19.86</Price>
<Change>1.23</Change>
<Volume>190393</Volume>
</Stock>
see
Writing with an XmlWriter
for more info.
One of the problems with writing a log file in XML format is that you can't just append lines to the end of the file, because the last line has to have a closing root element (for the XML to be valid)
This blog post by Filip De Vos demonstrates quite a good solution to this:
High Performance writing to XML Log files (edit: link now dead so removed)
Basically, you have two XML files linked together using an XML-include thing:
Header file:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log [
<!ENTITY loglines SYSTEM "loglines.xml">
]>
<log>
&loglines;
</log>
Lines file (in this example, named loglines.xml):
<logline date="2007-07-01 13:56:04.313" text="start process" />
<logline date="2007-07-01 13:56:25.837" text="do something" />
<logline date="2007-07-01 13:56:25.853" text="the end" />
You can then append new lines to the 'lines file', but (most) XML parsers will be able to open the header file and read the lines correctly.
Filip notes that: This XML will not be parsed correctly by every XML parser on the planet. But all the parsers I have used do it correctly.
The big difference is the way you are thinking about your log data. In plain text files you are indeed just adding new lines. XML is a tree structure however, and you need to think about like such. What you are adding is probably another NODE, i.e.:
<log>
<time>12:30:03 PST</time>
<user>joe</user>
<action>login</action>
<log>
Because it is a tree what you need to ask is what parent are you adding this new node to. This is usually all defined in your DTD (Aka, how you are defining the structure of your data). Hopefully this is more helpful then just what library to use as once you understand this principle the interface of the library should make more sense.
Why reinvent the wheel? Use TraceSource Class (System.Diagnostics) with the XmlWriterTraceListener.
Sorry to post a answer for old thread. i developed the same long time ago. here i like to share my full code for logger saved log data in xml file date wise.
logger class code
using System.IO;
using System.Xml;
using System.Threading;
public class BBALogger
{
public enum MsgType
{
Error ,
Info
}
public static BBALogger Instance
{
get
{
if (_Instance == null)
{
lock (_SyncRoot)
{
if (_Instance == null)
_Instance = new BBALogger();
}
}
return _Instance;
}
}
private static BBALogger _Instance;
private static object _SyncRoot = new Object();
private static ReaderWriterLockSlim _readWriteLock = new ReaderWriterLockSlim();
private BBALogger()
{
LogFileName = DateTime.Now.ToString("dd-MM-yyyy");
LogFileExtension = ".xml";
LogPath= Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + "\\Log";
}
public StreamWriter Writer { get; set; }
public string LogPath { get; set; }
public string LogFileName { get; set; }
public string LogFileExtension { get; set; }
public string LogFile { get { return LogFileName + LogFileExtension; } }
public string LogFullPath { get { return Path.Combine(LogPath, LogFile); } }
public bool LogExists { get { return File.Exists(LogFullPath); } }
public void WriteToLog(String inLogMessage, MsgType msgtype)
{
_readWriteLock.EnterWriteLock();
try
{
LogFileName = DateTime.Now.ToString("dd-MM-yyyy");
if (!Directory.Exists(LogPath))
{
Directory.CreateDirectory(LogPath);
}
var settings = new System.Xml.XmlWriterSettings
{
OmitXmlDeclaration = true,
Indent = true
};
StringBuilder sbuilder = new StringBuilder();
using (StringWriter sw = new StringWriter(sbuilder))
{
using (XmlWriter w = XmlWriter.Create(sw, settings))
{
w.WriteStartElement("LogInfo");
w.WriteElementString("Time", DateTime.Now.ToString());
if (msgtype == MsgType.Error)
w.WriteElementString("Error", inLogMessage);
else if (msgtype == MsgType.Info)
w.WriteElementString("Info", inLogMessage);
w.WriteEndElement();
}
}
using (StreamWriter Writer = new StreamWriter(LogFullPath, true, Encoding.UTF8))
{
Writer.WriteLine(sbuilder.ToString());
}
}
catch (Exception ex)
{
}
finally
{
_readWriteLock.ExitWriteLock();
}
}
public static void Write(String inLogMessage, MsgType msgtype)
{
Instance.WriteToLog(inLogMessage, msgtype);
}
}
Calling or using this way
BBALogger.Write("pp1", BBALogger.MsgType.Error);
BBALogger.Write("pp2", BBALogger.MsgType.Error);
BBALogger.Write("pp3", BBALogger.MsgType.Info);
MessageBox.Show("done");
may my code help you and other :)
Without more information on what you are doing I can only offer some basic advice to try.
There is a method on most of the XML objects called "AppendChild". You can use this method to add the new node you create with the log comment in it. This node will appear at the end of the item list. You would use the parent element of where all the log nodes are as the object to call on.
Hope that helps.
XML needs a document element (Basically top level tag starting and ending the document).
This means a well formed XML document need have a beginning and end, which does not sound very suitable for logs, where the current "end" of the log is continously extended.
Unless you are writing batches of self contained logs where you write everything to be logged to one file in a short period of time, I'd consider something else than XML.
If you are writing a log of a work-unit done, or a log that doesn't need to be inspected until the whole thing has finished, you could use your approach though - simply openfile, write the log lines, close the file when the work unit is done.
For editing an xml file, you could also use LINQ. You can take a look on how here:
http://www.linqhelp.com/linq-tutorials/adding-to-xml-file-using-linq-and-c/
I'm writing a lightweight XML editor, and in cases where the user's input is not well formed, I would like to indicate to the user where the problem is, or at least where the first problem is. Does anyone know of an existing algorithm for this? If looking at code helps, if I could fill in the FindIndexOfInvalidXml method (or something like it), this would answer my question.
using System;
namespace TempConsoleApp
{
class Program
{
static void Main(string[] args)
{
string text = "<?xml version=\"1.0\"?><tag1><tag2>Some text.</taagg2></tag1>";
int index = FindIndexOfInvalidXml(text);
Console.WriteLine(index);
}
private static int FindIndexOfInvalidXml(string theString)
{
int index = -1;
//Some logic
return index;
}
}
}
I'd probably just cheat. :) This will get you a line number and position:
string s = "<?xml version=\"1.0\"?><tag1><tag2>Some text.</taagg2></tag1>";
System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
try
{
doc.LoadXml(s);
}
catch(System.Xml.XmlException ex)
{
MessageBox.Show(ex.LineNumber.ToString());
MessageBox.Show(ex.LinePosition.ToString());
}
Unless this is an academic exercise, I think that writing your own XML parser is probably not the best way to go about this. I would probably check out the XmlDocument class within the System.Xml namespace and try/catch exceptions for the Load() or LoadXml() methods. The exception's message property should contain info on where the error occurred (row/col numbers) and I suspect it'd be easier to use a regular expression to extract those error messages and the related positional info.
You should be able to simply load the string into an XmlDocument or an XmlReader and catch XmlException. The XmlException class has a LineNumber property and a LinePosition property.
You can also use XmlValidatingReader if you want to validate against a schema in addition to checking that a document is well-formed.
You'd want to load the string into an XmlDocument object via the load method and then catch any exceptions.
public bool isValidXml(string xml)
{
System.Xml.XmlDocument xDoc = null;
bool valid = false;
try
{
xDoc = new System.Xml.XmlDocument();
xDoc.loadXml(xmlString);
valid = true;
}
catch
{
// trap for errors
}
return valid;
}