something wrong reading XML LINQ - c#

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")
};

Related

How to get separate values from Xlement

This is a portion of XML I'm trying to parse
<BRTHDATES>
<BRTHDATE value="5/1/1963" code="B"/>
</BRTHDATES>
var birthdates = xmlDoc.XPathSelectElements("/INDV/PERSON/BRTHDATES").Elements().Where(e => e.Name == "BRTHDATE");
xe = birthdates.Elements().Where(e => e.Name == "BRTHDATE");
bbs = from b in birthdates
select new
{
Birthdays = b.FirstAttribute.Value,
Code = b?.Value
};
var status = birthdates.Elements().Where(e => e.Name.LocalName == "BRTHDATE").Single().Value;
When I try to get "Value" from the Element I get an empty string. I can't get anything for the "code" attribute.
It sure seems like this should be a lot easier...
You can try below code. I've already tested through a test project and got the require value.
string personBirthday = string.Empty;
string soapResult = #"<?xml version=""1.0"" encoding=""utf - 8"" ?><INDV> <PERSON> <BRTHDATES><BRTHDATE value = ""5/1/1963"" code = ""B"" /> </BRTHDATES></PERSON></INDV> ";
XmlDocument doc = new XmlDocument();
doc.Load(new StringReader(soapResult));
XmlNodeList person = doc.GetElementsByTagName("BRTHDATES");
if (person[0].ChildNodes.Count > 0)
{
foreach (XmlNode item in person[0].ChildNodes)
{
if (item.Name.Trim().Equals("BRTHDATE"))
{
personBirthday = !string.IsNullOrEmpty(item.Attributes[0].Value) ? item.Attributes[0].Value.Trim() : string.Empty;
}
}
}
Here is the solution
You can select specific Element from a Xml. Just try below sample code
XmlNodeList generalTabNodeList = xmlDocument.SelectNodes("/INDV/PERSON/BRTHDATES");
foreach (XmlNode node in generalTabNodeList)
{
if (node.ChildNodes.Count > 0)
{
string birthdate = !string.IsNullOrEmpty(node.ChildNodes[0].ToString()) ? node.ChildNodes[2].InnerText.ToString() : string.Empty;
}
}
I can't quite follow what you are trying to do, but, this should get you going:
For an XML file that looks like this:
<?xml version="1.0" encoding="utf-8" ?>
<INDV>
<PERSON>
<BRTHDATES>
<BRTHDATE value="5/1/1963" code="B"/>
</BRTHDATES>
</PERSON>
</INDV>
(Note, this is an entire XML document - one that matches your code, not just the snippet you provided (that doesn't match your code))
This code will pick out the value and code attributes:
using (var xmlStream = new FileStream("Test.xml", FileMode.Open))
{
XDocument xmlDocument = XDocument.Load(xmlStream);
var birthDateElements = xmlDocument.XPathSelectElements("/INDV/PERSON/BRTHDATES/BRTHDATE");
var birthDateElement = birthDateElements.FirstOrDefault();
if (birthDateElement != null)
{
var attributes = birthDateElement.Attributes();
var valueAttribute = attributes.Where(a => a.Name == "value");
var codeAttribute = attributes.Where(a => a.Name == "code");
}
}
You can play around with this code to figure out what you want to do. Whatever you do, don't pick out attributes by position, pick them out by name.

C# xml reader, same element name

I'm trying to read an element from my xml file.
I need to read an string in an "link" element inside the "metadata",
but there are 2 elements called "link", I only need the second one:
<metadata>
<name>visit-2015-02-18.gpx</name>
<desc>February 18, 2015. Corn</desc>
<author>
<name>text</name>
<link href="http://snow.traceup.com/me?id=397760"/>
</author>
<link href="http://snow.traceup.com/stats/u?uId=397760&vId=1196854"/>
<keywords>Trace, text</keywords>
I need to read this line:
<link href="http://snow.traceup.com/stats/u?uId=397760&vId=1196854"/>
This is the working code for the first "link" tag, it works fine,
public string GetID(string path)
{
string id = "";
XmlReader reader = XmlReader.Create(path);
while (reader.Read())
{
if ((reader.NodeType == XmlNodeType.Element) && (reader.Name == "link"))
{
if (reader.HasAttributes)
{
id = reader.GetAttribute("href");
MessageBox.Show(id + "= first id");
return id;
//id = reader.ReadElementContentAsString();
}
}
}
return id;
}
Does anyone know how I can skip the first "link" element?
or check if reader.ReadElementContentAsString() contains "Vid" or something like that?
I hope you can help me.
xpath is the answer :)
XmlReader reader = XmlReader.Create(path);
XmlDocument doc = new XmlDocument();
doc.Load(reader);
XmlNodeList nodes = doc.SelectNodes("metadata/link");
foreach(XmlNode node in nodes)
Console.WriteLine(node.Attributes["href"].Value);
Use the String.Contains method to check if the string contains the desired substring, in this case vId:
public string GetID(string path)
{
XmlReader reader = XmlReader.Create(path);
while (reader.Read())
{
if ((reader.NodeType == XmlNodeType.Element) && (reader.Name == "link"))
{
if (reader.HasAttributes)
{
var id = reader.GetAttribute("href");
if (id.Contains(#"&vId"))
{
MessageBox.Show(id + "= correct id");
return id;
}
}
}
return String.Empty;
}
If acceptable you can also use LINQ2XML:
var reader = XDocument.Load(path); // or XDocument.Parse(path);
// take the outer link
Console.WriteLine(reader.Root.Element("link").Attribute("href").Value);
The output is always:
http://snow.traceup.com/stats/u?uId=397760&vId=1196854= first id
Another options is to use XPath like #user5507337 suggested.
XDocument example:
var xml = XDocument.Load(path); //assuming path points to file
var nodes = xml.Root.Elements("link");
foreach(var node in nodes)
{
var href = node.Attribute("href").Value;
}

Reading XML giving null

<tours xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://api.contiki.com/schemas/v2/detailed_tours.xsd">
<tour>
<id>290</id>
<name>Peru Uncovered</name>
<lowest_price>
<code>11D15a</code>
</lowest_price>
</tour>
</tours>
I want to read Id, name and code.
I am trying this code
XmlTextReader reader = new XmlTextReader(downloadfolder);
XmlDocument doc = new XmlDocument();
XmlNode node = doc.ReadNode(reader);
foreach (XmlNode chldNode in node.ChildNodes)
{
string employeeName = chldNode.Attributes["name"].Value;
}
But i am getting null. Can anyone tell me how can i read the values? i can not use Linq as i am working in SSIS 2008 project which does not support linq.
Updated Answer
XmlTextReader reader = new XmlTextReader(downloadfolder);
while (reader.Read())
{
switch (reader.NodeType)
{
case XmlNodeType.Element: // The node is an element.
string node = reader.Name;
if (node == "id")
{
string id = reader.ReadString();
}
if (node == "name")
{
string name = reader.ReadString();
}
if (node == "code")
{
string code = reader.ReadString();
}
break;
}
I can read the values but how can i add these as a row in my data table?
here node type of "name" is element.
below code can be used for node type checking
XmlTextReader reader = new XmlTextReader ("<file name>");
while (reader.Read())
{
switch (reader.NodeType)
{
case XmlNodeType.Element:
Reference : http://support.microsoft.com/en-us/kb/307548

XML read text inside two elements

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 });

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
}

Categories

Resources