I am trying to deserialize XML from SSIS DTSX files. I have found the XSD files which I think are needed, found here: https://msdn.microsoft.com/en-us/library/gg587628%28v=sql.105%29.aspx. I have used xsd2code plugin for VS to create objects from the XSDs.
The problem: I am able to deserialize into these objects, but almost no actual data gets pulled in from the DTSX files.
In the code below, I have placed a break point at the WriteLine() command in Parse_XML() and looked at the contents of the two ExecutableTypePackage objects (executables and exec). Both have the same contents:
The property ExecutableType gets set to "SSIS.Package.3"
The Property collection (List<ExecutableTypePackageProperty>) has one element; its Name property is set to "PackageFormatVersion" and Value property is set to "6".
That's all. While those values are correct, there's a lot more data in the file that's not getting pulled in. But I get no warnings nor exceptions.
Admittedly, I don't have much experience with XML, and using the serialization methods is very new to me, but I have used them for validating the XML structure of report files (RDL), and never ran across any such issues. I have been beating my head against the wall for 2 full days on this now, and I am not making any progress. I have searched every which way I can think of for answers on this, but I don't find anyone else having this problem.
string file = null;
public Form1()
{
InitializeComponent();
}
private void Run_btn_Click(object sender, EventArgs e)
{
Parse_XML();
MessageBox.Show("Done!");
}
private void Parse_XML()
{
TextReader tr = new StreamReader(file);
XmlSerializer serializer = new XmlSerializer(typeof(DTSX.ExecutableTypePackage));
DTSX.ExecutableTypePackage executables = (DTSX.ExecutableTypePackage)serializer.Deserialize(tr);
DTSX.ExecutableTypePackage exec = DTSX.ExecutableTypePackage.Deserialize(File.ReadAllText(file));
MessageBox.Show(String.Format("Found {0} executables in package.", exec.Executable.Count));
Console.WriteLine("Done loading root object.");
}
private void File_btn_Click(object sender, EventArgs e)
{
int text_size = -1;
DialogResult result = openFileDialog1.ShowDialog();
if (result == DialogResult.OK)
{
file = openFileDialog1.FileName;
try
{
string text = File.ReadAllText(file);
text_size = text.Length;
File_txtbx.Text = file;
}
catch (IOException)
{
}
}
Console.WriteLine(file);
Console.WriteLine(text_size);
Console.WriteLine(result);
}
Related
I am writing a Windows Form Application for data post-processing. I have a panel where I allow for files to be dragged and dropped. The XML files will be quite large (enough to slow the UI down). Therefore I would like to read the file in asynchronously. So far for this part of the app I have two methods:
namespace myApp
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void DragDropPanel_DragEnter(object sender, DragEventArgs e)
{
// Trigger the Drag Drop Event
e.Effect = DragDropEffects.Copy;
}
private async void DragDropPanel_DragDrop(object sender, DarEventArgs e)
{
// Identifiers used are:
string[] filePaths = (string[])e.Data.GetData(DataFormats.FileDrop);
string filePath = filePaths[0],
fileName = System.IO.Path.GetFileName(filePath);
// Read in the file asynchronously
XmlReader reader = XmlReader.Create(filePath);
//reader.Settings.Async = true; // ** (SECOND ERROR) ** \\
while (await reader.ReadAsync()) // ** (FIRST ERROR) ** \\
{
Console.WriteLine("testing...");
}
// Do other things...
}
}
}
Now when I drag and drop the XML file I get the following error:
System.InvalidOperationException:
Set XmlReaderSettings.Async to true if you want to use Async Methods.
this error occurs because of the line I labeled with FIRST ERROR. I attempt to fix this by uncommenting the line above it which I have labeled with SECOND ERROR. Now when I drag and drop I get the error:
System.Xml.Xml.XmlException:
The XmlReaderSettings.Async property is read only and cannot be set
So I go to the MS Docs for the XmlReaderSettings.Async property and it says:
You must set this value to true when you create a new XmlReader instance if you want to use asynchronous XmlReader methods on that instance.
Which then gives the reason why the SECOND ERROR occurs. However, I cannot get this to work. Any tips?
You need to Create the XmlReader with the proper settings.
XmlReaderSettings settings = new XmlReaderSettings
{
Async = true
};
XmlReader reader = XmlReader.Create(filePath, settings);
References:
https://msdn.microsoft.com/en-us/library/ms162474(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/system.xml.xmlreadersettings(v=vs.110).aspx
Solved - Accidentally wiped the actual file of data but the ide doesn't update that file unless you reopen it so I thought the data was still in there.
I'm working on a project in C# that reads in a fake inventory and then transactions to go with that inventory in another class. I know the code is quite messy at the moment, i'm just trying to figure out one thing specifically.
this code here will read in my file "Inventory.in", check if the file exists(which it does) and then start my streamreader and readline into a string.
private void btnFill_Click(object sender, EventArgs e)
{
string strInputLine;
string inFile = "Inventory.in";
StreamReader iSR;
InvRec currInvent;
if (File.Exists(inFile))
{
iSR = new StreamReader(inFile);
strInputLine = iSR.ReadLine();
while (strInputLine != null)
{
all of it isn't there but the point of emphasis is that the
"strInputLine = iSR.ReadLine();"
does indeed give me the correct value from that file.
now moving on to my question, the second block of code from another button is below:
private void btnProcess_Click(object sender, EventArgs e)
{
string strInputVal;
string inFileName = "Transactions.in";
TransRec currTrans;
StreamReader iSR2;
transListClass transactionList = new transListClass();
InvRec inventItem = inventoryList.Retrieve();
if (File.Exists(inFileName))
{
iSR2 = new StreamReader(inFileName);
strInputVal = iSR2.ReadLine();
while (strInputVal != null)
{
my problem lies when I try and do my ReadLine() into iSR2. it gives me null instead of the value from the file I'm supposed to get. Everything is the same otherwise, it just refuses to give me the correct value. I'm following the debugger in Visual Studio 2010, so I know the file is found and exists, I see it being opened, just a null value instead of my string I need.
Thank you to anybody in advance, I appreciate it.
-Anthony
edit:
the second block of code is supposed to read from "Transactions.in" instead of the first one that reads from "Inventory.in"
Important edit:
I have noticed when i changed "Transactions.in" to "Inventory.in" in the second block of code for the process button, it reads the values from Inventory.in and gives me a proper string unlike null from Transactions.in. The file is found and is just a text file named Transactions.in that was provided by my teacher, nobody else had a problem with it.
I have a combobox which gets the list of items from the name of files I put together in one directory, the purpose for this is to make it dynamic - I'm very new to c# and it didn't occur to me a different way. - Here's the code for that bit:
string[] files = Directory.GetFiles(templatePath);
foreach (string file in files)
cbTemplates.Items.Add(System.IO.Path.GetFileNameWithoutExtension(file));
Basically, that works just fine, it populates my combobox with the names of the files I have in that path, the problem is that I need to open the file that's selected in the combobox and read its contents and place them in labels, I was thinking maybe StreamReader would help me here but I have NO clue on how to implement it, I've searched the internet but it looks like no one had the same idea before me. Can someone please point me in the right direction? A link to something similar or a guide of the objects I need to use would be great, thanks!
what you should do is store the names of the files in a single separate file (csv or xml). then use this file to both load the combobox and as an indexer.
for example lets say you have files a.txt, b.txt, and c.txt. you should (as you already are) read the file names programmatically THEN write them to a new file in whichever format you want, including a unique index scheme (numbers work fine).
your csv might look like this:
1, a.txt,
2, b.txt,
3, c.txt,
from here you can parse the newly created csv to your liking. Use it to populate your combobox, index being its value and filename its text. Then you can read your combobox selectedvalue, get the proper filename from the csv index, and finally open the file.
It may be longwinded but it'll work. You could also just use a multidimensional array, but this is more fun from an educational stand point, and it will help you with read/write operations.
It is not so easy to understand your problem. Do you want just to display filename w/o extension in your combobox? I hope this code will be usefull to you.
internal class FileDetail
{
public string Display { get; set; }
public string FullName { get; set; }
}
public partial class Example: Form // This is just widows form. InitializeComponent is implemented in separate file.
{
public Example()
{
InitializeComponent();
filesList.SelectionChangeCommitted += filesListSelectionChanged;
filesList.Click += filesListClick;
filesList.DisplayMember = "Display";
}
private void filesListClick(object sender, EventArgs e)
{
var dir = new DirectoryInfo(_baseDirectory);
filesList.Items.AddRange(
(from fi in dir.GetFiles()
select new FileDetail
{
Display = Path.GetFileNameWithoutExtension(fi.Name),
FullName = fi.FullName
}).ToArray()
);
}
private void filesListSelectionChanged(object sender, EventArgs e)
{
var text = File.ReadAllText(
(filesList.SelectedItem as FileDetail).FullName
);
fileContent.Text = text;
}
private static readonly string _baseDirectory = #"C:/Windows/System32/";
}
Thanks for all your help folks but I figured out how to get around my issue, I'll post the code for future incidents. pd. Sorry it took me this long to reply, I was on vacation
string[] fname = Directory.GetFiles(templatePath); // Gets all the file names from the path assigned to templatePath and assigns it to the string array fname
// Begin sorting through the file names assigned to the string array fname
foreach (string file in fname)
{
// Remove the extension from the file names and compare the list with the dropdown selected item
if (System.IO.Path.GetFileNameWithoutExtension(file) != cbTemplates.SelectedItem.ToString())
{
// StreamReader gets the contents from the found file and assigns them to the labels
using (var obj = new StreamReader(File.OpenRead(file)))
{
lbl1.Content = obj.ReadLine();
lbl2.Content = obj.ReadLine();
lbl3.Content = obj.ReadLine();
lbl4.Content = obj.ReadLine();
lbl5.Content = obj.ReadLine();
lbl6.Content = obj.ReadLine();
lbl7.Content = obj.ReadLine();
lbl8.Content = obj.ReadLine();
lbl9.Content = obj.ReadLine();
lbl10.Content = obj.ReadLine();
obj.Dispose();
}
}
}
I have a CSV file in this format:
"Call Type","Charge Type","Map to"
"51","","Mobile SMS"
"52","","Mobile SMS"
"DD","Local Calls","Local Calls"
"DD","National Calls","National Calls"
First two columns are the "source information" that my C# will insert, and the last column is what it will return.
Currently what I am doing is a switch statement hardcoded in c#.
var File001 = from line in File.ReadLines(bill_file)
let l = line.Split(',')
select new
{ CallType = ICD_map(l[5],l[3])}
where
l[5] = "51";
l[3] = "";
private static string ICD_map(string call_type_description, string call_category,)
{
case "51":
case "52":
return "Mobile SMS";
default:
return "Unknown";
}
I want this to be an expandable list thus my new method is to load the mapping table from a csv file. Can you suggest any improvements to this method to make my definition library expandable (hoping CSV file okay for this purpose, it is only 100 lines long so far, so not concerned about memory management).
What I have tried so far is:
class ICD_Map2
{
private string call_type;
private string charge_type;
private string map_to;
// Default constructor
public ICD_Map2() {
call_type = "Unknown";
charge_type = "Unknown";
map_to = "Unknown";
}
// Constructor
public ICD_Map2(string call_type, string charge_type, string map_to)
{
this.call_type = call_type;
this.charge_type = charge_type;
this.map_to = map_to;
}
}
List<ICD_Map2>maps = new List<ICD_Map2>();
private void button2_Click(object sender, EventArgs e)
{
// Start new thread to create BillSummary.csv
button1.Enabled = false;
maps.Clear();
//load mapping file
var reader = new StreamReader(File.OpenRead(#"Itemised_Call_Details_Map.csv"));
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split(',');
maps.Add(new ICD_Map2(values[0].Replace("\"",""), values[1].Replace("\"",""), values[2].Replace("\"","")));
textBox2.AppendText(Environment.NewLine + " Mapping: " + values[0].Replace("\"", "") + " to " + values[1].Replace("\"", ""));
}
I have loaded the CSV file to my program but I am unable to do the lookup from LINQ. Can you tell me the next process.
Open to any other method.
Thanks for your time.
I would suggest you to go with
http://www.codeproject.com/Articles/9258/A-Fast-CSV-Reader
It will give you lots of flexibility to play around with your code.
We have been using it in our projects, and it's really helpful to have full control inplace of writing generic CSV code which is prone to errors and bugs
I've got a very strange issue while parsing an external XAML file. The pre-history is that I want to load an external XAML file with content to process. But I want to load as many different files as I want. That happens by unloading the old and loading the new one.
My issue is:
When I load a xaml the first time, everything is good, all as it should be.
But when I load the same xaml the second time, every entry of the object im Loading is there twice. If I run this again, every object is there three times and so on...
To debug the project yourself, download it here. The function starts at line 137 in the file "Control Panel.xaml.cs". I realy don't know what this is. Is it my fault or simply a bug? If yes, is there a workaround?
/// <summary>
/// Load a xaml file and parse it
/// </summary>
public void LoadPresentation()
{
this.Title = "Control Panel - " + System.IO.Path.GetFileName(global.file);
System.IO.FileStream XAML_file = new System.IO.FileStream(global.file, System.IO.FileMode.Open);
try
{
System.IO.StreamReader reader = new System.IO.StreamReader(XAML_file);
string dump = reader.ReadToEnd(); //This is only for debugging purposes because of the strange issue...
XAML_file.Seek(0, System.IO.SeekOrigin.Begin);
presentation = (ResourceDictionary)XamlReader.Load(XAML_file);
//Keys the resourceDictionary must have to be valid
if (presentation["INDEX"] == null || presentation["MAIN_GRID"] == null || presentation["CONTAINER"] == null || presentation["LAYOUTLIST"] == null)
{
throw new Exception();
}
//When this list is loaded, every item in it is there twice or three times or four... Why????
TopicList Index = null;
Index = (TopicList)presentation["INDEX"];
for (int i = 0; i < topics.Count; )
{
topics.RemoveAt(i);
}
foreach (TopicListItem item in Index.Topics)
{
topics.Insert(item.TopicIndex, (Topic)presentation[item.ResourceKey]);
}
lv_topics.SelectedIndex = 0;
selectedIndex = 0;
}
catch
{
System.Windows.Forms.MessageBox.Show("Failed to load XAML file \"" + global.file + "\"", "Parsing Error", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
presentation = null;
}
finally
{
XAML_file.Close();
}
}
Edit:
I have tried to serialize the object that was read from the XamlReader and in the output was nowhere any childelement... But if I pull the object out of the dictionary, the children are all there (duplicated and triplicated, but there).
I have already tried to clear the list over
topics.Clear();
and
topics=new ObservableCollection<TopicListItem>();
lv_topics.ItemsSource=topics;
Try Index.Topics.Clear() after loading the Topics into your topics object. That appears to get rid of the duplication.
//When this list is loaded, every item in it is there twice or three times or four... Why????
TopicList Index = null;
Index = (TopicList)presentation["INDEX"];
topics.Clear();
foreach (TopicListItem item in Index.Topics)
{
topics.Insert(item.TopicIndex, (Topic)presentation[item.ResourceKey]);
}
Index.Topics.Clear(); //Adding this will prevent the duplication
lv_topics.SelectedIndex = 0;
selectedIndex = 0;
In the code post topics is not declared in LoadPresentation() so naturally it will have any prior values.
I know you said you tried topics=new ObservableCollection(); but please try again. And put that IN LoadPresentation()
public void LoadPresentation()
{
ObservableCollection<TopicListItem> topics = new ObservableCollection<TopicListItem>()
I would pass filename
public void LoadPresentation(string fileName)
I get you may need to use topics outside LoadPresentation but this is debugging. If you need topics outside the return it.
public ObservableCollection<TopicListItem> LoadPresentation(string fileName)
If that does not fix it I would put a try catch block on the XAML_file.Close(); to see if something weird is not going on.