XML read text inside two elements - c#

Here is my xml code:
<?xml version="1.0" encoding="utf-8"?>
<updater>
<version>1.0.7</version>
<Enabled>true</Enabled>
<item>
<url>some url</url>
<name>file name</name>
</item>
<item>
<url>other url</url>
<name>other file name</name>
</item>
</updater>
how can i get the value of url and name inside of both item elements? The full code have 9 elements with the name item. Please make the solution fit with this code:
XmlTextReader reader = null;
try
{
string xmlURL = "someurl";
reader = new XmlTextReader(xmlURL);
reader.MoveToContent();
string elementName = "";
if ((reader.NodeType == XmlNodeType.Element) && (reader.Name == "updater"))
{
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element) elementName = reader.Name;
else
{
if ((reader.NodeType == XmlNodeType.Text) && (reader.HasValue))
{
switch (elementName)
{
case "url":
if (nummer >= urls.Length)
Array.Resize(ref urls, urls.Length + 1);
urls[nummer] = reader.Value.ToString();
MessageBox.Show(urls[nummer]);
break;
case "name":
if (nummer >= names.Length)
Array.Resize(ref names, names.Length + 1);
names[nummer] = reader.Value.ToString();
MessageBox.Show(names[nummer]);
break;
}
nummer++;
}
}
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
Any help will be appreciated. thanks in advance.
PS. If i'm unclear somewhere, or if you need more information then just explain what's needed.

You can use LINQ to XML:
var xdoc = XDocument.Load(path_to_xml);
var items = from i in xdoc.Root.Elements("item")
select new {
Url = (string)i.Element("url"),
Name = (string)i.Element("name")
};
This will give list of anonymous objects corresponding to your item elements. Each object will have strongly-typed properties for url and name:
foreach(var item in items)
{
// use item.Url or item.Name
}

XDocument doc = XDocument.Load("Xml.xml");
IEnumerable<XElement> items = doc.Descendants("updater").Elements("item")
.Select(x => new { Url = x.Element("url").Value,
Name = x.Element("name").Value });

Related

Convert a XML to CSV using C#

How to convert a XML file to a CSV file in C#, showing only these Tags: <original-impot-no>, <price>, <Small-price>, <Big-price>?
sample XML code: it represents one line among several lines, and every line may contains several <product-lineitem>Tags
<?xml version="1.0" encoding="UTF-8"?>
<impots xmlns="http://www.google.com/xml/impot//20016-02-31">
<impot impot-no="W0110891258">
<impot-date>2017-12-10T22:33:35.000Z</impot-date>
<prop-by>Yallo</prop-by>
<original-impot-no>891258</original-impot-no>
<currency>EUR</currency>
<server-locale>Esp</server-locale>
<lax>gross</lax>
<current-impot-no>123358</current-impot-no>
<product-lineitems>
<product-lineitem>
<price>450</price>
<red>6.50</red>
<Small-price>39</Small-price>
<Big-price>3229</Big-price>
<lineitem-text>Grand create</lineitem-text>
<basis>234.00</basis>
</product-lineitem>
</product-lineitems>
<product-lineitem>
<price>432</price>
<red>12</red>
<Small-price>44</Small-price>
<Big-price>34</Big-price>
<lineitem-text>Small create</lineitem-text>
<basis>44.00</basis>
</product-lineitem>
</product-lineitems>
</impot>
</impots>
I should get someting like this in y CSV file:
891258;450;39;229
891258;432;44;34
the C# code:
the problem that Im facing with this code is that I can not retrieve the descandent of the TAG <impot>
XmlTextReader xtr = new XmlTextReader(#"C:\Temp_Convert\Impot.xml");
StringBuilder dataToBeWritten = new StringBuilder();
while (xtr.Read())
{
if (xtr.NodeType == XmlNodeType.Element && xtr.Name == "original-impot-no")
{
string s1 = xtr.ReadElementString();
dataToBeWritten.Append(s1);
dataToBeWritten.Append(";");
}
else if (xtr.NodeType == XmlNodeType.Element && xtr.Name == "price")
{
string s2 = xtr.ReadElementString();
dataToBeWritten.Append(s2);
dataToBeWritten.Append(";");
}
else if (xtr.NodeType == XmlNodeType.Element && xtr.Name == "Small-price")
{
string s2 = xtr.ReadElementString();
dataToBeWritten.Append(s2);
dataToBeWritten.Append(";");
dataToBeWritten.Append(0);
dataToBeWritten.Append(Environment.NewLine);
}
else if (xtr.NodeType == XmlNodeType.Element && xtr.Name == "Big-price")
{
string s2 = xtr.ReadElementString();
dataToBeWritten.Append(s2);
dataToBeWritten.Append(";");
dataToBeWritten.Append(0);
dataToBeWritten.Append(Environment.NewLine);
}
}
File.WriteAllText(#"C:\Temp_Convert\Impot.csv", dataToBeWritten.ToString());
}
Can somebody please propose a solution, thank you so much in advance.
You have an invalid XML. I guess here is the correct format.
<?xml version="1.0" encoding="UTF-8"?>
<impots xmlns="http://www.google.com/xml/impot//20016-02-31">
<impot impot-no="W0110891258">
<impot-date>2017-12-10T22:33:35.000Z</impot-date>
<prop-by>Yallo</prop-by>
<original-impot-no>891258</original-impot-no>
<currency>EUR</currency>
<server-locale>Esp</server-locale>
<lax>gross</lax>
<current-impot-no>123358</current-impot-no>
<product-lineitems>
<product-lineitem>
<price>450</price>
<red>6.50</red>
<Small-price>39.00</Small-price>
<Big-price>3229.00</Big-price>
<lineitem-text>Grand create</lineitem-text>
<basis>234.00</basis>
</product-lineitem>
</product-lineitems>
<product-lineitems>
<product-lineitem>
<price>432</price>
<red>12</red>
<Small-price>44.00</Small-price>
<Big-price>34.00</Big-price>
<lineitem-text>Small create</lineitem-text>
<basis>44.00</basis>
</product-lineitem>
</product-lineitems>
</impot>
</impots>
You couldn't retrieve the descendant because you are not including the namespace http://www.google.com/xml/impot//20016-02-31.
Here is how the code should be.
XNamespace ns = "http://www.google.com/xml/impot//20016-02-31";
var results = xDocument.Descendants(ns + "impot");
Then, you need to modify your query to retrieve elements that you need.
Here is the sample. I assume that product-lineitems only has one child product-lineitem.
var results = xDocument.Descendants(ns + "impot").Select(x => new {
ImpotNo = x.Attribute("impot-no")?.Value,
ProductLineItems = x.Descendants(ns + "product-lineitems").Select(y => new
{
Item = y.Descendants(ns + "product-lineitem").Select(z => new
{
Price = z.Element(ns + "price")?.Value,
SmallPrice = z.Element(ns + "Small-price")?.Value,
BigPrice = z.Element(ns + "Big-price")?.Value,
}).FirstOrDefault()
})
});
foreach (var result in results)
{
foreach (var productLine in result.ProductLineItems)
{
dataToBeWritten.Append(result.ImpotNo);
dataToBeWritten.Append(";");
dataToBeWritten.Append(productLine.Item.Price);
dataToBeWritten.Append(";");
dataToBeWritten.Append(productLine.Item.SmallPrice);
dataToBeWritten.Append(";");
dataToBeWritten.Append(productLine.Item.BigPrice);
dataToBeWritten.Append(";");
dataToBeWritten.Append(0);
dataToBeWritten.Append(Environment.NewLine);
}
}
Well, first I tried to reformat your XML to be a bit more readable but the tag structure still seems wrong...
<impots
xmlns="http://www.google.com/xml/impot//20016-02-31">
<impot impot-no="W0110891258">
<impot-date>2017-12-10T22:33:35.000Z</impot-date>
<prop-by>Yallo</prop-by>
<original-impot-no>891258</original-impot-no>
<currency>EUR</currency>
<server-locale>Esp</server-locale>
<lax>gross</lax>
<current-impot-no>123358</current-impot-no>
<product-lineitems>
<product-lineitem>
<price>450</price>
<red>6.50</red>
<Small-price>39.00</Small-price>
<Big-price>3229.00</Big-price>
<lineitem-text>Grand create</lineitem-text>
<basis>234.00</basis>
-
</product-lineitems>
-
</product-lineitem>
<product-lineitems>
<product-lineitem>
<price>432</price>
<red>12</red>
<Small-price>44.00</Small-price>
<Big-price>34.00</Big-price>
<lineitem-text>Small create</lineitem-text>
<basis>44.00</basis>
</product-lineitems>
</product-lineitem>
Nonetheless, I'm guessing this line is incorrect since "impot-no" is an attribute...
impot-no = (string)x.Element("impot impot-no")
Perhaps you meant that line to be...
impot-no = (string)x.Attribute("impot-no").Value
Going by memory -- hopefully that is the correct way to retrieve an attribute.
Review the following code. Note the use of SelectMany to get the impot items to construct the desired object models.
XNamespace ns = "http://www.google.com/xml/impot//20016-02-31";
var results = xDocument.Descendants(ns + "impot")
.SelectMany(impot => impot.Descendants(impot.Name.Namespace + "product-lineitem")
.Select(item => new {
ImpotNo = (string)impot.Element(impot.Name.Namespace + "original-impot-no"),
Price = (string)item.Element(item.Name.Namespace + "price"),
SmallPrice = (string)item.Element(item.Name.Namespace + "Small-price"),
BigPrice = (string)item.Element(item.Name.Namespace + "Big-price"),
})
).ToList();
for (int i = 0; i < results.Count; i++) {
dataToBeWritten.Append(results[i].ImpotNo);
dataToBeWritten.Append(";");
dataToBeWritten.Append(results[i].Price);
dataToBeWritten.Append(";");
dataToBeWritten.Append(results[i].SmallPrice);
dataToBeWritten.Append(";");
dataToBeWritten.Append(results[i].BigPrice);
dataToBeWritten.Append(";");
dataToBeWritten.Append(0);
dataToBeWritten.Append(Environment.NewLine);
}
Also note the syntax used for the properties.

Read XML to a list<string[]> using xmlread

I am going to read an xml file of a gps points to a list and later convert them to a polygon and save in database.
Here is my problem..When I try to read file every item in list is the same as others..can you help me with my problem?thanks in advanced
here is my code:
public List<string[]> loadXML(string xmlpath)
{
List<string[]> points = new List<string[]>();
XmlReader xmlReader = XmlReader.Create(xmlpath);
while (xmlReader.Read())
{
string[] item = new string[3];
if ((xmlReader.NodeType == XmlNodeType.Element) && (xmlReader.Name == "trkpt"))
{
if (xmlReader.HasAttributes)
{
item[0] = xmlReader.GetAttribute("lat");
item[1] = xmlReader.GetAttribute("lon");
}
}
if ((xmlReader.NodeType == XmlNodeType.Element) && (xmlReader.Name == "ele"))
{
item[2] = xmlReader.ReadInnerXml();
}
points.Add(item);
}
return points;
}
and here is a peice of my xml:
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<gpx xmlns="" xmlns:gpxx="" xmlns:wptx1="" xmlns:gpxtpx="" creator="GPSMAP 78s" version="1.1" xmlns:xsi="" xsi:schemaLocation="">
<metadata>
<link href=""><text>Garmin International</text></link>
<time>2014-06-18T13:55:07Z</time></metadata>
<trk><name>PV164B2KHE</name>
<extensions><gpxx:TrackExtension><gpxx:DisplayColor>Cyan</gpxx:DisplayColor></gpxx:TrackExtension></extensions>
<trkseg>
<trkpt lat="31.0403929744" lon="51.5264290944"><ele>2089.08</ele><time>2014-06-18T13:45:57Z</time></trkpt>
<trkpt lat="31.0403881129" lon="51.5264252387"><ele>2088.60</ele><time>2014-06-18T13:46:01Z</time></trkpt></trkseg></trk></gpx>
I want to extract lat,lon and ele for each point
I would use Linq to XML for that:
var xmlDocument = XDocument.Load("path");
XNamepsace ns = xmlDocument.Root.GetDefaultNamespace();
var values = xmlDocument.Root
.Descendants(ns + "trkpt")
.Select(x => new
{
lat = (string)x.Attribute("lat"),
lon = (string)x.Attribute("lon"),
ele = (string)x.Element(ns + "ele")
});
Your mistake is xmlReader.Read() reads the next node, but you are creating a string[] array for each node.A node can not be a trkpt and ele at the same time. So that will never give you the desired result.

XmlReader How to read properly?

what is the best way to read xml like this one:
<Users>
<user name = "mail">
<supplier name = "supp1">
<project name = "proj1">
<subscribe name= "sub1"/>
<subscribe name = "sub2"/>
</project>
</supplier>
<supplier name = "supp2">
<project name = "proj2">
<subscribe name = "sub3"/>
</project>
<project name = "proj3">
<subscribe name= "sub4"/>
<subscribe name = "sub5"/>
</project>
<project name = "proj4"/>
</supplier>
<supplier name = "supp3"/>
<supplier name = "supp5">
<project name = "proj4"/>
<supplier name = "supp4"/>
</user>
</Users>
For now I am using
While(reader.Read())
{
if (((reader.NodeType == XmlNodeType.EndElement) && (reader.Name == "user")))
break;
if ((reader.NodeType == XmlNodeType.Element) && (reader.Name =="supplier"))
{
foreach (TreeNode tree in TreeView1.Nodes)
{
if (reader.GetAttribute(0) == tree.Text)
{
TreeView1.SelectedNode = tree;
TreeView1.SelectedNode.Checked = true;
Get_projects(reader, tree);
break;
}
}
}
}
this is the main after that is get_projects(...):
private void Get_projects(XmlReader reader, TreeNode tree)
{
while (reader.Read())
{
if ((reader.NodeType == XmlNodeType.EndElement) && (reader.Name == "supplier")) break;
//(reader.IsEmptyElement && reader.Name == "supplier")
if ((reader.NodeType == XmlNodeType.Element) && (reader.Name == "project"))
{
foreach (TreeNode projTree in tree.Nodes)
{
if (reader.GetAttribute(0) == projTree.Text)
{
TreeView1.SelectedNode = projTree;
TreeView1.SelectedNode.Checked = true;
Get_subscribes(reader, projTree);
break;
}
}
}
}
}
the Get_subscribes(reader, projTree):
private void Get_subscribes(XmlReader reader, TreeNode tree)
{
while (reader.Read())
{
if ((reader.NodeType == XmlNodeType.EndElement) && (reader.Name == "project") ||
(reader.IsEmptyElement && reader.Name == "project")) break;
if ((reader.NodeType == XmlNodeType.Element) && (reader.Name == "subscribe"))
{
foreach (TreeNode subTree in tree.Nodes)
{
if (reader.GetAttribute(0) == subTree.Text)
{
TreeView1.SelectedNode = subTree;
TreeView1.SelectedNode.Checked = true;
break;
}
}
}
}
}
It doesn't work, so I am wondering is there a better way or what am i missing?
I will give you sample to read properly
<ApplicationPool>
<Accounts>
<Account>
<NameOfKin></NameOfKin>
<StatementsAvailable>
<Statement></Statement>
</StatementsAvailable>
</Account>
</Accounts>
</ApplicationPool>
static IEnumerable<XElement> SimpleStreamAxis(string inputUrl, string elementName)
{
using (XmlReader reader = XmlReader.Create(inputUrl))
{
reader.MoveToContent();
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element)
{
if (reader.Name == elementName)
{
XElement el = XNode.ReadFrom(reader) as XElement;
if (el != null)
{
yield return el;
}
}
}
}
}
}
using (XmlReader reader = XmlReader.Create(inputUrl))
{
reader.ReadStartElement("theRootElement");
while (reader.Name == "TheNodeIWant")
{
XElement el = (XElement) XNode.ReadFrom(reader);
}
reader.ReadEndElement();
}
Source: Reading Xml with XmlReader in C#
Hope this help.
I would consider the reverse approach i.e.: instead of reading XML and checking if a node exists in TreeView I would prefer to use XPath to check if a node exists in XML document.
In order to do so you have to traverse TreeView nodes and for each node build XPath query
e.g.: /Users/user/supplier[#name='supp1']/project[#name='proj1'].
Having XPath query you can create an instance of XPathDocument based on your XMLReader and run the query. If something is found, you will check current node in TreeView.
you can try XPath to read informations you need
XMLDocument doc = new XMLDocument();
doc.Load(your_xml_file_path);
XMLNodeList list = doc.SelectNodes(#"//project"); //get all project element

something wrong reading XML LINQ

This is my source XML :
<?xml version="1.0" encoding="UTF-8"?>
<cteProc xmlns="http://www.portalfiscal.inf.br/cte" versao="1.04">
<CTe>
<infCte versao="1.04" Id="CTe35121004211559000111570010000118991000119858">
<ide>
<cUF>35</cUF>
<cCT>00011985</cCT>
<CFOP>7358</CFOP>
<natOp>PRESTACAO DE SERVICO DE TRANSPORTE</natOp>
<forPag>1</forPag>
<mod>57</mod>
<serie>1</serie>
<nCT>11899</nCT>
<dhEmi>2012-10-01T09:34:45</dhEmi>
</ide>
<compl>
<emit>
<rem>
<dest>
<vPrest>
<imp>
<infCTeNorm>
</infCte>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
</CTe>
<protCTe versao="1.04">
</cteProc>
I have read this file with this code :
XmlTextReader reader = new XmlTextReader(#"C:\Separados\56000858_v01.04-procCTe.xml");
XmlNodeType type;
while (reader.Read())
{
type = reader.NodeType;
if (type == XmlNodeType.Element)
{
if (reader.Name == "cUF")
{ reader.Read(); Xmunini = reader.Value; textBox1.Text = Xmunini;}
if (reader.Name == "cCT")
{ reader.Read(); vtprest = reader.Value; textBox2.Text = vtprest;}
if (reader.Name == "natOp")
{ reader.Read(); UFIni = reader.Value; textBox3.Text = UFIni; }
if (reader.Name == "nCT")
{ reader.Read(); NCT = reader.Value; textBox4.Text = NCT;}
But, i have read in many post here , the method with LINQ is more efficient, i have try write this :
var custs45 = from c in XElement.Load(#"C:\Separados\56000858_v01.04-procCTe.xml").Elements("Cte")
select new {
CFOP = c.Element("CFOP").Value,
xMunIni = c.Element("xMunIni").Value
};
My question is how to assign CFOP and Xmunini to a variable?? i have write this but do not show anything
string CFF;
foreach (var valores in custs45)
{
CFF = valores.CFOP.ToString() ;
}
You can't find nodes, because root node has namespace delcared. Here is the solution:
XDocument xdoc = XDocument.Load(path_to_xml);
XNamespace ns = "http://www.portalfiscal.inf.br/cte";
string CFF = (string)xdoc.Descendants(ns + "CFOP").Single();
Also you have typo in CTe element name. And you are missing that CFOP is not direct child of CTe. And there is still no xMunIni element in your xml.
Your original query should look like this:
XNamespace ns = "http://www.portalfiscal.inf.br/cte";
var custs45 = from ide in XElement.Load(path_to_xml).Descendants(ns + "ide")
select new
{
CFOP = (string)ide.Element(ns + "CFOP"),
xMunIni = (string)ide.Element(ns + "xMunIni")
};

read only particular instance using xmlreader

I have a xml file that looks like
<Name>AAA</Name>
<Age>23</Age>
<I1>
<Element1>A</Element1>
<Element2>B</Element2>
<Element3>C</Element3>
<\I1>
<I2>
<Element1>AA</Element1>
<Element2>BB</Element2>
<Element3>CC</Element3>
</I2>
I am reading all the values of elements using xmlreader in C# 3.0. But now i have to change by reading only the values within particular start and end tage. For the xml file mentioned above, i need to read <Name>, <Age> by default and then i have a function that returns the value "I1" or "I2" which is basically the element names. If it returns "I1" then i should read only the elements between <I1> and </I1> and should not read <I2> and vice versa. So the code structure would be (just the logic please ignore the syntax errors) like
/******function that returns element name I1 or I2*********/
string elementName = func(a,b);
xmlreader reader = reader.create("test.xml");
while(reader.read())
{
switch(reader.nodetype)
{
case xmlnodetype.element:
string nodeName = reader.name
break;
case xmlnodetype.text
switch(nodeName)
{
/*************Read default name and age values*******/
case "Name":
string personName = reader.value
break;
case "Age":
string personAge = reader.value;
break;
/*******End of reading default values**************/
/*** read only elements between the value returned by function name above
If function returns I1 then i need to read only values between <I1> </I1> else read </I2> and </I2>**/
}
}
}
Thanks!
So assuming, since we dont have any other tags to go off, that your file would look something such as this from beginning to end
<?xml version="1.0" encoding="utf-8" ?>
<RootElement>
<UserInformation>
<Name>AAA</Name>
<Age>23</Age>
<I1>
<Element1>A</Element1>
<Element2>B</Element2>
<Element3>C</Element3>
<\I1>
<I2>
<Element1>AA</Element1>
<Element2>BB</Element2>
<Element3>CC</Element3>
</I2>
</UserInformation>
</RootElement>
and then to call it
System.IO.StreamReader sr = new System.IO.StreamReader("test.xml");
String xmlText = sr.ReadToEnd();
sr.Close();
List<UserInfo> finalList = readXMLDoc(xmlText);
if(finalList != null)
{
//do something
}
private List<UserInfo> readXMLDoc(String fileText)
{
//create a list of Strings to hold our user information
List<UserInfo> userList = new List<UserInfo>();
try
{
//create a XmlDocument Object
XmlDocument xDoc = new XmlDocument();
//load the text of the file into the XmlDocument Object
xDoc.LoadXml(fileText);
//Create a XmlNode object to hold the root node of the XmlDocument
XmlNode rootNode = null;
//get the root element in the xml document
for (int i = 0; i < xDoc.ChildNodes.Count; i++)
{
//check to see if we hit the root element
if (xDoc.ChildNodes[i].Name == "RootElement")
{
//assign the root node
rootNode = xDoc.ChildNodes[i];
break;
}
}
//Loop through each of the child nodes of the root node
for (int j = 0; j < rootNode.ChildNodes.Count; j++)
{
//check for the UserInformation tag
if (rootNode.ChildNodes[j].Name == "UserInformation")
{
//assign the item node
XmlNode userNode = rootNode.ChildNodes[j];
//create userInfo object to hold results
UserInfo userInfo = new UserInfo();
//loop through each if the user tag's elements
foreach (XmlNode subNode in userNode.ChildNodes)
{
//check for the name tag
if (subNode.Name == "Name")
{
userInfo._name = subNode.InnerText;
}
//check for the age tag
if (subNode.Name == "Age")
{
userInfo._age = subNode.InnerText;
}
String tagToLookFor = "CallTheMethodThatReturnsTheCorrectTag";
//check for the tag
if (subNode.Name == tagToLookFor)
{
foreach (XmlNode elementNode in subNode.ChildNodes)
{
//check for the element1 tag
if (elementNode.Name == "Element1")
{
userInfo._element1 = elementNode.InnerText;
}
//check for the element2 tag
if (elementNode.Name == "Element2")
{
userInfo._element2 = elementNode.InnerText;
}
//check for the element3 tag
if (elementNode.Name == "Element3")
{
userInfo._element3 = elementNode.InnerText;
}
}
}
}
//add the userInfo to the list
userList.Add(userInfo);
}
}
}
catch (Exception e)
{
System.Windows.Forms.MessageBox.Show(e.Message);
return null;
}
//return the list
return userList;
}
//struct to hold information
struct UserInfo
{
public String _name;
public String _age;
public String _element1;
public String _element2;
public String _element3;
}

Categories

Resources