i am trying to edit the logging level in the config file programmaticly.
foreach (var rule in LogManager.Configuration.LoggingRules)
{
if (m_loginglevelcomboBox.SelectedItem.ToString() == "Debug")
{
rule.EnableLoggingForLevel(LogLevel.Debug);
}
else
{
rule.EnableLoggingForLevel(LogLevel.Info);
}
}
//LogManager.ReconfigExistingLoggers();
I am not interested in calling the Reconfig,as the changes will affect the application on the fly.
I want the changes to be made when the application is restarted. so I need it to edit the config file.
i cant use xDocument ,as linq is not compatible with my .net version
so how can i edit the minlevel rule to debug/info ?
i used this to edit the logging level. I hope if this would help if some one stumbles across. If some one thinks it to be a bad idea, please let me know .
string configFilename = GetConfigFilePath();
XmlDocument doc = new XmlDocument();
doc.Load(configFilename);
XmlNode documentElement = doc.DocumentElement;
foreach (XmlNode node in documentElement.ChildNodes)
{
if (ruleDocumentNodeName.Equals(node.Name))
{
foreach (XmlNode childNode in node.ChildNodes)
{
if (loggerDocumentNodeName.Equals(childNode.Name))
{
XmlAttribute idAttribute = childNode.Attributes[minLevelAttributeName];
string currentValue = minLogingLevelComboBox.SelectedItem.ToString();
idAttribute.Value = currentValue;
doc.Save(configFilename);
MinLoggingLevelChanged = true;
}
}
}
}
Related
I'm trying to generate some SSIS (2008) packages using C# (.Net 4.0) and ManagedDTS (10.0). So far I've managed to generate a package and add some connections and variables, now I'm trying to populate the control flow, the first task I'm trying to add is an "Execute SQL Task" to check if the source table has any rows so I can abort if it doesn't. How I'd do this if I was building the SSIS package manually is to have the Execute SQL task run a query like this:
SELECT RecordExists = CASE WHEN EXISTS (SELECT * FROM [Schema].[TABLE] WHERE [COLUMN] IS NULL) THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT) END
I'd then set the ResultSet property to "Single row" and then map the Result to a variable:
However I can't see how to do this in C#, this is what I've got so far:
using Microsoft.SqlServer.Dts.Runtime;
using Microsoft.SqlServer.Dts.Tasks.ExecuteSQLTask;
...
public Package SsisPackage;
...
SsisPackage.Variables.Add("VAR_RecordExists", false, "User", false);
Executable RecordExists = SsisPackage.Executables.Add("STOCK:SQLTask");
TaskHost thRecordExists = RecordExists as TaskHost;
thRecordExists.Properties["Name"].SetValue(thRecordExists, "Do Records Exist?");
thRecordExists.Properties["SqlStatementSource"].SetValue(thRecordExists, "SELECT RecordExists = CASE WHEN EXISTS (SELECT * FROM [Schema].[TABLE] WHERE [COLUMN] IS NULL) THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT) END");
thRecordExists.Properties["Connection"].SetValue(thRecordExists, "Stage");
thRecordExists.Properties["ResultSetType"].SetValue(thRecordExists, ResultSetType.ResultSetType_SingleRow);
My first problem is that the last line errors with the error:
The name 'ResultSetType' does not exist in the current context
My second problem is that even if I get this working I have no idea how to actually map the result set to the variable, I've been using the documentation here but it doesn't mention anything about mapping result sets: https://learn.microsoft.com/en-us/sql/integration-services/building-packages-programmatically/adding-tasks-programmatically. I then found this: https://msdn.microsoft.com/en-us/library/microsoft.sqlserver.dts.tasks.executesqltask.executesqltask.resultsettype.aspx?f=255&MSPPError=-2147217396 which tells me how to set the Result Set Type but results in the above error. It still doesn't mention how to set the result set mapping.
Any help is appreciated.
So I didn't find a way of doing this using the ManagedDTS Framework but I did get it to work.
What I ended up doing was:
Save the package without the result set mapping.
Open the package using XmlDocument
I created a helper class to this end and whilst it may not be the most efficient or clean code (I'm not a normally a C# developer) it does seem to do the job:
public class ResultSetBinding
{
string ResultName;
string DtsVariableName;
string TaskName;
public ResultSetBinding(string taskName, string resultName, string dtsVariableName)
{
TaskName = taskName;
ResultName = resultName;
DtsVariableName = dtsVariableName;
}
public void AddResultBinding(string filePath)
{
XmlDocument doc = new XmlDocument();
doc.Load(filePath);
XmlElement root = doc.DocumentElement;
var nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("DTS", "www.microsoft.com/SqlServer/Dts");
nsmgr.AddNamespace("SQLTask", "www.microsoft.com/sqlserver/dts/tasks/sqltask");
XmlNodeList executableNodes = root.SelectNodes("//DTS:Executable", nsmgr);
foreach (XmlNode executableNode in executableNodes)
{
if (IsExecuteSQLTask(executableNode, nsmgr))
{
if (IsSpecifiedTask(executableNode, nsmgr))
{
AddResultBindingToNode(doc, executableNode, nsmgr);
}
}
}
doc.PreserveWhitespace = true;
doc.Save(filePath);
}
private bool IsExecuteSQLTask(XmlNode executableNode, XmlNamespaceManager nsmgr)
{
foreach (XmlAttribute executableAttribute in executableNode.Attributes)
{
if (executableAttribute.Name == "DTS:ExecutableType")
{
return executableAttribute.Value.Contains("ExecuteSQLTask");
}
}
return false;
}
private bool IsSpecifiedTask(XmlNode executableNode, XmlNamespaceManager nsmgr)
{
foreach (XmlNode propertyNode in executableNode.ChildNodes)
{
if (propertyNode.Name == "DTS:Property")
{
foreach (XmlAttribute propertyAttribute in propertyNode.Attributes)
{
if (propertyAttribute.Name == "DTS:Name" && propertyAttribute.Value == "ObjectName" && propertyNode.InnerText == TaskName)
{
return true;
}
}
}
}
return false;
}
private void AddResultBindingToNode(XmlDocument doc, XmlNode executableNode, XmlNamespaceManager nsmgr)
{
foreach (XmlNode objectNode in executableNode.ChildNodes)
{
if (objectNode.Name == "DTS:ObjectData")
{
foreach (XmlNode sqlNode in objectNode.ChildNodes)
{
if (sqlNode.Name == "SQLTask:SqlTaskData")
{
XmlElement bindingElement = doc.CreateElement("SQLTask:ResultBinding", "www.microsoft.com/sqlserver/dts/tasks/sqltask");
bindingElement.SetAttribute("ResultName", "www.microsoft.com/sqlserver/dts/tasks/sqltask", ResultName);
bindingElement.SetAttribute("DtsVariableName", "www.microsoft.com/sqlserver/dts/tasks/sqltask", String.Format("User::{0}", DtsVariableName));
sqlNode.AppendChild(bindingElement);
}
}
}
}
}
}
Which I then set the following class member:
public List<ResultSetBinding> ResultBindings;
Add the result binding when creating the task:
ResultSetBinding ResultBinding = new ResultSetBinding("Do Records Exist?", "RecordExists", "VAR_RecordExists");
ResultBindings.Add(ResultBinding);
And then once saved loop through and add the result bindings:
foreach (ResultSetBinding ResultBinding in ResultBindings)
{
ResultBinding.AddResultBinding(FilePath);
}
I have the following XML file
<?xml version="1.0" encoding="utf-8"?>
<Comprobante version="2.2" serie="A" folio="35207" fecha="2013-05-31T11:51:48">
<Emisor rfc="" nombre="E">
<DomicilioFiscal calle="" noExterior="" colonia="" />
<ExpedidoEn calle="" noExterior="" colonia="" />
<RegimenFiscal Regimen="Regimen" />
</Emisor>
<Receptor rfc="" nombre="Z">
<Domicilio calle="" noExterior="" colonia="" />
</Receptor>
<Conceptos cantidad="1.000" unidad="COMISION" descripcion="PENDIENTE" valorUnitario="28.50000" importe="28.50" />
<Impuestos totalImpuestosTrasladados="3.14">
<Traslados>
<Traslado impuesto="IVA" tasa="11.00" importe="3.14" />
</Traslados>
</Impuestos>
<Addenda>
<ener:EstadoDeCuentaCombustible xmlns:ener="">
<ener:cadenaOriginal>||2.2|A|35207|2013-05-31T11:51:48|773463|2011|ingreso|Pago en una sola exhibicion|28.50|31.64|Tarjeta|Tijuana,Baja California|3213|ERE|E S.A. de C.V.|Prol|13351|Anexa e|Tijuana|Tijuana|Baja California|Mexico|22100|Prol|13351|Anexa e|Tijuana|Tijuana|Baja California|Mexico|22100|Regimen|XA|Z||||TIJUANA|TIJUANA|BAJA CALIFORNIA|Mexico||1.000|COMISION|PENDIENTE|28.50000|28.50|IVA|11.00|3.14|3.14||</ener:cadenaOriginal>
<ener:idRefund>98</ener:idRefund>
</ener:EstadoDeCuentaCombustible>
</Addenda>
</Comprobante>
I need to get the text that is inside (that long string)
Here's how I start the c# code
XmlDocument doc = new XmlDocument();
doc.Load("Route");
XmlNamespaceManager xnm = new XmlNamespaceManager(doc.NameTable);
xnm.AddNamespace("Documento", "http://www.sat.gob.mx/cfd/2");
xnm.AddNamespace("ener", "http://www.enercard.com.mx/cfd");
I've tried various ways...
//strOriginalString = doc.DocumentElement.SelectSingleNode("//Documento:Addenda", xnm).FirstChild.SelectSingleNode("//ener:cadenaOriginal", xnm).InnerText;
//strOriginalString = doc.DocumentElement.SelectSingleNode("//Documento:Addenda//ener:EstadoDeCuentaCombustible", xnm).FirstChild.SelectSingleNode("//ener:cadenaOriginal", xnm).InnerText;
//strOriginalString = doc.DocumentElement.SelectSingleNode("//Documento:Addenda/Documento:cadenaOriginal", xnm).InnerXml;
this 3 ways always throw an exception...
I found another way that doesn't throw an exception, but it doesn't get the string
XmlElement root = doc.DocumentElement;
XmlNodeList nodes = root.SelectNodes("/Addenda/EstadoDeCuentaCombustible");
strOriginalString = "";
foreach (XmlNode node in nodes)
{
XmlNode child = node.SelectSingleNode("./cadenaOriginal");
if (child != null)
{
strOriginalString = child.InnerText;
break;
}
}
What am I doing wrong? or is there another way that I can get the string inside
This is somewhat simplified, and you'll need to deal with the namespace problems (one I note below), but otherwise, this is the basic construct:
XmlDocument doc = new XmlDocument();
try { doc.Load("c:\\temp\\test.xml"); }
catch (Exception ex) { }
XmlElement root = doc.DocumentElement;
String strOriginalString = "";
foreach (XmlNode node in root.SelectNodes("/Comprobante/Addenda"))
{
XmlNode child = node.SelectSingleNode("EstadoDeCuentaCombustible/cadenaOriginal");
if (child != null)
{
strOriginalString = child.InnerText;
break;
}
}
There's an issue with <ener:EstadoDeCuentaCombustible xmlns:ener=""> as the empty namespace is invalid.
You're missing xmlns:ener declaration on your XML document:
<ener:EstadoDeCuentaCombustible xmlns:ener="http://www.enercard.com.mx/cfd">
Fix that and you'll be able to use something like this:
string xpath = "/Comprobante/Addenda/ener:EstadoDeCuentaCombustible";
foreach (XmlNode estado in doc.SelectNodes(xpath, xnm))
{
Console.WriteLine("ener:cadenaOriginal={0}",
estado.SelectSingleNode("ener:cadenaOriginal", xnm).InnerText);
}
I find Linq2Xml easier to use. (Assuming you have a valid namespace in xmlns:ener="").
var xDoc = XDocument.Load(filename);
XNamespace ener = "your name space for ex ,http://www.enercard.com.mx/cfd";
var result = xDoc.Descendants(ener + "cadenaOriginal").First().Value;
Your second attempt looks the closest to what should work:
//strOriginalString = doc.DocumentElement.SelectSingleNode("//Documento:Addenda//ener:EstadoDeCuentaCombustible", xnm).FirstChild.SelectSingleNode("//ener:cadenaOriginal", xnm).InnerText;
But switch to this(edited):
//strOriginalString = doc.SelectSingleNode("//ener:cadenaOriginal", xnm).InnerText;
So, essentially, I'm running into an interesting issue where, when the call to the "CreateXML()" function in the following code is made, an xelement is created as intended, but then, when I attempt to add it to a collection of xeleents, instead of continuing the foreach loop from which the call to "CreateXML()" originated, the foreach loop is broken out of, and a call is made to "WriteXML()". Additionally, though an XElement is created and populated, it is not added to the List. [for clarification, the foreach loops I am referring to live in the "ParseDoc()" method]
private List<XElement> _xelemlist;
private void WriteXml()
{
XElement head = new XElement("header", new XAttribute("headerattributename", "attribute"));
foreach (XElement xelem in _xelemlist)
{
head.Add(xelem);
}
XDocument doc = new XDocument();
doc.Add(head);
}
private void CreateXML(string attname, string att)
{
XElement xelem = new XElement("name", new XElement("child", new XAttribute(attname, att), segment));
_xelemlist.Add(xelem);
}
private void ExtractSegment(HtmlNode node)
{
HtmlAttribute[] segatts = node.Attributes.ToArray();
string attname = segatts[0].Value.ToString();
string att = node.InnerText.ToString();
CreateXML(attname, att);
}
private HtmlDocument ParseDoc(HtmlDocument document)
{
try
{
HtmlNode root = document.DocumentNode.FirstChild;
foreach (HtmlNode childnode1 in root.SelectNodes(".//child1"))
{
foreach (HtmlNode childnode2 in node.SelectNodes(".//child2"))
{
ExtractSegment(childnode2);
}
}
}
catch (Exception e) { }
WriteXml();
return document;
}
When I comment out the "List.Add()" in "CreateXML()" and step through the code, the foreach loop is not broken out of after the first iteration, and the code works properly.
I have no idea what I'm doing wrong (And yes, the code is instantiated by a public member, don't worry: I am only posting the relevant internal methods to my problem)... if anyone has come across this sort of behavior before, I would really appreciate a push in the right direction to attempt to correct it... Sepcifically: is the problem just poor coding, or is this behavior a result of a property of one of the methods/libraries I am using?
One Caveat: I know that I am using HTMLAgilityPack to parse a file and extract information, but a requirement on this code forces me to use XDocument to write said information... don't ask me why.
I have no idea what I'm doing wrong
This, for starters:
catch (Exception e) { }
That's stopping you from seeing what on earth's going on. I strongly suspect you've got a NullReferenceException due to _xelemlist being null, but that's a secondary problem. The main problem is that by pretending everything's fine whatever happens, with no logging whatsoever, the only way of getting anywhere is by debugging, and that's an awful experience when you don't need to go through it.
It's extremely rarely a good idea catch exceptions and swallow them without any logging at all. It's almost never a good idea to do that with Exception.
Whenever you have a problem which is difficult to diagnose, improve your diagnostic capabilities first. That way, when you next run into a problem, it'll be easier to diagnose.
Declare the List this way,
private List<XElement> _xelemlist = new List<XElement>();
In your foreach loop, you are attempting to use XElement head as a list of XElements when you add() to it. This should probably be a list of XElements?
Might I suggest switching to using XmlDocument?
Here is some sample code which I have written for work (changed to protect my work :D), and we are using it rather well.
Code:
XmlDocument doc = new XmlDocument();
XmlNode root;
if(File.Exists(path + "\\MyXmlFile.xml"))
{
doc.Load(path + "\\MyXmlFile.xml");
root = doc.SelectSingleNode("//Library");
}
else
{
XmlDeclaration dec = doc.CreateXmlDeclaration("1.0", "UTF-8", null);
doc.AppendChild(dec);
root = doc.CreateElement("Library");
doc.AppendChild(root);
}
XmlElement book = doc.CreateElement("Book");
XmlElement title = doc.CreateElement("Title");
XmlElement author = doc.CreateElement("Author");
XmlElement isbn = doc.CreateElement("ISBN");
title.InnerText = "Title of a Book";
author.InnerText = "Some Author";
isbn.InnerText = "RandomNumbers";
book.AppendChild(title);
book.AppendChild(author);
book.AppendChild(isbn);
root.AppendChild(book);
doc.Save(path + "\\MyXmlFile.xml");
I have looked all over for this. It could be me just typing the wrong thing in search I'm not sure. So, if you know a good tutorial or example of this please share. I'm trying to learn.
I have a C# Windows Form app I'm working on. I have information (movies in this case) saved in an XML file. I saved the xml file like this.
//Now we add new movie.
XmlElement nodRoot = doc.DocumentElement;
string allMyChildren = nodRoot.InnerText;
string capitalized = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(movieEditNameTextbox.Text);
int indexLookForNewMake = allMyChildren.IndexOf(capitalized);
if (indexLookForNewMake >= 0)
{
MessageBox.Show("Movie is already saved.", "Error");
}
else
{
XmlElement el = doc.CreateElement("Name");
el.InnerText = capitalized;
doc.DocumentElement.AppendChild(el);
//Check if Year is really a Number.
if (movieEditYearTextbox.Text.All(Char.IsDigit))
{
//Remove ' cause it gives errors.
string capitalizedFixed = capitalized.Replace("'", "");
string capitalizedFinalFixed = capitalizedFixed.Replace("\"", "");
//Assign Attribute to each New one.
el.SetAttribute("Name", capitalizedFinalFixed);
el.SetAttribute("Type", movieEditTypeDropdown.Text);
el.SetAttribute("Year", movieEditYearTextbox.Text);
//Reset all fields, they don't need data now.
movieEditNameTextbox.Text = "";
movieEditYearTextbox.Text = "";
movieEditTypeDropdown.SelectedIndex = -1;
removeMovieTextbox.Text = "";
doc.Save("movie.xml");
label4.Text = "Movie Has been Edited";
loadXml();
}
else
{
//Error out. Year not a Number
MessageBox.Show("Check movie year. Seems it isn't a number.", "Error");
}
}
That all works fine. Now what I'm trying to do is make it where you can choose a directory, and it search the directory and sub directories and get file names and save them into the XML file.
I used this to try to accomplish this. It does pull the list. But it doesn't save it. It don't save the new information.
I can't use LINQ as it cause a confliction for some reason with other code.
DirectoryInfo dirCustom = new DirectoryInfo(#"D:\Video");
FileInfo[] filCustom;
filCustom = dirCustom.GetFiles("*",SearchOption.AllDirectories);
//Open XML File.
XmlDocument doc = new XmlDocument();
doc.Load("movie.xml");
XmlElement el = doc.CreateElement("Name");
string fulCustoms = filCustom.ToString();
foreach (FileInfo filFile in filCustom)
{
string capitalized = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(filFile.Name);
string capitalizedFixed = capitalized.Replace("\"", "");
el.SetAttribute("Name", capitalizedFixed);
el.SetAttribute("Type", "EDIT TYPE");
el.SetAttribute("Year", "EDIT YEAR");
richTextBox1.AppendText(capitalizedFixed + "\r\n");
}
doc.Save("movie.xml");
label4.Text = "Movie Has been Edited";
loadXml();
Now, the richTextBox does display the information correctly but it don't save it.
The loadXml() is just my noobish way to refresh the datagridview.
I'm completely lost and don't know where to turn to. I know my coding is probarely horrible, lol. I'm new to this. This is my first more complex application I have worked on.
I can't think of anymore information that would help you understand what I mean. I hope you do.
Thank you so much for your help.
Not sure exactly what your LoadXML() method does but my only piece of advise with your issue is to change the way you are implementing this functionality.
Create an object called Movie
public class Movie
{
public Movie() {}
public String Title { get; set; }
blah... blah...
}
Then create a MovieList
public class MovieList : List<Movie> { }
Then implement the following 2 methods inside the MovieList.
public static void Serialize(String path, MovieList movieList)
{
XmlSerializer serializer = new XmlSerializer(typeof(MovieList));
using (StreamWriter streamWriter = new StreamWriter(path))
{
serializer.Serialize(streamWriter, movieList);
}
}
public static MovieList Deserialize(String path)
{
XmlSerializer serializer = new XmlSerializer(typeof(MovieList));
using (StreamReader streamReader = new StreamReader(path))
{
return (MovieList) serializer.Deserialize(streamReader);
}
}
Thats it... You now have your object serialized and you can retrieve the data to populate through binding or whatever other methods you choose.
I'm currently using the code below to attempt to check for a certain root node (rss) and a certain namespace\prefix (itunes), but it seems to be saying that the feed is valid even when supplied with a random web page URL instead of one pointing to a feed.
FeedState state = FeedState.Invalid;
XmlDocument xDoc = new XmlDocument();
xDoc.Load(_url);
XmlNode root = xDoc.FirstChild;
if (root.Name.ToLower() == "rss" && root.GetNamespaceOfPrefix("itunes") == "http://www.itunes.com/dtds/podcast-1.0.dtd")
{
state = FeedState.Valid;
}
return state;
Can anybody tell me why this might be?
Found the solution now. Putting xDoc.Load(_url); in a try .. catch block and returning FeedState.Invalid upon exception seems to have solved my problems.
FeedState state = FeedState.Invalid;
XmlDocument xDoc = new XmlDocument();
try
{
xDoc.Load(_url);
}
catch
{
return state;
}
XmlNode root = xDoc.FirstChild;
if (root.Name.ToLower() == "rss" && root.GetNamespaceOfPrefix("itunes") == "http://www.itunes.com/dtds/podcast-1.0.dtd")
{
state = FeedState.Valid;
}
return state;