Xml bulk Nodes appending issue - c#

I want to generate a million record xml file.For this i have a sample xml file with only one value set.Using this xml file fill ramdom values a million times.
I created a solutin but it is very time consuming one.My code is
try
{
label1.Text = "File creation in progress ...";
Random rnd = new Random();
string sStartupPath = Application.StartupPath;
string sName = "";
int flag = 0;
XmlDocument XmlFile = new XmlDocument();
XmlFile.Load(sStartupPath + #"..\..\..\BankStatement.xml");
XmlFile.Save(#"C:\XmlData\Bank.xml");
XmlDocument XmlF = new XmlDocument();
XmlF.Load(#"C:\XmlData\Bank.xml");
long k = Convert.ToInt32(textBox1.Text);
for (int j = 1; j < k; j++)
{
XmlTextReader objXmlTextReader = new XmlTextReader(sStartupPath + #"..\..\..\BankStatement.xml");
while (objXmlTextReader.Read())
{
switch (objXmlTextReader.NodeType)
{
case XmlNodeType.Element:
sName = objXmlTextReader.Name;
if (sName == "DataXml")
{
if (flag == 0)
flag = 1;
}
break;
case XmlNodeType.Text:
if (flag == 1)
{
XmlNodeList elemList = XmlFile.GetElementsByTagName(sName);
for (int i = 0; i < elemList.Count; i++)
{
if (elemList[i].Name == "Name")
elemList[i].InnerXml = generateNames();
else if (elemList[i].Name == "EmailID")
elemList[i].InnerXml = generatemailids();
else
elemList[i].InnerXml = rnd.Next(500000).ToString();
}
}
break;
case XmlNodeType.EndElement:
sName = objXmlTextReader.Name;
if (sName == "DataXml")
{
if (flag == 1)
flag = 0;
}
break;
}
}
XmlDocument dd = new XmlDocument();
dd.LoadXml(XmlFile.InnerXml);
XmlNodeList node=dd.GetElementsByTagName("Customers");
XmlDocumentFragment xfrag = XmlF.CreateDocumentFragment();
xfrag.RemoveAll();
for (int i = 0; i < 1; i++)
{
xfrag.InnerXml = node[i].InnerXml;
XmlF.DocumentElement.FirstChild.AppendChild(xfrag);
}
XmlF.Save(#"C:\XmlData\Bank.xml");
}
label1.Visible = false;
MessageBox.Show("File creation success..!");
}
catch (Exception ex)
{
label1.Text = "";
MessageBox.Show("Error Occured");
}
Please give me a better solution.

The fastest method I know to write XML (short of building the XML fragments manually) is to use XmlWriter
The XmlWriter class is an abstract base class that provides a
forward-only, write-only, non-cached way of generating XML streams. It
can be used to build XML documents that conform to the W3C Extensible
Markup Language (XML) 1.0 (fourth edition) recommendation and the
Namespaces in XML recommendation.
MSDN has a walkthrough on how to use the abstract XmlWriter class.

For writing large XML files you should use XmlTextWriter.

Related

How to retrieve all Elements from XML file using c#

I am trying to retrieve all elements from an XML file, but I just can reach one, is there any way I can retrieve all?
HttpWebResponse objResponse = (HttpWebResponse)objRequest.GetResponse();
using (XmlReader reader = XmlReader.Create(new StreamReader(objResponse.GetResponseStream())))
{
while (reader.Read())
{
#region Get Credit Score
//if (reader.ReadToDescendant("results"))
if (reader.ReadToDescendant("ssnMatchIndicator"))
{
string ssnMatchIndicator = reader.Value;
}
if (reader.ReadToDescendant("fileHitIndicator"))
{
reader.Read();//this moves reader to next node which is text
result = reader.Value; //this might give value than
Res.Response = true;
Res.SocialSecurityScore = result.ToString();
//break;
}
else
{
Res.Response = false;
Res.SocialSecurityScore = "Your credit score might not be available. Please contact support";
}
#endregion
#region Get fileHitIndicator
if (reader.ReadToDescendant("fileHitIndicator"))
{
reader.Read();
Res.fileHitIndicator = reader.Value;
//break;
}
#endregion
}
}
Can somebody help me out with this issue?
I am also using objResponse.GetResponseStream() because the XML comes from a response from server.
Thanks a lot in advance.
Try this :
XmlDataDocument xmldoc = new XmlDataDocument();
XmlNodeList xmlnode ;
int i = 0;
string str = null;
FileStream fs = new FileStream("product.xml", FileMode.Open, FileAccess.Read);
xmldoc.Load(fs);
xmlnode = xmldoc.GetElementsByTagName("Product");
for (i = 0; i <= xmlnode.Count - 1; i++)
{
xmlnode[i].ChildNodes.Item(0).InnerText.Trim();
str = xmlnode[i].ChildNodes.Item(0).InnerText.Trim() + " " + xmlnode[i].ChildNodes.Item(1).InnerText.Trim() + " " + xmlnode[i].ChildNodes.Item(2).InnerText.Trim();
MessageBox.Show (str);
}
I don't know why what you're doing is not working, but I wouldn't use that method. I've found the following to work well. Whether you're getting the xml from a stream, just put it into a string and bang...
StreamReader reader = new StreamReader(sourcepath);
string xml = reader.ReadToEnd();
reader.Close();
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
XmlNodeList list = doc.GetElementsByTagName("*");
foreach (XmlNode nd in list)
{
switch (nd.Name)
{
case "ContactID":
var ContactIdent = nd.InnerText;
break;
case "ContactName":
var ContactName = nd.InnerText;
break;
}
}
To capture what is between the Xml tags, if there are no child Xml tags, use the InnerText property, e.g. XmlNode.InnerText. To capture what is between the quotes in the nodes' attributes, use XmlAttribute.Value.
As for iterating through the attributes, if one of your nodes has attributes, such as the elements "Name", "SpectralType" and "Orbit" in the Xml here:
<System>
<Star Name="Epsilon Eridani" SpectralType="K2v">
<Planets>
<Planet Orbit="1">Bill</Planet>
<Planet Orbit="2">Moira</Planet>
</Planets>
</Star>
</System>
Detect them using the Attributes property, and iterate through them as shown:
if (nd.Attributes.Count > 0)
{
XmlAttributeCollection coll = nd.Attributes;
foreach (XmlAttribute cn in coll)
{
switch (cn.Name)
{
case "Name":
thisStar.Name = cn.Value;
break;
case "SpectralType":
thisStar.SpectralClass = cn.Value;
break;
}
}
}
You might find some more useful information HERE.

Generate Xml from Xsd with ado.net

I want to generate xml from a xsd, this xml I want to contain specify attributes from xsd. Any ideas?
string fn = System.IO.Path.GetFileName(File1.PostedFile.FileName);
string SaveLocation = Server.MapPath("Data") + "\\" + fn;
try
{
File1.PostedFile.SaveAs(SaveLocation);
Response.Write("The file has been uploaded.");
}
catch (Exception ex)
{
Response.Write("Error: " + ex.Message);
//Note: Exception.Message returns a detailed message that describes the current exception.
//For security reasons, we do not recommend that you return Exception.Message to end users in
//production environments. It would be better to put a generic error message.
}
try
{
XmlTextReader reader = new XmlTextReader(SaveLocation);
//XmlSchema myschema = XmlSchema.Read(reader, ValidationCallback);
while (reader.Read())
{
// LiteralURL.Text += reader.ReadString();
}
// Response.Write("\t"+myschema.Items);
XDocument doc = XDocument.Load(SaveLocation);
var ListNode = new List<XNode>();
if (doc != null)
{
Response.Write("nu este null");
}
else
{
Response.Write("Null !");
}
int i = 0;
string str = "";
foreach (XNode nodes in doc.Elements())
{
str = "node1: " + nodes.ToString();
ListNode[i] = nodes;
i++;
}
for(int j = 0; j < i; i++)
{
Response.Write("FirstNode:"+ ListNode[j]);
}
//Response.Write("FirstNode:" );
Response.Write(str);
}
catch (Exception ex)
{
}
}
else
{
Response.Write("Please select a file to upload.");
}
Have a look at xsd.exe. You run this against your XSD and it gives you classes based on the XSD elements and attributes. You don't need to work with raw XML or XSD after that.

Reading the string from a txt file and converting it to elements in xml using c#

I have a string like this { {Name Mike} {age 19} {gender male}} in a txt file.
I would like this to be converted to xml as the below output. As i am new to this, it seems to be pretty doubts for me.
<name>Mike</name>
<age>19</age>
<gender>male</male>
any help would be appreciated.
Here is my solution, at first you have to create a xml file in my case I have created x.xml at my bin folder and must create a root elemnt on the xml file, in my case sample xml at the begening as below, root element name can be anything, I have used just root
<root>
</root>
then code for writting you string as below
string s = "{{Name Mike} {age 19} {gender male}}";
string[] s2 = s.Replace("{", "").Replace("}", "").Split(' ');
for (int i = 0; i < s2.Length; i++)
{
XDocument doc = XDocument.Load("x.xml");
XElement rt = doc.Element("root");
XElement elm = rt.Element(s2[i]);
if (elm != null)
{
elm.SetValue(s2[i + 1]);
}
else
{
XElement x = new XElement(s2[i], s2[i + 1]);
rt.Add(x);
}
doc.Save("x.xml");
i++;
}
hope this will solve your problem
Update
if you want to automate file creation without creating the xml file by hand then you can do this way
string s = "{{Name Mike} {age 19} {gender male}}";
string[] s2 = s.Replace("{", "").Replace("}", "").Split(' ');
if (!File.Exists("x.xml"))
{
TextWriter tw = new StreamWriter("x.xml", true);
tw.WriteLine("<root>\n</root>");
tw.Close();
}
for (int i = 0; i < s2.Length; i++)
{
XDocument doc = XDocument.Load("x.xml");
XElement rt = doc.Element("root");
XElement elm = rt.Element(s2[i]);
if (elm != null)
{
elm.SetValue(s2[i + 1]);
}
else
{
XElement x = new XElement(s2[i], s2[i + 1]);
rt.Add(x);
}
doc.Save("x.xml");
i++;
}

XmlWriter -write from reader (xml fragment)

Is it possible to copy all content(xml fragment) from one stream(using xmlReader) to second (xmlWriter).
I have some procedures which return xml fragments.
<item></item>
<item></item>
<item></item>
<item></item>
<item></item>
using (XmlWriter writer = XmlWriter.Create(stream, _settings))
{
writer.WriteStartElement(typeName);
writer.WriteAttributeString("RowVersion", rowVersion);
for (int i = 1; i <= packagesCount; i++)
{
cmd.Parameters["#packageNumber"].Value = i;
using (var r = cmd.ExecuteXmlReader())
{
//need copy all fragment from reader
}
writer.WriteEndElement();
}
}
There is method like writer.WriteNode(reader,true), but using this I need to iterate all elements. It's not effective when I have 10000 elements in one fragment. I need just copy all content. Moreover this fragment could be very big, that's why I prefer to use stream, than saving it in string
An old post but for someone may be useful.
I have to deal with XML files that are fairly big (>50MB). And I need to extract a segment from them and work with that segments separately. So I did this:
class Program
{
static void processXML(string xml)
{
SqlServerTypes.Utilities.LoadNativeAssemblies(AppDomain.CurrentDomain.BaseDirectory);
XmlReader reader = XmlReader.Create(xml);
XmlWriterSettings settings = new XmlWriterSettings
{
ConformanceLevel = ConformanceLevel.Auto
};
var output_file = "output.xml";
if (File.Exists(output_file))
{
File.Delete(output_file);
}
XmlWriter writer = XmlWriter.Create("output.xml", settings);
try
{
Console.WriteLine("Processing: " + xml);
Console.WriteLine("Outputting to: " + Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "output.xml"));
//extract all namespaces used in document
XPathDocument x = new XPathDocument(reader);
XPathNavigator foo = x.CreateNavigator();
foo.MoveToFollowing(XPathNodeType.Element);
IDictionary<string, string> Namespaces = foo.GetNamespacesInScope(XmlNamespaceScope.All);
reader = XmlReader.Create(xml);
var elementFullName_ = "";
var elementName_ = "";
var elementToFind = "sl:stand";
var elementsFound = 0;
var prefix_ = "";
var text_ = "";
var whiteSpace_ = "";
while (reader.Read())
{
switch (reader.NodeType)
{
case XmlNodeType.Element:
elementFullName_ = reader.Name;
if (elementFullName_ == elementToFind)
{
//avoid processing the file if XmlWriter just started
if (writer.WriteState != WriteState.Start)
{
writer.Flush();
writer.Close();
//here process the file for whatever you want
if (File.Exists(output_file))
{
File.Delete(output_file);
}
writer = XmlWriter.Create("output.xml", settings);
}
elementsFound = 1;
}
else if(elementsFound > 0)
{
elementsFound++;
}
var arr = reader.Name.Split(':');
if (arr.Length == 2)
{
prefix_ = arr[0];
elementName_ = arr[1];
if (elementsFound > 0)
writer.WriteStartElement(arr[0], arr[1], Namespaces[arr[0]]);
}
else
{
prefix_ = "";
elementName_ = reader.Name;
if (elementsFound > 0)
writer.WriteStartElement(reader.Name);
}
if (elementsFound > 0 && reader.HasAttributes)
writer.WriteAttributes(reader, true);
if (elementsFound > 0 && reader.IsEmptyElement)
writer.WriteEndElement();
break;
case XmlNodeType.EndElement:
if (elementsFound > 0)
{
writer.WriteEndElement();
}
if (elementsFound > 0)
{
elementsFound--;
}
if (elementsFound == 0)
{
}
break;
case XmlNodeType.Text:
if (elementFullName_ == "gml:posList")
{
text_ = reader.Value;
}
if (elementsFound > 0)
writer.WriteString(reader.Value);
break;
case XmlNodeType.Whitespace:
if (elementFullName_ == "gml:posList")
{
whiteSpace_ = reader.Value;
}
if (elementsFound > 0)
writer.WriteWhitespace(reader.Value);
break;
}
}
}
finally
{
reader.Close();
writer.Close();
}
}
static void Main(string[] args)
{
var xml = "";
if (args.Length == 0 || !File.Exists(args[0]))
{
Console.WriteLine("Please, provide a valid XML file as a commandline parameter");
return;
}
xml = args[0];
processXML(xml);
Console.WriteLine("Done!");
}
}
Note: some conditions are not important to you so you can remove them.

Reading specific text from XML files

I have created a small XML tool which gives me count of specific XML tags from multiple XML files.
The code for this is as follow:
public void SearchMultipleTags()
{
if (txtSearchTag.Text != "")
{
try
{
//string str = null;
//XmlNodeList nodelist;
string folderPath = textBox2.Text;
DirectoryInfo di = new DirectoryInfo(folderPath);
FileInfo[] rgFiles = di.GetFiles("*.xml");
foreach (FileInfo fi in rgFiles)
{
int i = 0;
XmlDocument xmldoc = new XmlDocument();
xmldoc.Load(fi.FullName);
//rtbox2.Text = fi.FullName.ToString();
foreach (XmlNode node in xmldoc.GetElementsByTagName(txtSearchTag.Text))
{
i = i + 1;
//
}
if (i > 0)
{
rtbox2.Text += DateTime.Now + "\n" + fi.FullName + " \nInstance: " + i.ToString() + "\n\n";
}
else
{
//MessageBox.Show("No Markup Found.");
}
//rtbox2.Text += fi.FullName + "instances: " + str.ToString();
}
}
catch (Exception)
{
MessageBox.Show("Invalid Path or Empty File name field.");
}
}
else
{
MessageBox.Show("Dont leave field blanks.");
}
}
This code returns me the tag counts in Multiple XML files which user wants.
Now the same I want to Search for particular text and its count present in XML files.
Can you suggest the code using XML classes.
Thanks and Regards,
Mayur Alaspure
Use LINQ2XML instead..It's simple and a complete replacement to othe XML API's
XElement doc = XElement.Load(fi.FullName);
//count of specific XML tags
int XmlTagCount=doc.Descendants().Elements(txtSearchTag.Text).Count();
//count particular text
int particularTextCount=doc.Descendants().Elements().Where(x=>x.Value=="text2search").Count();
System.Xml.XPath.
Xpath supports counting: count(//nodeName)
If you want to count nodes with specific text, try count(//*[text()='Hello'])
See How to get count number of SelectedNode with XPath in C#?
By the way, your function should probably look something more like this:
private int SearchMultipleTags(string searchTerm, string folderPath) { ...
//...
return i;
}
Try using XPath:
//var document = new XmlDocument();
int count = 0;
var nodes = document.SelectNodes(String.Format(#"//*[text()='{0}']", searchTxt));
if (nodes != null)
count = nodes.Count;

Categories