I have this XML
<?xml version="1.0" encoding="UTF-8"?>
<nfeProc xmlns="http://www.portalfiscal.inf.br/nfe" versao="2.00">-<NFe>-<infNFe versao="2.00" Id="NFe35130649196462000115550010000036141000025758">
<ide>
<natOp>DEVOL. ARMAZENAGEM</natOp>
</ide>
<total>
<ICMSTot>
<vNF>43778.00</vNF>
</ICMSTot>
</total>
I read with this C# code :
private void leerarquivoN(string caminx)
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(caminx);
XmlNodeList ml = xmlDoc.GetElementsByTagName("*");
XmlNode primer = xmlDoc.DocumentElement;
tipo_arq = primer.Name;
if (xmlDoc.DocumentElement.Name == "nfeProc")
{ foreach (XmlNode xn in ml)
{
if (xn.Name == "infNFe")
{
chave_nota = xn.Attributes["Id"].Value;
versao = xn.Attributes["versao"].Value;
lblChaveNota.Text = chave_nota; lblversao.Text = versao;
}
}
XmlNodeList xnList = xmlDoc.GetElementsByTagName("ide");
foreach (XmlNode xn in xnList)
{
if (xn.Name == "ide")
{
if (xn["nNF"] != null)
{ nnota = (xn["nNF"]).InnerText; label8.Text = nnota; }
if (xn["dEmi"] != null)
{ ndata = (xn["dEmi"]).InnerText; lblData.Text = ndata;}
if (xn["natOP"] != null)
{ natop = (xn["natOP"]).InnerText; lblNAtop.Text = natop ; }
}
}
XmlNodeList xnList2 = xmlDoc.GetElementsByTagName("emit");
foreach (XmlNode xn in xnList2)
{
{ if (xn["CNPJ"] != null)
{ ncnpj = (xn["CNPJ"]).InnerText; lblCNPJ.Text = ncnpj; }
}
}
XmlNodeList xnList3 = xmlDoc.GetElementsByTagName("total");
foreach (XmlNode xn in xnList3)
{
{
if (xn["vNF"] != null)
{ ntotal = (xn["vNF"]).InnerText; lblvNF.Text = ntotal ; }
}
}
}
I can not read VNF and natOP , what i m doing wrong???
Thanks
The code you are using just gets the main nodes. To get the children associated with each node (natOp and vNF), you have to rely on a different code (MSDN reference). Sample for natOp (inside the xnList for loop):
if (xn.HasChildNodes)
{
for (int i=0; i<xn.ChildNodes.Count; i++)
{
//xn.ChildNodes[i].InnerText -> what you are after
}
}
Related
My friend wants to upload only product differences to his web shop. So my idea is to compare XML files and extract only changes. Thus I've created this:
Part of XML file (note that this XML have more elements, but I've excluded them):
<?xml version="1.0" encoding="UTF-8"?>
<artikli>
<artikal>
<id>1039282</id>
<sifra>42640</sifra>
<naziv><![CDATA[Bluetooth zvucnik za tablet IYIGLE X7 crni]]></naziv>
</artikal>
<artikal>
<id>1048331</id>
<sifra>48888</sifra>
<naziv><![CDATA[Bluetooth zvucnik REMAX RB-M15 crni]]></naziv>
</artikal>
</artikli>
C# script
static IEnumerable<XElement> StreamRootChildDoc(string uri)
{
using (XmlReader reader = XmlReader.Create(uri))
{
reader.MoveToContent();
while (!reader.EOF)
{
if (reader.NodeType == XmlNodeType.Element && reader.Name == "artikal")
{
XElement el = XElement.ReadFrom(reader) as XElement;
if (el != null)
yield return el;
}
else
{
reader.Read();
}
}
}
}
void ProcessFiles()
{
try
{
IEnumerable<XElement> posle = from el in StreamRootChildDoc(#"lisic2.xml")
select el;
IEnumerable<XElement> pre = from el in StreamRootChildDoc(#"lisic1.xml")
select el;
XmlDocument doc = new XmlDocument();
//(1) the xml declaration is recommended, but not mandatory
XmlDeclaration xmlDeclaration = doc.CreateXmlDeclaration("1.0", "UTF-8", null);
XmlElement root = doc.DocumentElement;
doc.InsertBefore(xmlDeclaration, root);
//(2) string.Empty makes cleaner code
XmlElement element1 = doc.CreateElement(string.Empty, "artikli", string.Empty);
doc.AppendChild(element1);
int count_files = 0;
foreach (XElement node_posle in posle)
{
count_files++;
var node_pre = pre.First(child => child.Element("id").Value == node_posle.Element("id").Value);
if (node_pre != null)
{
string pre_Value = node_pre.Value.Replace("\t", ""); ;
string posle_Value = node_posle.Value.Replace("\t", ""); ;
if (pre_Value != posle_Value)
{
var reader = node_posle.CreateReader();
reader.MoveToContent();
XmlElement element2 = doc.CreateElement(string.Empty, "artikal", reader.ReadInnerXml());
element1.AppendChild(element2);
}
}
}
doc.Save("document.xml");
}
finally
{
}
}
This works but after 10000 passed records the speed is 18 records per second, after 14000 - 12 records/sec. Is there any other approach to speed this up?
UPDATE
Now, I will try to move faster to the corresponding ID of checked XML.
One way to do it is with XmlDocument, just because the XML is small (22000 products) it is possible to use it.
void ProcessXMLDocument()
{
SetControlEnabled(btStart, false);
Stopwatch sw = new Stopwatch();
sw.Start();
try
{
XmlDocument sada = new XmlDocument();
sada.Load(tbPathSada.Text);
XmlDocument pre = new XmlDocument();
pre.Load(tbPathOdPre.Text);
XmlDocument doc = new XmlDocument();
//(1) the xml declaration is recommended, but not mandatory
XmlDeclaration xmlDeclaration = doc.CreateXmlDeclaration("1.0", "UTF-8", null);
XmlElement root = doc.DocumentElement;
doc.InsertBefore(xmlDeclaration, root);
//(2) string.Empty makes cleaner code
XmlElement element1 = doc.CreateElement(string.Empty, "artikli", string.Empty);
doc.AppendChild(element1);
root = sada.DocumentElement;
XmlNodeList nodes = root.SelectNodes("artikal");
int count_files = 0;
foreach (XmlNode nodeSada in nodes)
{
count_files++;
try
{
SetControlText(lbBlokova, count_files.ToString());
TimeSpan elapsed = sw.Elapsed;
var files_per_sec = Math.Floor((double)count_files / (double)elapsed.TotalSeconds);
SetControlText(lbPerSecond, files_per_sec.ToString());
SetControlText(lbTime, elapsed.ToString(#"hh\:mm\:ss"));
}
catch (Exception ex2)
{
}
var idSada = nodeSada.SelectSingleNode("id").InnerText.Trim();
var nodePre = pre.DocumentElement.SelectSingleNode("artikal[id='" + idSada + "']");
if (nodePre != null)
{
string pre_Value = nodePre.InnerXml.Replace("\t", ""); ;
string posle_Value = nodeSada.InnerXml.Replace("\t", ""); ;
if (pre_Value != posle_Value)
{
XmlNode importNode = doc.ImportNode(nodeSada, true);
element1.AppendChild(importNode);
}
}
else
{
XmlNode importNode = doc.ImportNode(nodeSada, true);
element1.AppendChild(importNode);
}
}
doc.Save("razlika.xml");
}
finally
{
sw.Stop();
SetControlEnabled(btStart, true);
}
}
This way I've managed to improve #10000 records => 140 rec/sec and #14000 => 104 rec/sec
I have an XML file looking like this:
<data xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<row>
<Alert>warning</Alert>
<Alert2>warning</Alert2>
</row>
</data>
When I use the code below I only get the "Alert"-node. But I wan't "Alert2" as well (and so on...). What am I missing here?
using (XmlReader reader = cmd.ExecuteXmlReader())
{
string xmlFile = "";
while (reader.Read())
{
xmlFile = reader.ReadOuterXml();
}
var doc = new XmlDocument();
doc.LoadXml(xmlFile);
var nodes = doc.SelectNodes("data/row");
if (nodes == null) return columns;
var i = 0;
foreach (XmlNode node in nodes)
{
var column = node.ChildNodes[i].Name;
columns.Add(column);
i++;
}
return columns;
}
Change your loop to the equivalent of:
var doc = new XmlDocument();
doc.LoadXml(xml);
var nodes = doc.SelectNodes("data/row");
int i = 0;
foreach (XmlNode node in nodes)
{
foreach (var child in node.ChildNodes)
{
var element = (XmlElement)child;
string nodeName = element.Name;
string value = element.InnerXml;
i++;
}
}
I have data in the following format:
https://www.dropbox.com/s/osu4w634lnoy2pw/2.xml
While trying to parse I want all the field elements also. I am able to get all the elements under table but not under field. Could somebody please help me?
My code is as follows:
XmlDocument doc = new XmlDocument();
doc.Load(#maploc);
XmlNodeList nodes = doc.DocumentElement.SelectNodes("/schema/table");
foreach (XmlNode node in nodes)
{
attribute1 = "";
attribute2 = "";
attribute3 = "";
try
{
attribute1 = node.Attributes["name"].Value;
attribute2 = node.SelectSingleNode("tabledefault").InnerText;
attribute3 = node.SelectSingleNode("invoke").InnerText;
}
catch(Exception ex)
{
//Nothing
}
if (node.HasChildNodes)
{
for (int i = 0; i < node.ChildNodes.Count; i++)
{
foreach (XmlNode nodei in node.ChildNodes[i])
{
attribute4 = "";
attribute5 = "";
attribute6 = "";
try
{
attribute4 = node.Attributes["name"].Value;
attribute5 = node.SelectSingleNode("invoke").InnerText;
attribute6 = node.SelectSingleNode("dtype").InnerText;
catch (Exception ex)
{
//Nothing
}
}
}
}
Thanks...
Your error is :
for (int i = 0; i < node.ChildNodes.Count; i++)
{
foreach (XmlNode nodei in node.ChildNodes[i])
{
You are iterating over the nodes that are the children of the current child (you are going one level too deep). This is because an XmlNode is an Enumerable over its Children.
A single foreach loop is needed :
foreach (XmlNode nodei in node.ChildNodes)
{
Why duplicate code?
I read on a rampage in the xml data! and installing a toolstripmenu! but for some reason every so often put into the xml amennyi item is in! Why?
here is the code:
try
{
XmlDocument xml = new XmlDocument();
xml.Load("allomasok.xml");
XmlNodeList xnList = xml.SelectNodes("/radiok/allomas");
mennyi =int.Parse(xnList.Count.ToString());
foreach (XmlNode xn in xnList)
{
string radioNEV = xn["neve"].InnerText;
string radioURL = xn["url"].InnerText;
//int i = mennyi;
ToolStripMenuItem[] items = new ToolStripMenuItem[mennyi];
for (int i = 0; i < items.Length; i++)
{
items[i] = new ToolStripMenuItem();
items[i].Name = "mentett" + i.ToString();
items[i].Tag = radioURL;
items[i].Text = radioNEV;
items[i].Click += new EventHandler(MenuItemClickHandler);
}
sajátokToolStripMenuItem.DropDownItems.AddRange(items);
}
}
catch
{
MessageBox.Show("Hiba", "NetRadioPlayer");
}
finally
{
MessageBox.Show("Ennyi mentett állomás van: " + mennyi);
}
Thanks.
You have too many loops, I think. Try this:
try
{
XmlDocument xml = new XmlDocument();
xml.Load("allomasok.xml");
XmlNodeList xnList = xml.SelectNodes("/radiok/allomas");
ToolStripMenuItem mi;
int i;
foreach (XmlNode xn in xnList)
{
string radioNEV = xn["neve"].InnerText;
string radioURL = xn["url"].InnerText;
mi = new ToolStripMenuItem();
mi.Name = "mentett" + i++.ToString();
mi.Tag = radioURL;
mi.Text = radioNEV;
mi.Click += new EventHandler(MenuItemClickHandler);
sajátokToolStripMenuItem.DropDownItems.Add(mi);
}
}
catch
{
MessageBox.Show("Hiba", "NetRadioPlayer");
}
finally
{
MessageBox.Show("Ennyi mentett állomás van: " + mennyi);
}
If that doesn't help I'm sorry, I don't understand the question.
I am trying to loop through an Xml file and display the value for account in a message.
XmlNodeList nodeList = testDoc.SelectNodes("/details/row/var");
foreach (XmlNode no in nodeList)
{
XmlNode node = testDoc.SelectSingleNode("/details/row/var[#name='account']");
test.actual = node.Attributes["value"].Value;
MessageBox.Show(test.account);
}
The message box is currently displaying the first record repeatidly, how can I get to the next record?
Thanks for your input in advance.
You are repeatedly assigning node with the same element from testDoc. It is not clear what test.account is (perhaps a mistype for test.actual)?
no is the variable which will iterate the contents of nodeList - I imagine you intended to use that.
EDIT following edit of OP
Now you've shown us what nodeList is, I suspect you want to do something like this instead :
XmlNodeList nodeList = testDoc.SelectNodes("/details/row/var[#name='account']");
foreach (XmlNode no in nodeList)
{
test.actual = no.Attributes["value"].Value;
...
XmlDocument doc = new XmlDocument();
doc.Load("d:\\test.xml");
XmlNodeList node = doc.GetElementsByTagName("w:r");
foreach (XmlNode xn in node)
{
try
{
if (xn["w:t"].InnerText != null)
{
if (xn["w:t"].InnerText == "#")
{
string placeHolder = xn["w:t"].InnerText;
foreach (XmlNode a in node)
{
if (a["w:t"].InnerText != "#")
{
string placeHolder1 = a["w:t"].InnerText;
}
}
}
}
}
catch (Exception e)
{
Console.Write(e);
}
}
Here is the sample for parent node value to get information of the child nodes.here i am using the ReportItems ParentNode and Print only image child nodes.
xmldoc.Load(rdlFile);
StringBuilder sb=new StringBuilder();
XmlNode node = xmldoc.GetElementsByTagName("ReportItems")[0];
XmlNodeList list = node.ChildNodes;
atributes=new string[node.ChildNodes.Count];
int l = 0;
for (int j = 0; j < node.ChildNodes.Count; j++)
{
if (list[j].Name == "Image")
{
XmlAttributeCollection att = list[j].Attributes;
atributes[l] = att[0].Value.ToUpper();
}
l++;
}
for (int i = 0; i < node.ChildNodes.Count; i++)
{
if (searchText.Text.ToUpper() == atributes[i])
{
XmlNodeList lastlist = node.ChildNodes;
XmlNodeList endlist = lastlist[i].ChildNodes;
for (int k = 0; k < endlist.Count; k++)
{
sb.Append(endlist[k].Name+" - "+ endlist[k].InnerText);
sb.Append("\n"+"\n");
}
}
}
let me know if you have doubt..
Try this,
XmlDocument xdoc = new XDocument();
xdoc.Load("*/File/*");
string xmlcontents = xdoc.InnerXml;
var xpath = "(/details/row/var[#name='account'])";
XmlNodeList lists = xdoc.DocumentElement.SelectNodes(xpath);
foreach (XmlNode _node in lists)
{
string _nodeValue = _node.InnerText;
MessageBox.Show(_nodeValue);
}
Try the following:
//Create an xml reader;
XmlDocument _xmlDocument = new XmlDocument();
_xmlDocument.Load(/*File Name here*/);
//Select the element with in the xml you wish to extract;
XmlNodeList _nodeList = _xmlDocument.SelectNodes("/details/row/var[#name='account']");
//Display the values in the node list to the screen;
foreach (XmlNode _node in _nodeList)
{
String _nodeValue = _node.InnerText.ToString();
MessageBox.Show(_nodeValue.ToString());
}
I'm not 100% sure, but you may need to use recursion. If not, it should just look like this:
XmlDocument doc = //etc..
foreach(XmlNode node in doc.ChildNodes)
{
if(node.Name == "account")
{
MessageBox.Show(node.Value);
}
}
You shouldn't spend time with reading the xml node by node. Try Deserialization: