XML generation using c# - c#

My goal is to generate xml structure in this format
<?xml version='1.0' encoding='UTF-8'?>
<return xmlns:rmas="value here" xmlns:xsi="value here" xsi:noNamespaceSchemaLocation="value here">
<header>
<return-code>""</return-code>
<return-desc>""</return-desc>
<as-at-date>""</as-at-date>
<operator-code>""</operator-code>
</header>
<body>
<scheme>
<code>10050</code>
<employer>
<empr-code></empr-code>
<data>
<serial-no />
<pin />
<employer-contribution />
<employee-contribution />
<voluntary-contribution />
<total-contribution />
</data>
</employer>
</scheme>
<scheme>
<code>10100</code>
<employer>
<empr-code></empr-code>
<data>
<serial-no />
<pin />
<employer-contribution />
<employee-contribution />
<voluntary-contribution />
<total-contribution />
</data>
</employer>
</scheme>
[...]
</body>
</return>
This is the sample of the data I am consuming
scheme-code emp-code pin empr-contr empyee-contr total total-vol-cont
10050 PR0000395010 PEN200386572133 54777.28 43821.82 108599.1 10000
10050 PR0000679771 PEN200629902715 65528.34 0 215528.34 150000
10050 PR0000007340 PEN200629902715 0 65528.34 215528.34 150000
10050 PU000035E001 PEN100786299723 10570.34 10570.34 21140.68 0
10050 TCF000615630 PEN100786299723 12060.15 12060.16 24120.31 0
10050 TCF000615630 PEN100786299723 12204.98 12204.99 24409.97 0
10050 PR0000615630 PEN100144364216 10945.19 13681.49 24626.68 0
10050 PR0000615630 PEN100453089112 14319.32 17899.15 32218.47 0
10050 PR0000615630 PEN200742682512 13116.33 16395.41 29511.74 0
10100 PRTEMP005022 PEN100940140007 792 990 1782 0
10100 PRTEMP005022 PEN100799131715 2375 2970 5345 0
10100 PRTEMP005022 PEN100799212715 831.6 1039.5 1871.1 0
In the body tag, I'd like to group the data first by the scheme-code and inside the code, group the data by the emp-code in that scheme and then by the data(pin, empr-contr,empyee-contr...) having the empr-code. The serial-no(int) for each data tag will be 0,1,2,3....T999 depending on the number of data tags in the parent employer tag. Please see further example below
<scheme>
<code>10050</code>
[...]
<employer>
<empr-code>PR0000615630</empr-code>
<data>
<serial-no>1</serial-no>
<pin>PEN100144364216</pin>
<employer-contribution>10945.19</employer-contribution>
<employee-contribution>13681.49</employee-contribution>
<voluntary-contribution>0.00</voluntary-contribution>
<total>32218.47</total>
</data>
<data>
<serial-no>2</serial-no>
<pin>PEN100453089112</pin>
<employer-contribution>14319.32</employer-contribution>
<employee-contribution>17899.15/employee-contribution>
<voluntary-contribution>0.00</voluntary-contribution>
<total>32218.47</total>
</data>
<data>
<serial-no>T9999</serial-no>
<pin>PEN200742682512</pin>
<employer-contribution>13116.33</employer-contribution>
<employee-contribution>16395.41</employee-contribution>
<voluntary-contribution>0.00</voluntary-contribution>
<total>29511.74</total>
</data>
</employer>
[...]
</scheme>
How can I generate it using XMLDocument or XMLWriter

Try following xml linq. I put your input file into a text file and then read into DataTable. Then create XML from table :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Data;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
const string INPUT_FILENAME = #"c:\temp\test.txt";
const string OUTPUT_FILENAME = #"c:\temp\test.xml";
static DataTable dt = new DataTable();
static XDocument doc;
static void Main(string[] args)
{
ReadData(INPUT_FILENAME);
dt = dt.AsEnumerable()
.OrderBy(x => x.Field<string>("scheme-code"))
.ThenBy(x => x.Field<string>("emp-code"))
.ThenBy(x => x.Field<string>("pin"))
.CopyToDataTable();
CreateXml();
doc.Save(OUTPUT_FILENAME);
}
static void ReadData(string filename)
{
int rowNumber = 0;
string line = "";
StreamReader reader = new StreamReader(INPUT_FILENAME);
while ((line = reader.ReadLine()) != null)
{
string[] splitData = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).ToArray();
if (++rowNumber == 1)
{
for (int i = 0; i < splitData.Length; i++)
{
if (i < 3)
{
dt.Columns.Add(splitData[i], typeof(string));
}
else
{
dt.Columns.Add(splitData[i], typeof(decimal));
}
}
}
else
{
DataRow newRow = dt.Rows.Add();
for (int i = 0; i < splitData.Length; i++)
{
if (i < 3)
{
newRow[i] = splitData[i];
}
else
{
newRow[i] = decimal.Parse(splitData[i]);
}
}
}
}
reader.Close();
}
static void CreateXml()
{
string xmlns_rmas = "value here";
string xmlns_xsi = "value here";
string xmlns_noNamespaceSchemaLocation = "value here";
string xmlIdentFormat =
"<?xml version='1.0' encoding='UTF-8'?>" +
"<return" +
" xmlns:rmas=\"{0}\"" +
" xmlns:xsi=\"{1}\"" +
" xsi:noNamespaceSchemaLocation=\"{2}\">" +
"</return>";
string xmlIdent = string.Format(xmlIdentFormat, xmlns_rmas, xmlns_xsi, xmlns_noNamespaceSchemaLocation);
doc = XDocument.Parse(xmlIdent);
XElement _return = doc.Root;
string returnCode = "";
string returnDesc = "";
DateTime date = DateTime.Now;
string operatorCode = "";
XElement header = new XElement("header", new object[] {
new XElement("return-code", returnCode),
new XElement("return-desc", returnDesc),
new XElement("as-at-date", date),
new XElement("operator-code", operatorCode)
});
_return.Add(header);
XElement body = new XElement("body");
_return.Add(body);
foreach(var schemeGroup in dt.AsEnumerable().GroupBy(x => x.Field<string>("scheme-code")))
{
XElement scheme = new XElement("scheme");
body.Add(scheme);
XElement code = new XElement("code", schemeGroup.Key);
scheme.Add(code);
foreach(var empCodeGroup in schemeGroup.GroupBy(y => y.Field<string>("emp-code")))
{
XElement employer = new XElement("employer");
scheme.Add(employer);
int serialNumber = 0;
foreach(var pinGroup in empCodeGroup.GroupBy(y => y.Field<string>("pin")))
{
if (serialNumber == 0)
{
XElement emprCode = new XElement("empr-code", empCodeGroup.Key);
employer.Add(emprCode);
}
foreach (DataRow row in pinGroup)
{
XElement data = new XElement("data");
employer.Add(data);
if ((empCodeGroup.Count() > 1) && (serialNumber == empCodeGroup.Count() - 1))
{
data.Add(new XElement("serial-no", "T999"));
}
else
{
data.Add(new XElement("serial-no", serialNumber));
}
data.Add(new XElement("pin", pinGroup.Key));
data.Add(new XElement("employer-contribution", row.Field<decimal>("empr-contr")));
data.Add(new XElement("employee-contribution", row.Field<decimal>("empyee-contr")));
data.Add(new XElement("voluntary-contribution", row.Field<decimal>("total-vol-cont")));
data.Add(new XElement("total-contribution", row.Field<decimal>("total")));
serialNumber++;
}
}
}
}
}
}
}

Load Data to the DataSet and use Write XML. This is the simplest way you can try
DataSet oDsData = new DataSet();
oDsData.WriteXml("path", XmlWriteMode.WriteSchema);

This could be one of the solution if your data is in MSSQL server. I assumed your data resides in a table (##tmp_test) in database.
public string GetXML()
{
XmlDocument document = new XmlDocument();
XmlDeclaration xmlDeclaration = document.CreateXmlDeclaration("1.0", "UTF-8", null);
XmlElement root = document.DocumentElement;
document.InsertBefore(xmlDeclaration, root);
var returnElement = document.CreateElement( "return");
returnElement.SetAttribute("xmlns:rmas", "value here");
returnElement.SetAttribute("xmlns:xsi", "value here");
returnElement.SetAttribute("noNamespaceSchemaLocation", "value here");
var header = document.CreateElement("header");
var rc = document.CreateElement("return-code");
rc.InnerText = "\"\"";
header.AppendChild(rc);
var rd = document.CreateElement("return-desc");
rd.InnerText = "\"\"";
header.AppendChild(rd);
var aad = document.CreateElement("as-at-date");
aad.InnerText = "\"\"";
header.AppendChild(aad);
var oc = document.CreateElement("operator-code");
oc.InnerText = "\"\"";
header.AppendChild(oc);
returnElement.AppendChild(header);
var body = document.CreateElement("body");
body.InnerXml = GetBodyXML();
returnElement.AppendChild(body);
document.AppendChild(returnElement);
return document.OuterXml;
}
private string GetBodyXML()
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
using (SqlCommand command = new SqlCommand())
{
command.Connection = connection;
command.CommandText = #"
SELECT 1 AS Tag
,NULL AS Parent
,[Scheme].[scheme-code] AS [scheme!1!code!ELEMENT]
,NULL AS [employer!2!empr-code!ELEMENT]
,NULL AS [data!3!serial-no!ELEMENT]
,NULL AS [data!3!pin!ELEMENT]
,NULL AS [data!3!employer-contribution!ELEMENT]
,NULL AS [data!3!employee-contribution!ELEMENT]
,NULL AS [data!3!voluntary-contribution!ELEMENT]
,NULL AS [data!3!total!ELEMENT]
FROM ##tmp_test [Scheme]
UNION
SELECT 2 AS Tag
,1 AS Parent
,[Scheme].[scheme-code] AS code
,[Scheme].[emp-code] AS [empr-code]
,NULL AS [serial-no]
,NULL AS pin
,NULL AS [employer-contribution]
,NULL AS [employee-contribution]
,NULL AS [voluntary-contribution]
,NULL AS [total]
FROM ##tmp_test [Scheme]
UNION
SELECT 3 AS Tag
,2 AS Parent
,[Scheme].[scheme-code] AS code
,[Scheme].[emp-code] AS [empr-code]
,ROW_NUMBER() OVER (
PARTITION BY [Scheme].[scheme-code]
,[Scheme].[emp-code] ORDER BY pin
) AS [serial-no]
,[Scheme].pin AS [pin]
,[Scheme].[empr-contr] AS [employer-contribution]
,[Scheme].[empyee-contr] AS [employee-contribution]
,[Scheme].[total-vol-cont] AS [voluntary-contribution]
,[Scheme].total AS [total]
FROM ##tmp_test [Scheme]
ORDER BY [scheme!1!code!ELEMENT]
,[employer!2!empr-code!ELEMENT]
FOR XML EXPLICIT
";
//Better approach to read all xml - https://stackoverflow.com/a/40775242/1010395
using (XmlReader xmlReader = command.ExecuteXmlReader())
{
XPathDocument xp = new XPathDocument(xmlReader);
XPathNavigator xn = xp.CreateNavigator();
return xn.OuterXml;
}
}
}
}

Related

save separate separate xml file base on orderid

Hi all currently i have saved all the xml file in one file . but i need to save in separate file. could you please help me on it.
current code :-
System.Data.DataTable checkFile = new System.Data.DataTable();
sql = "sql";
DBCon clsDB = new DBCon(SAPCompanySettings.MSSQLConnectionString);
clsDB.Execute(sql, ref checkFile);
var stringwriter = new StringWriter();
using (var xmlWriter = XmlWriter.Create(stringwriter, new XmlWriterSettings { Indent = true }))
{
xmlWriter.WriteStartDocument();
xmlWriter.WriteStartElement("Root");
var groups = checkFile.AsEnumerable().GroupBy(x => new { DocNum = x.Field<int>("orderid"), Type = x.Field<string>("Type"), Status = x.Field<string>("Status"), productno = x.Field<string>("productno"), ProductDescription = x.Field<string>("ProductDescription"), uom = x.Field<string>("uom"), customer = x.Field<string>("customer"), remark = x.Field<string>("remark"), U_JobNumber = x.Field<string>("U_JobNumber"), U_SalesPerson = x.Field<string>("U_SalesPerson"), U_JobType = x.Field<string>("U_JobType"), PlannedQty = x.Field<decimal>("PlannedQty"), OriginNum = x.Field<int?>("OriginNum"), orderdate = x.Field<DateTime>("orderdate"), duedate = x.Field<DateTime>("duedate") });
foreach (var group in groups)
{
xmlWriter.WriteStartElement("productionorder");
xmlWriter.WriteAttributeString("orderid", group.Key.DocNum.ToString());
xmlWriter.WriteElementString("type", group.Key.Type);
xmlWriter.WriteElementString("status", group.Key.Status);
xmlWriter.WriteElementString("productno", group.Key.productno); xmlWriter.WriteElementString("ProductDescription", group.Key.ProductDescription);
xmlWriter.WriteElementString("PlannedQty",group.Key.PlannedQty.ToString());
xmlWriter.WriteElementString("uom", group.Key.uom);
xmlWriter.WriteElementString("salesorder", group.Key.OriginNum.ToString()); xmlWriter.WriteElementString("customer", group.Key.customer);
xmlWriter.WriteElementString("Remarks", group.Key.remark);
xmlWriter.WriteStartElement("date");
xmlWriter.WriteElementString("orderdate", group.Key.orderdate.ToString());
xmlWriter.WriteElementString("duedate", group.Key.duedate.ToString());
xmlWriter.WriteEndElement();
xmlWriter.WriteElementString("jobdescription", group.Key.U_JobNumber);
xmlWriter.WriteElementString("salesperson", group.Key.U_SalesPerson);
xmlWriter.WriteElementString("jobtype", group.Key.U_JobType);
foreach (DataRow row in group)
{
xmlWriter.WriteStartElement("Components");
xmlWriter.WriteElementString("itemno", row.Field<string>("itemno"));
xmlWriter.WriteEndElement();
}
xmlWriter.WriteEndElement();
var sql2 = "update IS_XML_generated='Y' from OWOR where DocNum=group.Key.DocNum";
clsDB.Execute(sql2);
}
xmlWriter.WriteEndElement();
}
var xml = stringwriter.ToString();
XmlDocument docSave = new XmlDocument();
docSave.LoadXml(stringwriter.ToString());
docSave.Save(System.IO.Path.Combine(#"C:\DEMO PSL\DOXMLFILE", "Filename.xml"));
Current output:-
filename.xml:-both order is saved in same file
<?xml version="1.0" encoding="utf-16"?>
<Root>
<productionorder orderid="1">
...................
</productionorder>
<productionorder orderid="2">
...............
</productionorder>
</Root>
but expected output :-i need to save different different file
1.xml :-
<?xml version="1.0" encoding="utf-16"?>
<Root>
<productionorder orderid="1">
..............
</productionorder>
</Root>
2.xml :-
<?xml version="1.0" encoding="utf-16"?>
<Root>
<productionorder orderid="2">
............
</productionorder>
</Root>
I swapped the using and the foreach loops. I also modify filename so each filename is unique.
System.Data.DataTable checkFile = new System.Data.DataTable();
sql = "sql";
DBCon clsDB = new DBCon(SAPCompanySettings.MSSQLConnectionString);
clsDB.Execute(sql, ref checkFile);
var groups = checkFile.AsEnumerable().GroupBy(x => new { DocNum = x.Field<int>("orderid"), Type = x.Field<string>("Type"), Status = x.Field<string>("Status"), productno = x.Field<string>("productno"), ProductDescription = x.Field<string>("ProductDescription"), uom = x.Field<string>("uom"), customer = x.Field<string>("customer"), remark = x.Field<string>("remark"), U_JobNumber = x.Field<string>("U_JobNumber"), U_SalesPerson = x.Field<string>("U_SalesPerson"), U_JobType = x.Field<string>("U_JobType"), PlannedQty = x.Field<decimal>("PlannedQty"), OriginNum = x.Field<int?>("OriginNum"), orderdate = x.Field<DateTime>("orderdate"), duedate = x.Field<DateTime>("duedate") });
int count = 1;
foreach (var group in groups)
{
var stringwriter = new StringWriter();
using (var xmlWriter = XmlWriter.Create(stringwriter, new XmlWriterSettings { Indent = true }))
{
xmlWriter.WriteStartDocument();
xmlWriter.WriteStartElement("Root");
xmlWriter.WriteStartElement("productionorder");
xmlWriter.WriteAttributeString("orderid", group.Key.DocNum.ToString());
xmlWriter.WriteElementString("type", group.Key.Type);
xmlWriter.WriteElementString("status", group.Key.Status);
xmlWriter.WriteElementString("productno", group.Key.productno); xmlWriter.WriteElementString("ProductDescription", group.Key.ProductDescription);
xmlWriter.WriteElementString("PlannedQty",group.Key.PlannedQty.ToString());
xmlWriter.WriteElementString("uom", group.Key.uom);
xmlWriter.WriteElementString("salesorder", group.Key.OriginNum.ToString()); xmlWriter.WriteElementString("customer", group.Key.customer);
xmlWriter.WriteElementString("Remarks", group.Key.remark);
xmlWriter.WriteStartElement("date");
xmlWriter.WriteElementString("orderdate", group.Key.orderdate.ToString());
xmlWriter.WriteElementString("duedate", group.Key.duedate.ToString());
xmlWriter.WriteEndElement();
xmlWriter.WriteElementString("jobdescription", group.Key.U_JobNumber);
xmlWriter.WriteElementString("salesperson", group.Key.U_SalesPerson);
xmlWriter.WriteElementString("jobtype", group.Key.U_JobType);
foreach (DataRow row in group)
{
xmlWriter.WriteStartElement("Components");
xmlWriter.WriteElementString("itemno", row.Field<string>("itemno"));
xmlWriter.WriteEndElement();
}
xmlWriter.WriteEndElement();
var sql2 = "update IS_XML_generated='Y' from OWOR where DocNum=group.Key.DocNum";
clsDB.Execute(sql2);
xmlWriter.WriteEndElement();
}
var xml = stringwriter.ToString();
XmlDocument docSave = new XmlDocument();
docSave.LoadXml(stringwriter.ToString());
docSave.Save(System.IO.Path.Combine(#"C:\DEMO PSL\DOXMLFILE", "Filename" + count.ToString() + ".xml"));
count++;
}

How to get data with Column name in XML?

I have XML file like below
<?xml version="1.0" standalone="yes"?>
<ShippersDataSet xmlns="http://www.tempuri.org/ShippersDataSet.xsd">
<Shippers>
<ShipperID>1</ShipperID>
<CompanyName>Speedy Express</CompanyName>
<Phone>(503) 555-9831</Phone>
</Shippers>
<Shippers>
<ShipperID>2</ShipperID>
<CompanyName>United Package</CompanyName>
<Phone>(503) 555-3199</Phone>
</Shippers>
<Shippers>
<ShipperID>3</ShipperID>
<CompanyName>Federal Shipping</CompanyName>
<Phone>(503) 555-9931</Phone>
</Shippers>
</ShippersDataSet>
I have following input for XML data :
string XMLpath, string query
Query :
<Query>
<ElementPath> Shippers</ElementPath>
</Query>
I need to add
Like following , ( I have achieved in SQL) same way I need to add for XML data
var list = new List<Myclassdef>();
using (var con = new SqlConnection(Settings.Default.ConnectionString))
{
using (var cmd = new SqlCommand("SELECT ... WHERE Col1=#param1", con))
{
cmd.Parameters.AddWithValue("#param1", "value1");
// ...
con.Open();
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
Myclassdef data = new Myclassdef();
data.Data = new Dictionary<string, object>();
for (int i = 0; i < reader.FieldCount; i++)
{
data.Data.Add(reader.GetName(i), reader[i]);
}
list.Add(data);
}
}
}
}
I have following input for XML data :
string XMLpath, string query
Query :
<Query><ElementPath> Shippers</ElementPath></Query>
Try this:
class Program
{
static void Main(string[] args)
{
var list = new List<Myclassdef>();
var query = XDocument
.Parse("<Query><ElementPath> Shippers</ElementPath></Query>");
var doc = XDocument.Parse(File.ReadAllText("xml.xml"));
doc.Descendants(
XName.Get(
query.Root.Value.Trim(),
doc.Root.GetDefaultNamespace().NamespaceName))
.ToList()
.ForEach(e =>
{
var data = new Myclassdef();
data.Data = e
.Elements()
.Select(c => new
{
Name = c.Name.LocalName,
Value = (object)c.Value
})
.ToDictionary(c => c.Name, c => c.Value);
list.Add(data);
});
}
}
You can use Linq to XML for that (namespace System.Xml.Linq):
XDocument document = XDocument.Load(stream); // load the xml into an XDocument from a stream
// select the first of a specific element
IEnumerable<XElement> elements = from shippers in document.Descendants("Shippers") select shippers;
XElement element = (XElement)elements.First().FirstNode;
// loop through all the elements inside that element
foreach (XNode node in elements.First().Nodes())
{
// do something with elements
}

Get actual Column name from XML

I have a problem with this XML. In our system we are using XML from DataSet (ds.GetXml()) and send it to our Silverlight application as a string. From there we read the XML with the following:
StringReader stream = new StringReader(XmlData);
XmlReader reader = XmlReader.Create(stream);
XDocument myDoc = new XDocument();
myDoc = XDocument.Load(reader);
The problem: Some times column names are changed, example: If a column name starts with a numeric number then it will convert it.
"_x0033_column" original column name was "3column"
Is it possible to get the original column name from the XML?
The XML
<NewDataSet>
<Table>
<CheckboxCol>0</CheckboxCol>
<Kunde>1</Kunde>
<Ort_x0020_Postfach />
<erfasst_x0020_von>MasterMind</erfasst_x0020_von>
<Buchhaltungsnummer>1</Buchhaltungsnummer>
<Kreditlimit>0.0000</Kreditlimit>
<_x0033_STT_Inaktiv>Nein</_x0033_STT_Inaktiv>
<_x0033_STT_Status>Interessent</_x0033_STT_Status>
<Zahlungsbedingungen>10 : 10 Tage Netto</Zahlungsbedingungen>
</Table>
<Table>
<CheckboxCol>0</CheckboxCol>
<Kunde>3</Kunde>
<Ort_x0020_Postfach />
<erfasst_x0020_von>MasterMind</erfasst_x0020_von>
<Buchhaltungsnummer>3</Buchhaltungsnummer>
<Kreditlimit>0.0000</Kreditlimit>
<_x0033_STT_Inaktiv>Nein</_x0033_STT_Inaktiv>
<_x0033_STT_Status>Kunde</_x0033_STT_Status>
<Zahlungsbedingungen>10 : 10 Tage Netto</Zahlungsbedingungen>
</Table>
<NewDataSet>
My current Code
public SLDataTable(string XmlData, Dictionary<string, string> ColumnDict)
{
ColumnDefination = ColumnDict;
foreach (var Item in ColumnDefination)
{
Columns.Add(new SLDataColumn() { ColumnName = Item.Key.ToString().Trim(), DataType = GetNullableType(GetColumnType(Item.Value.ToString())) });
}
StringReader stream = new StringReader(XmlData);
XmlReader reader = XmlReader.Create(stream);
XDocument myDoc = new XDocument();
myDoc = XDocument.Parse(XmlData);
if (myDoc != null && myDoc.Elements().Count() > 0 && myDoc.Element("NewDataSet").Elements().Count() > 0)
{
int columnCount = myDoc.Element("NewDataSet").Element("Table").Elements().Count();
int rowCount = myDoc.Element("NewDataSet").Elements().Count();
string ElmentColumnName = string.Empty;
foreach (XElement element in myDoc.Element("NewDataSet").Elements())
{
var row = new SLDataRow(this);
foreach (XElement ele in element.Elements())
{
ElmentColumnName = ele.Name.ToString().Replace("_x0020_", " ").Replace("_x0028_", " (").Replace("_x0029_", ") ");
row[ElmentColumnName] = ConvertValue(ElmentColumnName, ele.Value);
}
Rows.Add(row);
}
}
}

Locate nodes in XML file

I have fixed my issue with reading the XML files. What I am needing now is to trim the datetime down to just MM dd yyyy hh:mm:ss and not bring the rest of it over when I insert into my Informix database.
This is the XML info:
<RecordFilingRequestMessage xmlns:nc="http://niem.gov/niem/niem-core/2.0">
<nc:DocumentIdentification>
<nc:IdentificationID>3212842</nc:IdentificationID>
</nc:DocumentIdentification>
<nc:DocumentPostDate>
<nc:DateTime>2013-06-25T11:32:08.5343733-04:00</nc:DateTime>
</nc:DocumentPostDate>
<nc:DocumentSubmitter>
<ecf:EntityPerson s:id="REVIEWER">
<nc:PersonName />
<nc:PersonOtherIdentification>
<nc:IdentificationID>41130</nc:IdentificationID>
<nc:IdentificationCategoryText>FLEPORTAL</nc:IdentificationCategoryText>
</nc:PersonOtherIdentification>
<nc:PersonOtherIdentification>
<nc:IdentificationID>kacolburn</nc:IdentificationID>
<nc:IdentificationCategoryText>FLEPORTAL_LOGONNAME</nc:IdentificationCategoryText>
</nc:PersonOtherIdentification>
...and here is my C# code:
string DocID = null;
int elementCount = 0;
string reqID = null;
string reqDateTime = null;
string empName = null;
string[] fileEntries = Directory.GetFiles(#"C:\XML\3212842.xml");
foreach (string fileName in fileEntries)
{
XmlReader xr = XmlReader.Create(fileName); //reads XML from folder
while (xr.Read())
{
if (xr.NodeType == XmlNodeType.Element && xr.Name == "nc:DateTime")
{
reqDateTime = xr.ReadElementContentAsString();
}
if (xr.NodeType == XmlNodeType.Element && xr.Name == "nc:IdentificationID")
{
elementCount++;
DocID = xr.ReadElementContentAsString();
if (elementCount == 1)
{
reqID = DocID;
}
if (elementCount == 3)
{
empName = DocID;
listBox1.Items.Add(reqID + " / " + reqDateTime + " / " + empName);
elementCount = 0;
break;
}
My first thought is, that the last '/' doesn't belong to the 'SelectNodes' call.
Alternatively, this code will solve your problem:
foreach(XmlNode node in xmlDoc.GetElementsByTagName("RecordFilingRequest")[0].GetElementsByTagName("nc:DocumentIdentification"))
{
int ID = Convert.ToInt32(node.FirstChild().InnerText);
}
Edit: This does assume, that 'RecordFilingRequest' always exists. Add a try .. catch statement, if that isn't the case.
Looks like the issue is that the XML uses namespaces, and your XPath does not. You didn't post your full XML, but you probably have something like xmlns:nc="http://some.url/ in there. Make sure to include a the namespace in a namespace manager, then add namespace prefixes to your query:
var nameTable = new NameTable();
var nsMgr = new XmlNamespaceManager(nameTable);
nsmgr.AddNamespace("nc", "http://some.url/");
var dataNodes = xmlDoc.SelectNodes("nc:RecordFilingRequest/nc:DocumentIdentification", nsMgr);
foreach (var node in dataNodes)
{
var ID = Convert.ToInt32(node.SelectSingleNode("nc:IdentificationID", nsMgr).InnerText);
// insert into database, e.g. using SqlCommand or whatever
}

I want to recursively list the nodes in xml

I recursively want to display xml nodes. But unfortunately it doesn't work. The output is only the first element of the xml file. Why?
public string GetOutline(int indentLevel, XmlNode xnod)
{
StringBuilder result = new StringBuilder();
XmlNode xnodWorking;
result = result.AppendLine(new string('-', indentLevel * 2) + xnod.Name);
if (xnod.NodeType == XmlNodeType.Element)
{
if (xnod.HasChildNodes)
{
xnodWorking = xnod.FirstChild;
while (xnodWorking != null)
{
GetOutline(indentLevel + 1, xnodWorking);
xnodWorking = xnodWorking.NextSibling;
}
}
}
return result.ToString();
}
Here the code calling the function. The XML file begins with <Videos> then <Video>... etc...
private void button2_Click(object sender, EventArgs e)
{
SaveFileDialog fDialog = new SaveFileDialog();
fDialog.Title = "Save XML File";
fDialog.FileName = "drzewo.xml";
fDialog.CheckFileExists = false;
fDialog.InitialDirectory = #"C:\Users\Piotrek\Desktop";
if (fDialog.ShowDialog() == DialogResult.OK)
{
using (var newXmlFile = File.Create(fDialog.FileName));
{
string xmlTree = fDialog.FileName.ToString();
XmlDocument xdoc = new XmlDocument();
xdoc.Load(XML);
XmlNode xnodDE = xdoc.DocumentElement;
textBox2.Text = GetOutline(0, xnodDE);
//StringBuilder result = new StringBuilder();
/*
foreach (var childelement in xdoc.DescendantNodes().OfType<XElement>()
.Select(x => x.Name).Distinct())
{
result.Append(childelement + Environment.NewLine );
}
textBox2.Text = result.ToString();
*/
using (StreamWriter sw = File.AppendText(xmlTree))
{
sw.Write(textBox2.Text);
}
}
}
XML content :
<Videos>
<Video>
<Title>The Distinguished Gentleman</Title>
<Director>Jonathan Lynn</Director>
<Actors>
<Actor>Eddie Murphy</Actor>
<Actor>Lane Smith</Actor>
<Actor>Sheryl Lee Ralph</Actor>
<Actor>Joe Don Baker</Actor>
</Actors>
<Length>112 Minutes</Length>
<Format>DVD</Format>
<Rating>R</Rating>
</Video>
<Video>
<Title>Her Alibi</Title>
<Director>Bruce Beresford</Director>
<Length>94 Mins</Length>
<Format>DVD</Format>
<Rating>PG-13</Rating>
</Video>
</Videos>
You need to read all document line by line whith a for each or a while instruction
XmlReader reader = XmlReader.Create(your xml file);
reader.MoveToContent();
while (reader.Read())
{
// your code
}
reader.Close();
not the best way, try to have a look also on linq to xml
try that
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace testStackOverflow
{
class Program
{
static void Main(string[] args)
{
//Load xml
XDocument xdoc = XDocument.Load("test.xml");
//Run query
var lv1s = from lv1 in xdoc.Descendants("Video")
select new
{
title = lv1.Element("Title").Value
};
//Loop through results
foreach (var lv1 in lv1s)
{
Console.WriteLine(lv1.title);
}
Console.ReadLine();
}
}
}
You're not doing anything to add the results of the recursive calls to the string you're building. You need to do this:
result.Append(GetOutline(indentLevel + 1, xnodWorking));
And this modification should avoid the text nodes and nodes with the same name:
public string GetOutline(int indentLevel, XmlNode xnod)
{
StringBuilder result = new StringBuilder();
XmlNode xnodWorking;
result = result.AppendLine(new string('-', indentLevel * 2) + xnod.Name);
if (xnod.HasChildNodes)
{
List<string> foundElements = new List<string>();
xnodWorking = xnod.FirstChild;
while (xnodWorking != null)
{
if(xnodworking.NodeType == XmlNodeType.Element && !foundElements.Contains(xnodworking.Name))
{
result.Append(GetOutline(indentLevel + 1, xnodWorking));
foundElements.Add(xnodworking.Name);
}
xnodWorking = xnodWorking.NextSibling;
}
}
return result.ToString();
}

Categories

Resources