|
Hello,
I am trying to read an XML file and break it up into smaller chunks but am having real problems in doing so as I have never used XML before.
I wish to read a large XML document and cycle through it, copying each record to a new file that I have created (with the relevant header info), until I have 1000 records, then start again. The format of the records is:
<Record>
<attribute1>blah blah</attribute1>
<attribute2>blah blah</attribute2>
<attribute3>blah blah</attribute3>
</Record>
So far I have created the following code:
while (fileReader != null)
{
// Create a file to write to
XmlTextWriter fileWriter = new XmlTextWriter(directory + "\\Output" + x + " myXMLfile.xml", System.Text.Encoding.GetEncoding("ISO-8859-1"));//null);
//fileWriter.WriteStartDocument();
// Write the header details to the new file
fileWriter.WriteProcessingInstruction("xml", "version='1.0' encoding='ISO-8859-1'");
fileWriter.WriteComment("Some commentd");
fileWriter.WriteStartElement("message");
fileWriter.WriteAttributeString("xmlns", "xsi", null, "http://www.w3.org/2001/XMLSchema-instance");
fileWriter.WriteAttributeString("xsi", "noNamespaceSchemaLocation", null, "myXSD.xsd");
// Add 'messageHeader' as part of the header
while (fileReader.Name != "messageHeader")
{
fileReader.Read();
}
fileWriter.WriteNode(fileReader, true);
// Write each row to the file, until 1000 records have been written
for (int i = 1; i <= 1001; i++)
{
while (fileReader.Name != "CISKASNRecord")
fileReader.Read();
fileWriter.WriteNode(fileReader, true);
fileWriter.Flush();
}
// Tidy up and close the file so that a new one can be opened
fileWriter.WriteEndElement();
fileWriter.Close();
x++;
}
I can create a new XML file which prints the header info, then begins to cycle through and print the records as expected (hoped!). However, it crashes at the second document with the following error:
"XML document must have a top level element."Error processing resource 'file:///C:/........"
If I increase the size of my for-loop to include all records to see what happens it crashes at the end of the file with the following error:
"The following tags were not closed: message"
I guess this may be the real reason for my errors, however the C# code looks to close all tags so I can't see how this error is appearing? Can anybody help here please?
|
|
|
|
|
You plain cannot do this. Any XML document must have a top level element. In other words, this is XML:
<tag>
<tag1/>
<tag2/>
<tag>
This is not:
<tag1/>
<tag2/>
When you break up your XML, you lose the symmetry of tags, and you are obviously also losing the top level tag.
-- modified at 6:07 Thursday 21st September, 2006
Christian Graus - Microsoft MVP - C++
Metal Musings - Rex and my new metal blog
|
|
|
|
|
Thanks for the reply Christian; however, your code did not appear in your response.
What little I have learnt about XML is the need for a top level element. What is stumping me is the fact that it appears in the first file, but not in the second - yet it is within the loop so for all I can see, should do. As you say, I am losing the top level tag somewhere, but I really don't see where...
|
|
|
|
|
bigove wrote: however, your code did not appear in your response.
Sorry, fixed it.
bigove wrote: What is stumping me is the fact that it appears in the first file, but not in the second
The nature of your code makes it random. Some XML fragments will be broken, some will not. If you're going a tag at a time, the first one will have to fail, it will write the opening top level tag, and by definition will not close it.
You cannot break an XML document into a group of smaller ones, at least not with brute force, or unless you at least add a top level tag to each group and remove it later.
Christian Graus - Microsoft MVP - C++
Metal Musings - Rex and my new metal blog
|
|
|
|
|
I don't understand how it doesn't write the top level tag in the second file, yet does for the first one. On it's own I could follow this, but the fact that if I increase the for-loop to include all records it errors saying the 'message' tag was not closed confuses me - as it is closed and works fine for 1000 records?
What does concern me is the way you say an XML document cannot be 'broken up'. I really need to do so, so am I chasing a lost cause? Or how would adding the top level tag suggestion work?
Thank you for your help.
|
|
|
|
|
Well, it depends on the schema. IF your schema is simple enough, then you can probably break it up so long as you add a top level tag to each new document. But if the schema is complex, then your problem is, every tag that gets opened, needs to be closed in the same document or it's no longer XML. And if your schema is just
record1
record2
record3
all the way down, one wonders if XML is overkill, that schema doesn't give you anything that a flat file wouldn't give you.
Christian Graus - Microsoft MVP - C++
Metal Musings - Rex and my new metal blog
|
|
|
|
|
The part that I don't understand is the top level tags; I add them at the beginning of my while-loop and close them at the end, so the XML document is 'correct'. But then there seems to be some issue with opening up the second saved file - yet it uses the same part of code that adds the tags at the beginning, so should open. When I increase the for-loop to include all records it errors saying my tag isn't closed - yet it is, and closes fine for the smaller loop...
|
|
|
|
|
Progress? Not sure...
If I comment out the part that adds 'messageHeader', the first file completes and this time I can open the seciond file. This has some records in, before near the end it has the error saying 'message' was not closed, even though it is in my code. I don't know if this helps, but I feel I'm getting closer!
|
|
|
|
|
Hi
i made a search module that search a file in any selected drive.
How can i use a progress bar
what will be tha min ,max time and increament steps
|
|
|
|
|
How long is a piece of string ?
You really have no way of knowing. That's why windows tends to show a progress bar that just moves back and forth in those sort of scenarios, or even if it's copying files, it shows a time but often gets it wrong.
Christian Graus - Microsoft MVP - C++
Metal Musings - Rex and my new metal blog
|
|
|
|
|
Hi,
It will be decided dynamically on the basis of total number of files searched in the worst case, i.e. total number of files present in the directory.
for eg, say you have 10000 files then min will be 0 max will be 100 step will be 1, after every 100 files are searched the step will be incremented and when you find the specific file the value will become 100, and about time... well, Chris is right, you never know exactly.
Waqas Nasir,
Software Engineer,
EzValidation Inc,
Karachi,
Pakistan.
|
|
|
|
|
Hello everybody.
Someone know how show on toolStripProgressBar the progress at retrive data from SQL Query?
Example:
SQL Structure:
CREATE TABLE [student](<br />
[student_id] INT NOT NULL IDENTITY(1,1),<br />
[student_name] VARCHAR(50) NOT NULL,<br />
[student_lastname] VARCHAR(70) NOT NULL,<br />
[student_age] TINYINT NOT NULL,<br />
[student_since] SMALLDATETIME NOT NULL DEFAULT GETDATE(),<br />
[student_grade] TINYINT NOT NULL,<br />
[student_active] BIT NOT NULL DEFAULT 1,<br />
PRIMARY KEY( [student_data_id] )<br />
)
CREATE TABLE [class](<br />
[class_id] SMALLINT NOT NULL IDENTITY(1,1),<br />
[class_name] VARCHAR(50) NOT NULL,<br />
[class_acive] BIT NOT NULL DEFAULT 1,<br />
PRIMARY KEY( [class_id] )<br />
)
CREATE TABLE [class_by_student](<br />
[class_id] REFERENCES [class] ( [class_id] ),<br />
[student_id] REFERENCES [student]( [student_id] ),<br />
PRIMARY KEY( [class_id], [student_id] )<br />
)<br />
C# Code:
<br />
using System;<br />
using System.Data;<br />
using System.Data.SqlClient;<br />
using System.Windows.Forms;<br />
using System.Thread;<br />
<br />
public class Form1 : Form<br />
{<br />
private System.ComponentModel.IContainer components = null;<br />
private StatusStrip sb;<br />
private ToolStripProgressBar pb;<br />
DataGridView dg;<br />
Thread Thread4LoadData;<br />
<br />
public Form1()<br />
{<br />
this.makeForm();<br />
}<br />
<br />
public makeForm()<br />
{<br />
this.sb = new StatusStrip();<br />
this.pb = new ToolStripProgressBar();<br />
this.dg = new DataGridView();<br />
((System.ComponentModel.ISupportInitialize)(this.dg)).BeginInit();<br />
this.sb.SuspendLayout();<br />
this.SuspendLayout();<br />
<br />
this.sb.Items.Add(this.pb);<br />
this.sb.Name = "sb";<br />
<br />
this.pb.Name = "pb";<br />
this.pb.Size = new System.Drawing.Size(100, 16);<br />
<br />
this.dg.Location = new System.Drawing.Point(12, 42);<br />
this.dg.Name = "dg";<br />
this.dg.Size = new System.Drawing.Size(464, 374);<br />
<br />
this.Controls.Add(this.sb);<br />
this.dg.Add(this.dg);<br />
((System.ComponentModel.ISupportInitialize)(this.dg)).EndInit();<br />
this.Name = "Form1";<br />
this.Text = "Staudents";<br />
this.Load += new System.EventHandler(this.Form1_Load);<br />
this.sb.ResumeLayout();<br />
this.sb.PerformLayout();<br />
this.ResumeLayout(false);<br />
this.PerformLayout();<br />
}<br />
<br />
private void Form1_Load()<br />
{<br />
Thread4LoadData = new Thread( new ThreadStart( this.LoadData ) );<br />
Thread4LoadData.Start();<br />
}<br />
<br />
private void LoadData()<br />
{<br />
string connStr = "server=myserver.com.;database=school;uid=sa;password=666;Trusted_Connection=False;";<br />
SqlConnection conn = new SqlConnection(connStr);<br />
conn.open();<br />
<br />
string SQL;<br />
SQL="SELECT * " + <br />
"FROM [class_by_student] AS [cs]" +<br />
"JOIN [class] AS [c] ON [c].[class_id] = [cs].[class_id]" +<br />
"JOIN [student] AS [s] ON [s].[student_id] = [cs].[student_id]" +<br />
"WHERE [s].[student_active] = 1 " +<br />
"AND [c].[class_active] = 1" +<br />
"ORDER BY [S].[student_name]";<br />
<br />
DataSet dts = new DataSet();<br />
<br />
SqlDataAdapter da = new SqlDataAdapter( SQL, conn );<br />
da.Fill(dts, "schools");<br />
this.dg.DataSource = dts;<br />
this.dg.DataMember = "schools";<br />
conn.close();<br />
}<br />
}<br />
I need show the progress when data is downloading because sometimes the time is longer.
SINCERELY.
ANTHONY ACUÑA
PREFERED PHRASE:
SOMEBODY TELL ME WHY IS MORE REAL WHEN I DREAM THAT I AM WAKE?
|
|
|
|
|
You can't. Your query starts, and it ends, there's no step in between where you get feedback from the db or, ( in a single threaded app ) where your code does anything at all.
Christian Graus - Microsoft MVP - C++
Metal Musings - Rex and my new metal blog
|
|
|
|
|
lo;
i am reading a string from my comm port,
i want to check it wether it is a letter or a number,
if it is a letter i need to give an error, if it is a number i want to check if it is smaller then 500
how do i do this?
grz & thx
|
|
|
|
|
If it's a char, you can use Char.IsDigit and Char.IsLetter. If it's a full string, then try this:
int n;
if (int.TryParse(str, out n) && n < 500)
{
}
else
{
// Not a number, or >= 500
}
Christian Graus - Microsoft MVP - C++
Metal Musings - Rex and my new metal blog
|
|
|
|
|
You can use a regular expression with the pattern "^\d{1,3}$" to check if the string contains only digits and not more than three digits. If it does, you can safely use int.Parse to parse it to an integer, and check the value.
---
b { font-weight: normal; }
|
|
|
|
|
thx, but i have found something else
public bool hasNumber(String s)
{
for (int j = 0; j < s.Length; j++)
{
if (!Char.IsDigit(s,j))
{
return false;
}
}
return true;
}
and to know wether it is a letter, just the oppesit :p
thx though
|
|
|
|
|
Yes, that works too. Or even simpler:
public bool hasNumber(String s) {
foreach (char c in s) if (!Char.IsDigit(c)) return false;
return true;
}
---
b { font-weight: normal; }
|
|
|
|
|
Hi,
I want to disable "Form Close" option of a child form if any background worker is busy in that form. How can I implement that in C# ?
Because, IF an user closes a child form when a background worker is busy in that form, then, very bad problem occurs when the background worker completed event triggered.
Regards.
|
|
|
|
|
Hi
Iam developing WindowsMobile Application VS2005, I want to bind Listview(with three columns) in a seperate thread bcoz it always needs to refresh from database by timer.
How can I use Control.Invoke with ListView?Is it possible.
I have tried ListBox Binding, but only one column possible.
Please help
|
|
|
|
|
Hi
i use a listbox control that contains number of files.i want to select multifiles and when i select a file a check should appear in front of file
How can i do this
Parshant
|
|
|
|
|
Hi
I think you are in wrong way.
There is no request to add checkbox to listbox control.
You can use CheckedListBox control, you can find it under listbox control in your toolbox.
Bye
|
|
|
|
|
But how can i do it in web application. there is no control like checkedlistbox ??
|
|
|
|
|
Hi Dear All Respected Programmers
Kindly let me know that, Is there any method of ConnectionString to connect with Oralce10g or (if any above 8x) database without installling Oracle client software or Oracle net?
Thank you in Advance
|
|
|
|
|
There is no way. You'll definitely need the client.
|
|
|
|
|