Loop through specific Node of XML in C# - c#

I have researched a lot but I cannot find solution to my particular problem. I have to read an external xml file in C# and read the values in an Object. Here is the snapshot of my xml file:
<DatabaseList>
<DatabaseDetails>
<ConnectionId>1</ConnectionId>
<ConnectionName>MyConn1</ConnectionName>
<ServerConnection xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<CobConnection>
<CobConnection />
<ConnectionType>MSSQL</ConnectionType>
<Database />
<Server />
</CobConnection>
<ConnectionType>MSSQL</ConnectionType>
<Database>MyDB1</Database>
<Port>2431</Port>
<Server>MyServerName1</Server>
</ServerConnection>
</DatabaseDetails>
<DatabaseDetails>
<ConnectionId>2</ConnectionId>
<ConnectionName>MyConn2</ConnectionName>
<ServerConnection xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<CobConnection>
<CobConnection />
<ConnectionType>MSSQL</ConnectionType>
<Database />
<Server />
</CobConnection>
<ConnectionType>MSSQL</ConnectionType>
<Database>MyDB2</Database>
<Port>2431</Port>
<Server> MyServerName2</Server>
</ServerConnection>
</DatabaseDetails>
</DatabaseList>
For example, ConnectionName = MyConn2 is passed to the procedure below, code should read values for MyConn2. But in my case, I'm selecting the xmlNodesLvl2 correctly, but it starts from the beginning of the file. I need to read the value of node just found in previous step. For that particular Database.ConnectionName, I need to read the node values for eg, Database, ConnectionType, Server, etc. But I’m starting in next step from the beginning. I have put comment in my code //Problem here.
public static void GetInfo(string ConnectionName)
{
XmlDocument xmlDoc = new XmlDocument();
bool bfound = false;
xmlDoc.Load(#"C:\path..\Database.xml");
XmlNodeList xmlNodesLvl1 = xmlDoc.SelectNodes("DatabaseList/DatabaseDetails");
foreach (XmlNode xmlNode in xmlNodesLvl1)
{
if (xmlNode.HasChildNodes)
{
foreach (XmlNode item in xmlNode.ChildNodes)
{
string tagName = item.Name;
if (tagName == "ConnectionId")
{
Database.ConnectionId = item.InnerText;
}
if (tagName == "ConnectionName")
{
if (item.InnerText == ConnectionName)
{
Database.ConnectionName = item.InnerText;
bfound = true;
XmlNodeList xmlNodesLvl2 = null;
//Problem here
if (Enviroment == "COB")
{
xmlNodesLvl2 = xmlDoc.SelectNodes("DatabaseList/DatabaseDetails/ServerConnection/CobConnection");
}
else
{
xmlNodesLvl2 = xmlDoc.SelectNodes("DatabaseList/DatabaseDetails/ServerConnection");
}
foreach (XmlNode xmlNodeLvl2 in xmlNodesLvl2)
{
if (xmlNodeLvl2.HasChildNodes)
{
foreach (XmlNode itemLvl2 in xmlNodeLvl2.ChildNodes)
{
if (itemLvl2.Name == "CobConnection")
{
Database.CobConnection = itemLvl2.InnerText;
}
if (itemLvl2.Name == "Database")
{
Database.Name = itemLvl2.InnerText;
}
if (itemLvl2.Name == "ConnectionType")
{
Database.ConnectionType = itemLvl2.InnerText;
}
if (itemLvl2.Name == "Server")
{
Database.Server = itemLvl2.InnerText;
}
}
if (bfound == true)
{
break;
}
}
}
if (bfound == true)
{
break;
}
}
}
}
if (bfound == true)
{
break;
}
}
}
}
Please advise!

Try putting in DataTable
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
DataTable dt = new DataTable();
dt.Columns.Add("ConnectionId",typeof(string));
dt.Columns.Add("ConnectionName",typeof(string));
dt.Columns.Add("CobConnection",typeof(string));
dt.Columns.Add("CobConnectionType",typeof(string));
dt.Columns.Add("CobDatabase",typeof(string));
dt.Columns.Add("CobServer",typeof(string));
dt.Columns.Add("ConnectionType",typeof(string));
dt.Columns.Add("Database",typeof(string));
dt.Columns.Add("Port",typeof(string));
dt.Columns.Add("Server", typeof(string));
List<XElement> details = doc.Descendants("DatabaseDetails").ToList();
foreach (XElement detail in details)
{
string id = (string)detail.Element("ConnectionId");
string name = (string)detail.Element("ConnectionName");
XElement xCobConnection = detail.Descendants("CobConnection").FirstOrDefault();
string cobConnection = (string)xCobConnection.Element("CobConnection");
string cobType = (string)xCobConnection.Element("ConnectionType");
string cobDatabase = (string)xCobConnection.Element("Database");
string cobServer = (string)xCobConnection.Element("Server");
XElement serverConnection = detail.Element("ServerConnection");
string connectionType = (string)serverConnection.Element("ConnectionType");
string database = (string)serverConnection.Element("Database");
string port = (string)serverConnection.Element("Port");
string server = (string)serverConnection.Element("Server");
dt.Rows.Add(new object[] {
id,
name,
cobConnection,
cobType,
cobDatabase,
cobServer,
connectionType,
database,
port,
server
});
}
}
}
}

Related

Converting each and every attribute of xml into datatable column and filling its inner text as column value

I am trying to start with "event" tag,which is in the event list tag of my file,its root node is marina playlist.This file contains 1024 number of event tags,now I want to to make the attributes as datatable column and fill the column value with its inner text.
For ex-
event type will be a column and its value will be Comment,event enabled will be a datatable column and its value will be true.Now its child node properties is null so we will leave this,and iterate to the next child event which is again null,but its child comment have value so it will be converted into datatable,then schedule startType is also nt null it have attribute so schedule will become column and filled with value Sequential.
Now coming forward to next event tag,type,enabled,tiermarker,uid are already in datatable so we will iterate to the next child nodes and do the same thing,and if any new tag is found which has attribute like mediaStream som then it will become column,segment type,and then markup orderNo will become column,markup name will also become column and its value will be the innertext..
This is my file.I am trying for past 3 days but not getting solution.If done through recursion then it will be great help.
<marinaPlaylist version="3.1">
<properties>
</properties>
<eventList>
<event type="Comment" enabled="true" timerMarker="false" uid="4473">
<properties>
<event>
<comment>11/21/2016 10:21:48:22 - User 'Browse 2' Loaded List 'C:/Users/User/Desktop/الخميس 17 -11 -2016 - Copy.mpl'.</comment>
</event>
<schedule startType="Sequential"/>
</properties>
</event>
<event type="PrimaryVideo" enabled="true" timerMarker="false" uid="4480">
<properties>
<mediaStream som="00:00:00:20">
<segment type="Markup">
<markup orderNo="1" name="TxSegments"/>
</segment>
<video jobType="Play"/>
<allocation type="ListStream">
<listStream type="Fixed" listStreamNo="0"/>
</allocation>
</mediaStream>
<schedule endOffset="00:02:51:00" endType="Duration" startType="Sequential" startOffset="2017-05-03T06:00:00:00"/>
<media mediaType="Video" mediaName="RJ-000001"/>
<event title="السلام الملكي "/>
<switch rate="Fast" transition="Cut">
<source type="Auto">
<auto type="MediaStream"/>
</source>
<backupSource type="Auto">
<auto type="MediaStream"/>
</backupSource>
<destination type="Auto">
<auto type="PGM"/>
</destination>
<backupDestination type="Auto">
<auto type="PGM"/>
</backupDestination>
</switch>
</properties>
</event>
Try code below. It is just a start and not sure how to handle the element values and the attribute values. Let me know if I can modify code as needed
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Data;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
new Events(FILENAME);
}
}
public class Events
{
public static DataTable dt = new DataTable();
public static int idCount = 0;
public Events() { }
public Events(string filename)
{
XDocument doc = XDocument.Load(filename);
XElement eventList = doc.Descendants("eventList").FirstOrDefault();
string[] columnNames = eventList.Descendants().Select(x => (string)x.Name.LocalName).Distinct().OrderBy(x => x).ToArray();
dt.Columns.Add("ID", typeof(int));
dt.Columns.Add("Parent ID", typeof(int));
foreach (string columName in columnNames)
{
dt.Columns.Add(columName, typeof(string));
}
int rootId = idCount;
RecursiveParse(eventList, rootId);
}
public void RecursiveParse(XElement parent, int parentID)
{
foreach(XElement child in parent.Elements())
{
int childId = idCount++;
DataRow row = dt.Rows.Add();
row["Parent ID"] = parentID;
row["ID"] = childId;
string name = child.Name.LocalName;
string value = (string)child;
row[name] = value;
if (child.HasElements)
{
RecursiveParse(child, childId);
}
}
}
}
}
Thanks #jdweng for your quick reply and helping in solving the query.However I got the solution for the above query.
If you can modify the code to make it short then it will helpful because it is taking time in loading the form and populating the gridview.
public Form1()
{
InitializeComponent();
fillData();
}
public void fillColumns(XElement rootValue)
{
docu = XDocument.Load(FILENAME);
if (rootValue != null)
{
Queue<XElement> queue = new Queue<XElement>(rootValue.Elements());
while (queue.Count > 0)
{
XElement xelement = queue.Dequeue();
if (xelement.HasAttributes)
{
foreach (XAttribute attribute in xelement.Attributes())
{
string sColName = xelement.Name.ToString().Trim() + "" + attribute.Name.ToString().Trim();
if (!string.IsNullOrEmpty(sColName) && !dt.Columns.Contains(sColName))
{
DataColumn dtCol = new DataColumn();
dtCol.ColumnName = sColName;
dt.Columns.Add(dtCol);
}
}
}
if (!xelement.HasElements && xelement.Value != null)
{
string sColName = xelement.Name.ToString().Trim();
if (!string.IsNullOrEmpty(sColName) && !dt.Columns.Contains(sColName))
{
DataColumn dtCol = new DataColumn();
dtCol.ColumnName = sColName;
dt.Columns.Add(dtCol);
}
}
if (xelement.HasElements)
{
fillColumns(xelement);
}
}
}
}
public void fillRows(XElement rootValue, XElement actualValue)
{
try
{
if (rootValue != null)
{
Queue<XElement> queue = new Queue<XElement>(rootValue.Elements());
while (queue.Count > 0)
{
XElement xelement = queue.Dequeue();
if (xelement.Parent == actualValue)
{
if (dtRow != null)
dt.Rows.Add(dtRow);
dtRow = dt.NewRow();
}
if (xelement.HasAttributes)
{
foreach (XAttribute xattribute in xelement.Attributes())
{
string sColName = xelement.Name.ToString() + "" + xattribute.Name.ToString();
if (!string.IsNullOrEmpty(sColName) && dt.Columns.Contains(sColName))
{
dtRow[sColName] = xattribute.Value;
}
}
}
if (!xelement.HasElements && xelement.Value != null && !string.IsNullOrEmpty(xelement.Value))
{
string sColName = xelement.Name.ToString().Trim();
if (!string.IsNullOrEmpty(sColName) && dt.Columns.Contains(sColName))
{
dtRow[sColName] = xelement.Value;
}
}
if (xelement.HasElements)
{
fillRows(xelement, actualValue);
}
}
}
}
catch (Exception)
{
}
}
public void fillData()
{
docu = XDocument.Load(FILENAME);
XElement xElement = docu.XPathSelectElement("//eventList");
dt = new DataTable();
fillColumns(xElement);
fillRows(xElement, xElement);
dataGridView1.DataSource = dt;
}
}

How to get value from a specific child element in XML using XmlReader

Here is the XML
<?xml version="1.0" encoding="UTF-8"?>
<Data_Speed>
<Tech ID = "UMTS">
<Coverage ID="Dense_Urban">
<DownLoad_Speed>10</DownLoad_Speed>
<Upload_Speed>20</Upload_Speed>
</Coverage>
<Coverage ID="Urban">
<DownLoad_Speed>30</DownLoad_Speed>
<Upload_Speed>40</Upload_Speed>
</Coverage>
<Coverage ID="SubUrban">
<DownLoad_Speed>50</DownLoad_Speed>
<Upload_Speed>60</Upload_Speed>
</Coverage>
</Tech>
<Tech ID = "UMTS900">
<Coverage ID="Dense_Urban">
<DownLoad_Speed>11</DownLoad_Speed>
<Upload_Speed>12</Upload_Speed>
</Coverage>
<Coverage ID="Urban">
<DownLoad_Speed>13</DownLoad_Speed>
<Upload_Speed>14</Upload_Speed>
</Coverage>
<Coverage ID="SubUrban">
<DownLoad_Speed>15</DownLoad_Speed>
<Upload_Speed>16</Upload_Speed>
</Coverage>
</Tech>
<Tech ID = "4G800">
<Coverage ID="Dense_Urban">
<DownLoad_Speed>30</DownLoad_Speed>
<Upload_Speed>42</Upload_Speed>
</Coverage>
<Coverage ID="Urban">
<DownLoad_Speed>50</DownLoad_Speed>
<Upload_Speed>34</Upload_Speed>
</Coverage>
<Coverage ID="SubUrban">
<DownLoad_Speed>45</DownLoad_Speed>
<Upload_Speed>46</Upload_Speed>
</Coverage>
<Coverage ID="Rural">
<DownLoad_Speed>47</DownLoad_Speed>
<Upload_Speed>48</Upload_Speed>
</Coverage>
<Coverage ID="Variable">
<DownLoad_Speed>15</DownLoad_Speed>
<Upload_Speed>52</Upload_Speed>
</Coverage>
<Coverage ID="Outdoor">
<DownLoad_Speed>25</DownLoad_Speed>
<Upload_Speed>22</Upload_Speed>
</Coverage>
</Tech>
</Data_Speed>
So how could I get value of DownLoad_Speed> & UpLoad_Speed> element by given Coverage ID Urban> and Tech ID UMTS900>? Say, if I give tech id value = "UMTS900" and coverage id value "Urban", I'd like to have string value dwnload_speed = 13 and Upload_Speed = 14 as result.
Using Linq to Xml
XDocument doc = XDocument.Load(filepath);
//ex...
string technology = "UMTS900";
string coverage = "Dense_Urban";
var result = doc.Descendants("Tech")
.Where(x=> (string)x.Attribute("ID") == technology)
.Elements("Coverage")
.Where(x=>(string)x.Attribute("ID")== coverage)
.Select(x=> new
{
Dowload_Speed = (string)x.Element("DownLoad_Speed"),
Upload_Speed = (string)x.Element("Upload_Speed")
});
Check this Demo
You need to open XML document
XmlDocument _document = new XmlDocument();
byte[] bytes = File.ReadAllBytes(filePath);
string xml = Encoding.UTF8.GetString(bytes);
try
{
_document.LoadXml(xml);
}
catch (XmlException e)
{
//exception handling
}
var doc = (XmlDocument)_document.CloneNode(true);
XmlNode node = doc.GetElementsByTagName("your child node name");
Once you get your node then you can do necessary thing with it
string techId = "UMTS900";
string coverageId = "SUBURBAN";
int downloadSpeed = 0;
int uploadSpeed = 0;
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(#"C:\....\DataSpeed.xml");
XmlNodeList techTags = xmlDoc.GetElementsByTagName("Tech");
foreach (XmlNode techTag in techTags)
{
if (techTag.Attributes["ID"].Value.Equals(techId,StringComparison.OrdinalIgnoreCase))
{
XmlNodeList coverageTags = techTag.ChildNodes;
foreach (XmlNode coverageTag in coverageTags)
{
if (coverageTag.Attributes["ID"].Value.Equals(coverageId, StringComparison.OrdinalIgnoreCase))
{
downloadSpeed =Convert.ToInt16(coverageTag.ChildNodes[0].InnerText);
uploadSpeed = Convert.ToInt16(coverageTag.ChildNodes[1].InnerText);
break;
}
}
break;
}
}
if (downloadSpeed == 0 && uploadSpeed == 0)
{
Console.WriteLine("Specified Tech Id and Coverage Id not found");
}
else
{
Console.WriteLine("Download Speed is {0}. Upload Speed is {1}.",downloadSpeed,uploadSpeed);
}
Here is solution using XmlReader with xml linq
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication4
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XmlReader reader = XmlReader.Create(FILENAME);
string id = "UMTS900";
object coverages = null;
while (!reader.EOF)
{
if (reader.Name != "Tech")
{
reader.ReadToFollowing("Tech");
}
if (!reader.EOF)
{
XElement tech = (XElement)XElement.ReadFrom(reader);
if((string)tech.Attribute("ID") == id)
{
coverages = tech.Descendants("Coverage").Select(x => new
{
id = (string)x.Attribute("ID"),
downLoad_Speed = (int)x.Element("DownLoad_Speed"),
upLoad_Speed = (int)x.Element("Upload_Speed"),
}).ToList();
break;
}
}
}
}
}
}

Efficient Parsing of XML

Good day,
I'm writing a program in C# .Net to manage products of my store,
Following a given link I can retrieve an XML file that contains all the possible products that I can list onto my storefront.
The XML structure looks like this :
<Product StockCode="103-10440">
<lastUpdated><![CDATA[Fri, 20 May 2016 17:00:03 GMT]]></lastUpdated>
<StockCode><![CDATA[103-10440]]></StockCode>
<Brand><![CDATA[3COM]]></Brand>
<BrandID><![CDATA[14]]></BrandID>
<ProdName><![CDATA[BIG FLOW BLOWING JUNCTION FLEX BLOCK, TAKES 32, 40]]> </ProdName>
<ProdDesc/>
<Categories>
<TopCat><![CDATA[Accessories]]></TopCat>
<TopCatID><![CDATA[24]]></TopCatID>
</Categories>
<ProdImg/>
<ProdPriceExclVAT><![CDATA[30296.79]]></ProdPriceExclVAT>
<ProdQty><![CDATA[0]]></ProdQty>
<ProdExternalURL><![CDATA[http://pinnacle.eliance.co.za/#!/product/4862]]></ProdExternalURL>
</Product>
Here are the entries I'm looking for :
lastUpdated
StockCode
Brand
ProdName
ProdDesc
TopCat <--- nested in Categories tag.
ProdImg
ProdPriceExclVAT
ProdQty
ProdExternalURL
This is all fine to handle , and in-fact I did :
public ProductList Parse() {
XmlDocument doc = new XmlDocument();
doc.Load(XMLLink);
XmlNodeList ProductNodeList = doc.GetElementsByTagName("Product");
foreach (XmlNode node in ProductNodeList) {
Product Product = new Product();
for (int i = 0; i < node.ChildNodes.Count; i++) {
if (node.ChildNodes[i].Name == "StockCode") {
Product.VariantSKU = Convert.ToString(node.ChildNodes[i].InnerText);
}
if (node.ChildNodes[i].Name == "Brand") {
Product.Vendor = Convert.ToString(node.ChildNodes[i].InnerText);
}
if (node.ChildNodes[i].Name == "ProdName") {
Product.Title = Convert.ToString(node.ChildNodes[i].InnerText);
Product.SEOTitle = Product.Title;
Product.Handle = Product.Title;
}
if (node.ChildNodes[i].Name == "ProdDesc") {
Product.Body = Convert.ToString(node.ChildNodes[i].InnerText);
Product.SEODescription = Product.Body;
if (Product.Body == "") {
Product.Body = "ERROR";
Product.SEODescription = "ERROR";
}
}
if (node.ChildNodes[i].Name == "Categories") {
if (!tempList.Categories.Contains(node.ChildNodes[i].ChildNodes[0].InnerText)) {
if (!tempList.Categories.Contains("All")) {
tempList.Categories.Add("All");
}
tempList.Categories.Add(node.ChildNodes[i].ChildNodes[0].InnerText);
}
Product.Type = Convert.ToString(node.ChildNodes[i].ChildNodes[0].InnerText);
}
if (node.ChildNodes[i].Name == "ProdImg") {
Product.ImageSrc = Convert.ToString(node.ChildNodes[i].InnerText);
if (Product.ImageSrc == "") {
Product.ImageSrc = "ERROR";
}
Product.ImageAlt = Product.Title;
}
if (node.ChildNodes[i].Name == "ProdPriceExclVAT") {
float baseprice = float.Parse(node.ChildNodes[i].InnerText);
double Costprice = ((baseprice * 0.14) + (baseprice * 0.15) + baseprice);
Product.VariantPrice = Costprice.ToString("0.##");
}
}
Product.Supplier = "Pinnacle";
if (!tempList.Suppliers.Contains(Product.Supplier)) {
tempList.Suppliers.Add(Product.Supplier);
}
tempList.Products.Add(Product);
}
return tempList;
}
}
The problem is however, that this way of doing it, takes about 10 seconds to finish, and this is only just the first of multiple such files that I have to parse.
I am looking for the most efficient way to parse this XML file, getting all the fields's data that I mentioned above.
EDIT :
I benchmarked the code when running with a pre-downloaded copy of the file, and when downloading the file from the server at runtime :
With local copy : 5 Seconds.
Without local copy : 7.30 Seconds.
With large XML files you have to use an XmlReader. The code below will read one Product at a time.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
XmlReader reader = XmlReader.Create("filename");
while(!reader.EOF)
{
if (reader.Name != "Product")
{
reader.ReadToFollowing("Product");
}
if (!reader.EOF)
{
XElement product = (XElement)XElement.ReadFrom(reader);
string lastUpdated = (string)product.Element("lastUpdated");
}
}
}
}
}

How to get all child nodes of an XML in C#

I've an XML document like this:
<Columns>
<Column>
<Name>A</Name>
<Width>100</Width>
</Column>
</Columns>
<Columns>
</Columns>
<Columns>
<Column>
<Name>C</Name>
<Width>300</Width>
</Column>
<Column>
<Name>C1</Name>
<Width>310</Width>
</Column>
</Columns>
I'm getting their Name and Width text and store them a List.
var man = new XmlNamespaceManager(xdoc.NameTable);
man.AddNamespace("ns", "http://schemas.microsoft.com/project");
List <string> lstText = new List<string>();
List <List<string>> lst = new List<List<string>>();
XmlNodeList xnList = xdoc.SelectNodes("/ns:Columns/ns:Column", man);
foreach (XmlNode xn in xnList)
{
lstText.Add(xn["Name"].InnerText));
lstText.Add(xn["Width"].InnerText));
}
lst.Add(lstText);
So, I can only get these values: A and 100, C and 300.
I want to get C1 and 310 too. How can I get them?
Edit: Some of Columns has no Column, some of Columns has 1 or more Colums. In this sample, my List has 3 elements:
lst[0][0] = {A, 100}
lst[1][0] = null
lst[2][0] = {C, 300}, lst[2][1] = {C1, 310}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;
public class MainClass
{
public static void Main()
{
XmlDocument mDocument = new XmlDocument();
XmlNode mCurrentNode;
mDocument.Load("XPathQuery.xml");
mCurrentNode = mDocument.DocumentElement;
XmlNodeList nodeList = mCurrentNode.SelectNodes("*");
DisplayList(nodeList);
}
static void DisplayList(XmlNodeList nodeList)
{
foreach (XmlNode node in nodeList)
{
RecurseXmlDocumentNoSiblings(node);
}
}
static void RecurseXmlDocumentNoSiblings(XmlNode root)
{
if (root is XmlElement)
{
Console.WriteLine(root.Name);
if (root.HasChildNodes)
RecurseXmlDocument(root.FirstChild);
}
else if (root is XmlText)
{
string text = ((XmlText)root).Value;
Console.WriteLine(text);
}
else if (root is XmlComment)
{
string text = root.Value;
Console.WriteLine(text);
if (root.HasChildNodes)
RecurseXmlDocument(root.FirstChild);
}
}
static void RecurseXmlDocument(XmlNode root)
{
if (root is XmlElement)
{
Console.WriteLine(root.Name);
if (root.HasChildNodes)
RecurseXmlDocument(root.FirstChild);
if (root.NextSibling != null)
RecurseXmlDocument(root.NextSibling);
}
else if (root is XmlText)
{
string text = ((XmlText)root).Value;
Console.WriteLine(text);
}
else if (root is XmlComment)
{
string text = root.Value;
Console.WriteLine(text);
if (root.HasChildNodes)
RecurseXmlDocument(root.FirstChild);
if (vroot.NextSibling != null)
RecurseXmlDocument(root.NextSibling);
}
}
}
public readonly Dictionary<string, int> XmlValues = new Dictionary<string, int>();
public void Analyze(XmlDocument xml)
{
RecurseXmlDocument(xml.LastChild);
}
void RecurseXmlDocument(XmlNode root)
{
switch (root.NodeType)
{
case XmlNodeType.Element:
if (root.HasChildNodes)
RecurseXmlDocument(root.FirstChild);
if (root.NextSibling != null)
RecurseXmlDocument(root.NextSibling);
break;
case XmlNodeType.Text:
DictionayHelper.AddValue(XmlValues, root.Value);
break;
}
}
Use System.Xml.Linq:
const string name = "Name";
var xml = XDocument.Load(#"P:\athToYour\columns.xml");
var columns = xml.Descendants(name).Select(x => new
{
Name = x.Value,
Width = x.ElementsAfterSelf("Width").FirstOrDefault().Value
})
.ToDictionary(x=> x.Name, x=> x.Width);
columns.Dump();
You can do it this way; If you need you can reduce it down to 2 lines.
var xDoc = XDocument.Load(#"c:\XPathQuery.xml");
//this query gets Names and widths
var widths = xDoc.Descendants().Where(x => x.Name.LocalName.Equals("Name")).Select(x => new { Name = x.Value, Width = x.ElementsAfterSelf().First().Value }).ToList();
//if you want to loop through the collection, you can do like this.
foreach (var width in widths)
{
var name = width.Name;
var value = width.Width;
}

Convert xmlstring into XmlNode

i have one xml string like this
string stxml="<Status>Success</Status>";
I also creaated one xml document
XmlDocument doc = new XmlDocument();
XmlNode docNode = doc.CreateXmlDeclaration("1.0", "UTF-8", null);
doc.AppendChild(docNode);
XmlNode rootNode = doc.CreateElement("StatusList");
doc.AppendChild(rootNode);
i need an output like this.
<StatusList>
<Status>Success</Status>
</StatusList>
How can i achieve this.if we using innerhtml,it will insert.But i want to insert xml string as a xmlnode itself
A very simple way to achieve what you are after is to use the often overlooked XmlDocumentFragment class:
XmlDocument doc = new XmlDocument();
XmlNode docNode = doc.CreateXmlDeclaration("1.0", "UTF-8", null);
doc.AppendChild(docNode);
XmlNode rootNode = doc.CreateElement("StatusList");
doc.AppendChild(rootNode);
//Create a document fragment and load the xml into it
XmlDocumentFragment fragment = doc.CreateDocumentFragment();
fragment.InnerXml = stxml;
rootNode.AppendChild(fragment);
Using Linq to XML:
string stxml = "<Status>Success</Status>";
XDocument doc = new XDocument(new XDeclaration("1.0", "utf-8", "yes"),
new XElement("StatusList", XElement.Parse(stxml)));
You could instead use the XElement class:
string stxml = "<Status>Success</Status>";
var status = XElement.Parse(stxml);
var statusList = new XElement("StatusList", status);
var output = statusList.ToString(); // looks as you'd like
If you want to write the new statusList content to a file:
statusList.Save(#"C:\yourFile.xml", SaveOptions.None);
you ca try it using xmlwriter
using (XmlWriter writer = XmlWriter.Create("new.xml"))
{
writer.WriteStartDocument();
writer.WriteStartElement("StatusList");
writer.WriteElementString("Status", "Success"); // <-- These are new
writer.WriteEndDocument();
}
using System;
using System.Collections.Generic;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
using System.Reflection;
using System.ComponentModel;
public class MyClass
{
public static void RunSnippet()
{
XmlNode node = default(XmlNode);
if(node == null)
Console.WriteLine(bool.TrueString);
if(node != null)
Console.WriteLine(bool.FalseString);
XmlDocument doc = new XmlDocument();
node = doc.CreateNode (XmlNodeType.Element,"Query", string.Empty);
node.InnerXml=#"<Where><Eq><FieldRef Name=""{0}"" /><Value Type=""{1}"">{2}</Value></Eq></Where>";
string xmlData = ToXml<XmlNode>(node);
Console.WriteLine(xmlData);
XmlNode node1 = ConvertFromString(typeof(XmlNode), #"<Query><Where><Eq><FieldRef Name=""{0}"" /><Value Type=""{1}"">{2}</Value></Eq></Where></Query>") as XmlNode;
if(node1 == null)
Console.WriteLine(bool.FalseString);
if(node1 != null)
Console.WriteLine(bool.TrueString);
string xmlData1 = ToXml<XmlNode>(node1);
Console.WriteLine(xmlData1);
}
public static string ToXml<T>(T t)
{
string Ret = string.Empty;
XmlSerializer s = new XmlSerializer(typeof(T));
using (StringWriter Output = new StringWriter(new System.Text.StringBuilder()))
{
s.Serialize(Output, t);
Ret = Output.ToString();
}
return Ret;
}
public static object ConvertFromString(Type t, string sourceValue)
{
object convertedVal = null;
Type parameterType = t;
if (parameterType == null) parameterType = typeof(string);
try
{
// Type t = Type.GetType(sourceType, true);
TypeConverter converter = TypeDescriptor.GetConverter(parameterType);
if (converter != null && converter.CanConvertFrom(typeof(string)))
{
convertedVal = converter.ConvertFromString(sourceValue);
}
else
{
convertedVal = FromXml(sourceValue, parameterType);
}
}
catch { }
return convertedVal;
}
public static object FromXml(string Xml, Type t)
{
object obj;
XmlSerializer ser = new XmlSerializer(t);
using (StringReader stringReader = new StringReader(Xml))
{
using (System.Xml.XmlTextReader xmlReader = new System.Xml.XmlTextReader(stringReader))
{
obj = ser.Deserialize(xmlReader);
}
}
return obj;
}
#region Helper methods
public static void Main()
{
try
{
RunSnippet();
}
catch (Exception e)
{
string error = string.Format("---\nThe following error occurred while executing the snippet:\n{0}\n---", e.ToString());
Console.WriteLine(error);
}
finally
{
Console.Write("Press any key to continue...");
Console.ReadKey();
}
}
private static void WL(object text, params object[] args)
{
Console.WriteLine(text.ToString(), args);
}
private static void RL()
{
Console.ReadLine();
}
private static void Break()
{
System.Diagnostics.Debugger.Break();
}
#endregion
}
From my experience it is always better to work with unique id's i suggest u look in that situation first and then come back to this page, and research/position my code for a try if u did not yet have a solution for it.
I just finished it on my side for my own project, i have modified abit to look more integrated for your project.
Good luck. Sorry for the late response ;-)
XmlDocument xDoc = new XmlDocument();
string Bingo = "Identification code";
xDoc.Load(pathFile);
XmlNodeList idList = xDoc.GetElementsByTagName("id");
XmlNodeList statusList = xDoc.GetElementsByTagName("Status");
for (int i = 0; i < idList.Count; i++)
{
StatusNode = "<Status>fail</Status>";
XmlDocumentFragment fragment = xDoc.CreateDocumentFragment();
fragment.InnerXml = StatusNode;
statusList[i].InnerXml = "";
statusList[i].AppendChild(fragment);
if (statusList[i].InnerText == Bingo)
{
StatusNode = "<Status>Succes!</Status>";
fragment.InnerXml = Status;
statusList[i].InnerXml = "";
statusList[i].AppendChild(fragment);
}
}
xDoc.Save(pathFile);

Categories