Extracting nested nodes from xml file c# - c#

I have this xml file:
<table head="Film">
<row>
<id>USD</id><jan>Jan</jan><feb>Feb</feb><mar>Mar</mar><apr>Apr</apr><maj>May</maj><jun>Jun</jun><jul>Jul</jul><aug>Aug</aug><sep>Sep</sep><okt>Oct</okt><nov>Nov</nov><dec>Dec</dec><sum>Year</sum>
</row>
<row>
<id>2018</id><jan>7629</jan><feb>6433</feb><mar>5573</mar><apr>3676</apr><maj>2545</maj><jun>2542</jun><jul>266</jul><aug>276</aug><sep>2690</sep><okt>371</okt><nov>5446</nov><dec>754</dec><sum>52731</sum>
</row>
I'm trying to extract the individual values for every month.
I've tried
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("model.xml");
XmlNodeList nodeList = xmlDoc.GetElementsByTagName("table");
foreach (XmlNode node in nodeList) // for each <testcase> node
{
Console.WriteLine(node["row"].InnerText);
}
This gives an exception because node["row"] is empty.
Any ideas?

Firstly your XML is not valid. You need to have a </table> on there.
//In this example GetXml() just returns your XML
var doc = XDocument.Parse(GetXml());
var rows = doc.Descendants("table").Elements("row").ToList();
foreach(var element in rows[1].Elements()){
Console.WriteLine(element?.Value);
}
Now this is just a basic example based of your XML. You would likely want it to be more robust. You will notice I am showing you this with LINQ, I feel it's more readable than XmlDocument.

You need to loop through the child nodes to get your desired result as follow:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("model.xml");
XmlNodeList nodeList = xmlDoc.GetElementsByTagName("table");
foreach (XmlNode node in nodeList) // for each <testcase> node
{
foreach (XmlNode row in node.ChildNodes)
{
foreach (XmlNode mon in row.ChildNodes)
{
}
}
}

Related

Load XML file into SQL Server tables using C#

I have complex XML file that export from old program in VB6, now I must write a program in C# to load this XML file into 2 tables. Here is the XML file structure:
<?xml version="1.0" encoding="SHIFT-JIS" standalone="yes"?>
<AdminFile>
<PO_No></PO_No>
<Database>
<PO>
<Table_PO_Master>
<DATA>
<PO_No></PO_No>
<PO_Date></PO_Date>
</DATA>
</Table_PO_Master>
<Table_PO_Details>
<DATA>
<PO_No></PO_No>
<GOODS_CD></GOODS_CD>
<QTY></QTY>
</DATA>
</Table_PO_Details>
</PO>
</Database>
</AdminFile>
I need to load this XML into 2 SQL Server tables that have the structure as below:
Table_PO_Master(Id,PO_No,PO_Date)
Table_PO_Details(PO_No,GOODS_CD,QTY)
I googled and found this code but do not know to to apply it in my case.
string myXMLfile = "D:\\MyXML.xml";
XmlTextReader textReader = new XmlTextReader(myXMLfile);
XmlDocument doc = new XmlDocument();
doc.Load(myXMLfile);
XmlNodeList List = doc.GetElementsByTagName("RWResponse");
foreach (XmlNode node in List)
{
XmlNode Element = (XmlNode)node;
foreach (XmlNode node1 in Element)
{
XmlNode Element1 = (XmlNode)node1;
foreach (XmlNode node2 in Element1)
{
XmlNode Element2 = (XmlNode)node2;
foreach (XmlNode node3 in Element2)
{
XmlNode Element3 = (XmlNode)node3;
if (Element3.Name.ToUpper() != "HEADER")
{
if (!Element3.OuterXml.ToString().Contains("ROW type=\"subtotal\""))
{
if (!Element3.OuterXml.ToString().Contains("ROW type=\"total\""))
{
DataRow dr = ret_XML_Data_in_DataTable.NewRow();
foreach (XmlNode node4 in Element3)
{
XmlElement Element4 = (XmlElement)node4;
}
}
}
}
}
}
}
}
}
If you want to save data by SP than you need not to load xml in your c# application,
Pass your xml as a store procedure parameter usingo ado.net,
After you can extract xml and insert the data
so your SP is like,
CREATE PROCEDURE [dbo].[InsertData]
#xml XML
AS
BEGIN
INSERT INTO Table_PO_Master
SELECT
PO_Master.value('(PO_No/text())[1]','VARCHAR(100)') AS PO_No, --TAG
PO_Master.value('(PO_Date/text())[1]','VARCHAR(100)') AS PO_Date --TAG
FROM
#xml.nodes('/AdminFile/Database/PO/Table_PO_Master/Data')AS TEMPTABLE(PO_Master)
INSERT INTO Table_PO_Details
SELECT
PO_Master.value('(PO_No/text())[1]','VARCHAR(100)') AS PO_No, --TAG
PO_Master.value('(GOODS_CD/text())[1]','VARCHAR(100)') AS GOODS_CD --TAG
PO_Master.value('(QTY/text())[1]','int') AS QTY --TAG
FROM
#xml.nodes('/AdminFile/Database/PO/Table_PO_Details/Data')AS TEMPTABLE(PO_Details)
End
You can also use XDocument:
var doc = XDocument.Parse(xml);
foreach (XElement xe in doc.Descendants("Table_PO_Master"))
{
var PO_No = xe.Element("DATA").Element("PO_No").Value;
var PO_Date = xe.Element("DATA").Element("PO_Date").Value;
SaveIntoMaster(PO_No, PO_Date);
}
and do the same for Table_PO_Details

how to get(read) data from xmldocument in windows phone, c#

I'm getting data from a web service in my phone application and get the response to xmldocument like below.
XmlDocument XmlDoc = new XmlDocument();
XmlDoc.LoadXml(newx2);
Ther result of XmlDoc is like below.now I want to get the values from this.
<root>
<itinerary>
<FareIndex>0</FareIndex>
<AdultBaseFare>4719</AdultBaseFare>
<AdultTax>566.1</AdultTax>
<ChildBaseFare>0</ChildBaseFare>
<ChildTax>0</ChildTax>
<InfantBaseFare>0</InfantBaseFare>
<InfantTax>0</InfantTax>
<Adult>1</Adult>
<Child>0</Child>
<Infant>0</Infant>
<TotalFare>5285.1</TotalFare>
<Airline>AI</Airline>
<AirlineName>Air India</AirlineName>
<FliCount>4</FliCount>
<Seats>9</Seats>
<MajorCabin>Y</MajorCabin>
<InfoVia>P</InfoVia>
<sectors xmlns:json="http://james.newtonking.com/projects/json">
</itinerary>
</root>
I tried with this.
XmlNodeList xnList = XmlDoc.SelectNodes("/root[#*]");
but it gives null result. the count is 0. how can I read the data from this.hope your help with this.thanx.
You can use System.Xml.Linq.XElement to parse an xml:
XElement xRoot = XElement.Parse(xmlText);
XElement xItinerary = xRoot.Elements().First();
// or xItinerary = xRoot.Element("itinerary");
foreach (XElement node in xItinerary.Elements())
{
// Read node here: node.Name, node.Value and node.Attributes()
}
If you want to use XmlDocument you can do like this:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xmlText);
XmlNode itinerary = xmlDoc.FirstChild;
foreach (XmlNode node in itinerary.ChildNodes)
{
string name = node.Name;
string value = node.Value;
// you can also read node.Attributes
}
You can get the value of a particular element like,
var fareIndex = XmlDoc.SelectSingleNode("/root/itinerary/FareIndex").InnerText;
If you want to get the list of all elements that come under root/itinerary -
XmlNodeList xnList = XmlDoc.SelectNodes("/root/itinerary/*");
This link might help you.

Select Nodes Using XPath

I'm trying to select nodes using xpath in c#
This is my XML file
<?xml version="1.0" encoding="utf-8"?>
<xObject version="3.0.2002.0" xmlns="http://schemas.microsoft.com/wix/2006/objects">
<section id="*" type="product">
<table name="NotThis">
<row sourceLineNumber="D:\bla\bla\">
<field>Borderish.fo</field>
<field>Documents</field>
<field>1</field>
<field>No, not this line here 1</field>
</row>
<row sourceLineNumber="D:\blah\blah\">
<field>Charterish</field>
<field>Documents</field>
<field>1</field>
<field>No not, this line here 2</field>
</row>
</table>
<table name="XFile">
<row sourceLineNumber="D:\bla\bla\">
<field>Borderish.fo</field>
<field>Documents</field>
<field>1</field>
<field>This line here 1</field>
</row>
<row sourceLineNumber="D:\blah\blah\">
<field>Charterish</field>
<field>Documents</field>
<field>1</field>
<field>This line here 2</field>
</row>
</table>
</section>
</xObject>
This is my C# code which seems to not work
XmlDocument doc = new XmlDocument();
doc.Load("Testing.xml");
XmlNode root = doc.DocumentElement;
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("ns", "xmlns="http://schemas.microsoft.com/wix/2006/objects"");
XmlNodeList nodeList = root.SelectNodes("ns:table[#type='XFile']/ns:row", nsmgr);
foreach (XmlNode xn in nodeList)
{
string fieldLine = xn["Field"].InnerText;
Console.WriteLine("Field: {4}", fieldLine);
}
What I want to output is every 4th field table name="xfile", like this:
This line here 1
This line here 2
Please let me know if you know a solution or a better way.
First - you should provide just uri for namespace:
nsmgr.AddNamespace("ns", "http://schemas.microsoft.com/wix/2006/objects");
Second - you should use namespace when providing node name. And table has attribute name instead of type:
XmlNodeList nodeList = root.SelectNodes("//ns:table[#name='XFile']/ns:row", nsmgr);
And last - after selecting row nodes, you should select fourth field node (which has full name ns:field):
foreach (XmlNode row in nodeList)
{
XmlNode field = row.SelectSingleNode("(ns:field)[4]", nsmgr);
Console.WriteLine("Field: {0}", field.InnerText);
}
Output:
Field: This line here 1
Field: This line here 2
NOTE: You can get fields directly, without looping on rows:
XmlNodeList fields =
root.SelectNodes("//ns:table[#name='XFile']/ns:row/ns:field[4]", nsmgr);

How to get the value for multiple subnode in xml?

Xml code:
<Report>
<ChartData>
<ListName>area</ListName>
<ViewName>Selecte List</ViewName>
<YAxisFields>
<YAxisField>
<Name>Scheduled Start Date/Time</Name>
<DataType>DateTime</DataType>
<Category>Year</Category>
</YAxisField>
</YAxisFields>
<XAxisFields>
<XAxisField>
<Name>Release Type</Name>
<DataType>String</DataType>
<Category>
</Category>
</XAxisField>
</XAxisFields>
</ChartConfig>
</Report>
I got the value for the subnode listname and viewname by using the
below code,
XmlDocument doc = new XmlDocument();
doc.Load("XmlFileName");
XmlNodeList node = doc.SelectNodes("Report/ChartData");
foreach (XmlNode xn in node)
{ xn["ListName"].InnerXml = chartname;
xn["ViewName"].InnerXml = SelectedList;
**xn["YAxisFields/YAxisField"].InnerXml = yaxisfield; //not working, need to get the value for this xml node,need help in this line dono how to proceed**
doc.Save("XmlFilename");
}
First i have tried with code like this instead of above code,in this
i need to create number of objects in order get the value for each
node so i tried by creating object for xmlnodelist then i used
foreach loop to get the value for each node but in this couldnt get
the value for YAxisFields/YAxisField because it also has parent node
as YAxisFields and subnode as YAxisField so there is only way to
create number of objects for xmlnode or is there any other way to do
this?
XmlDocument doc = new XmlDocument();
doc.Load("XmlFileName");
XmlNode Listnode = doc.SelectSingleNode("Report/ChartData/ListName");
XmlNode Viewnode = doc.SelectSingleNode("Report/ChartData/ViewName");
if (Listnode != null)
{
Listnode.InnerXml = chartname;
Viewnode.InnerXml = SelectedList; ;
doc.Save("XmlFileName");
Use Linq to XML XDocument, like this:
doc.Root.Descendants("ChartData").ToList().ForEach(node =>
{
node.Element("ListName").Value = chartname;
node.Element("ViewName").Value = SelectedList;
});

Read a XML (from a string) and get some fields - Problems reading XML

I have this XML (stored in a C# string called myXML)
<?xml version="1.0" encoding="utf-16"?>
<myDataz xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<listS>
<sog>
<field1>123</field1>
<field2>a</field2>
<field3>b</field3>
</sog>
<sog>
<field1>456</field1>
<field2>c</field2>
<field3>d</field3>
</sog>
</listS>
</myDataz>
and I'd like to browse all <sog> elements. For each of them, I'd like to print the child <field1>.
So this is my code :
XmlDocument xmlDoc = new XmlDocument();
string myXML = "<?xml version=\"1.0\" encoding=\"utf-16\"?><myDataz xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><listS><sog><field1>123</field1><field2>a</field2><field3>b</field3></sog><sog><field1>456</field1><field2>c</field2><field3>d</field3></sog></listS></myDataz>"
xmlDoc.Load(myXML);
XmlNodeList parentNode = xmlDoc.GetElementsByTagName("listS");
foreach (XmlNode childrenNode in parentNode)
{
HttpContext.Current.Response.Write(childrenNode.SelectSingleNode("//field1").Value);
}
but seems I can't read a string as XML? I get System.ArgumentException
You should use LoadXml method, not Load:
xmlDoc.LoadXml(myXML);
Load method is trying to load xml from a file and LoadXml from a string. You could also use XPath:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xml);
string xpath = "myDataz/listS/sog";
var nodes = xmlDoc.SelectNodes(xpath);
foreach (XmlNode childrenNode in nodes)
{
HttpContext.Current.Response.Write(childrenNode.SelectSingleNode("//field1").Value);
}
Use Linq-XML,
XDocument doc = XDocument.Load(file);
var result = from ele in doc.Descendants("sog")
select new
{
field1 = (string)ele.Element("field1")
};
foreach (var t in result)
{
HttpContext.Current.Response.Write(t.field1);
}
OR : Get the node list of <sog> tag.
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(myXML);
XmlNodeList parentNode = xmlDoc.GetElementsByTagName("sog");
foreach (XmlNode childrenNode in parentNode)
{
HttpContext.Current.Response.Write(childrenNode.SelectSingleNode("field1").InnerText);
}
The other answers are several years old (and do not work for Windows Phone 8.1) so I figured I'd drop in another option. I used this to parse an RSS response for a Windows Phone app:
XDocument xdoc = new XDocument();
xdoc = XDocument.Parse(xml_string);
Or use the XmlSerializer class.
XmlSerializer xs = new XmlSerializer(objectType);
obj = xs.Deserialize(new StringReader(yourXmlString));
I used the System.Xml.Linq.XElement for the purpose. Just check code below for reading the value of first child node of the xml(not the root node).
string textXml = "<xmlroot><firstchild>value of first child</firstchild>........</xmlroot>";
XElement xmlroot = XElement.Parse(textXml);
string firstNodeContent = ((System.Xml.Linq.XElement)(xmlroot.FirstNode)).Value;

Categories

Resources