How to read xml file c# - c#

<CPT xmlns="http://www.example.org/genericClientProfile" xmlns:ns2="http://www.blahblah.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.org/genericClientProfile genericClientProfile.xsd">
<header>
<serviceId>CPT-UK</serviceId>
<versionId>1.0</versionId>
<brandCode>CUK</brandCode>
<creationTime>2013-09-26T13:55:32.31+02:00</creationTime>
</header>
</CPT>
I need to be able to read the elements in the header tag. I'm struggling to read the values for some reason, which i'm not sure of. What i've tried:
public ActionResult readxmldata()
{
using (var db = new CPTEntities())
{
var file = System.IO.Directory.GetFiles("C:\\Workspace\\CPTStaging","*.xml");
foreach (var xmldoc in file)
{
XmlDocument docpath = new XmlDocument();
docpath.Load(xmldoc);
CPTPROFILE doc = new CPTPROFILE();
db.SaveChanges();
H_HEADER header = new H_HEADER();
header.SERVICEID = docpath.SelectSingleNode("//CPT/header/#serviceId").Value;
header.VERSIONID = Convert.ToDecimal(docpath.SelectSingleNode("//CPT/header/#versionId").Value);
header.CREATIONTIME = Convert.ToDateTime(docpath.SelectSingleNode("//CPT/header/#creationTime").Value);
header.BRANDCODE = docpath.SelectSingleNode("//CPT/header/#brandCode").Value;
db.CPTPROFILEs.AddObject(doc);
db.SaveChanges();
}
}

Your XML uses namespaces. xmlns attribute declares default namespace. You should use it for each element of the XML.
XNamespace ns = "http://www.example.org/genericClientProfile";
XDocument doc = XDocument.Load(xmldoc);
XElement header = doc.Root.Element(ns + "header");

For comparison, here is one way to do it with Linq-to-XML:
XDocument doc = XDocument.Load(xmlFileName);
XNamespace ns = "http://www.example.org/genericClientProfile";
var header = doc.Descendants(ns+"header").Single();
H_HEADER header = new H_HEADER();
header.SERVICEID = (string) header.Element(ns + "serviceId");
header.VERSIONID = (double) header.Element(ns + "versionId");
header.BRANDCODE = (string) header.Element(ns + "brandCode");
header.CREATIONTIME = (DateTime) header.Element(ns + "creationTime");

Related

xdocument re writing xml document [duplicate]

I have a method which load XML to a XDocument and modify its elements then save.
But when I reload it. I got this error :
Unexpected XML declaration. The XML declaration must be the first node in the document, and no white space characters are allowed to appear before it.
I checking the XML and see that the XDocument didn't save the changed but create a duplicate and save.
It save the old one and the new one like this example xml :
<?xml version="1.0" encoding="UTF-8"?>
<Ungdungs>
<Ungdung>
<Name>HERE City Lens</Name>
<Id>b0a0ac22-cf9e-45ba-8120-815450e2fd71</Id>
<Path>/Icon/herecitylens.png</Path>
<Version>Unknown</Version>
<Category>HERE</Category>
<Date>Uknown</Date>
</Ungdung>
<?xml version="1.0" encoding="UTF-8"?>
<Ungdungs>
<Ungdung>
<Name>HERE City Lens</Name>
<Id>b0a0ac22-cf9e-45ba-8120-815450e2fd71</Id>
<Path>/Icon/herecitylens.png</Path>
<Version>1.0.0.0</Version>
<Category>HERE</Category>
<Date>Uknown</Date>
</Ungdung>
Here the code I used to modify and save XML :
using (Stream stream = storage.OpenFile("APPSDATA.xml", FileMode.Open, FileAccess.ReadWrite))
{
//var xdoc = XDocument.Load("APPSDATA.xml");
var xdoc = XDocument.Load(stream, LoadOptions.None);
var listapp = from c in xdoc.Descendants("Ungdung") select c;
foreach (XElement app in listapp)
{
var xElement = app.Element("Name");
if (xElement != null)
progressIndicator.Text = "Checking " + xElement.Value + "...";
var element = app.Element("Id");
if (element != null)
{
var appId = element.Value;
var appVersion = await GetAppsVersion(appId);
app.Element("Version").Value = appVersion.ToString();
}
}
xdoc.Save(stream);
}
How can I solve this problem ?
Looks like you're appending modified document at the end of current file content. That's why you can't parse it later again.
I would split read and write parts into different using statements:
XDocument xdoc;
using (Stream stream = storage.OpenFile("APPSDATA.xml", FileMode.Open, FileAccess.Read))
{
xdoc = XDocument.Load(stream, LoadOptions.None);
}
var listapp = from c in xdoc.Descendants("Ungdung") select c;
foreach (XElement app in listapp)
{
var xElement = app.Element("Name");
if (xElement != null)
progressIndicator.Text = "Checking " + xElement.Value + "...";
var element = app.Element("Id");
if (element != null)
{
var appId = element.Value;
var appVersion = await GetAppsVersion(appId);
app.Element("Version").Value = appVersion.ToString();
}
}
using (Stream stream = storage.OpenFile("APPSDATA.xml", FileMode.Truncate, FileAccess.Write))
{
xdoc.Save(stream);
}
Setting FileMode.Truncate on second using statement will clear previous file content, what should fix your problem.

How to get attribute xml without loop c#

i have xml file like this
> <?xml version='1.0' ?>
<config>
<app>
<app version="1.1.0" />
> </app>
</config>
and i want to read attribute version from node app
without any loop like this
while(reader.read()) or foreach etc.
Thanks
XmlDocument document = new XmlDocument();
document.Load("D:/source.xml");
XmlNode appVersion1 = document.SelectSingleNode("//app[#version]/#version");
XmlNode appVersion2 = document["config"]["app"]["app"].Attributes["version"];
Console.WriteLine("{0}, {1}",
appVersion1.Value,
appVersion2.Value);
You can do it this way.
XmlDocument doc = new XmlDocument();
string str = "<config><app><app version=" + "\"1.1.0\"" + "/></app></config>";
doc.LoadXml(str);
var nodes = doc.GetElementsByTagName("app");
foreach (XmlNode node in nodes)
{
if (node.Attributes["version"] != null)
{
string version = node.Attributes["version"].Value;
}
}
And you need to this for loop cause you got two nodes with same name App.
If you have a single node with name App,
XmlDocument doc = new XmlDocument();
string str = "<config><app version=" + "\"1.1.0\"" + "/></config>";
doc.LoadXml(str);
var node = doc.SelectSingleNode("//app");
if (node.Attributes["version"] != null)
{
string version = node.Attributes["version"].Value;
Console.WriteLine(version);
}
You can use linq to do
string stringXml= "yourXml Here";
XElement xdoc = XElement.Parse(stringXml);
var result= xdoc.Descendants("app").FirstOrDefault(x=> x.Attribute("version") != null).attribute("version").Value;
or:
var result = xdoc.Descendants("app").Where(x => x.Attribute("version") != null)
.Select(x => new { Version = x.Value });

Get specific xml lines with linq

I have an XML looking like this:
<data xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<row>
<Alert>warning</Alert>
</row>
</data>
I wan't to get all the rows. In this case, the value that I wan't is "Alert".
This is as fare as I've got...
using (XmlReader reader = cmd.ExecuteXmlReader())
{
string xmlFile = "";
while (reader.Read())
{
xmlFile = reader.ReadOuterXml();
}
var xmlElement = XElement.Parse(xmlFile);
var result = xmlElement.Elements("data").Where(x => x.Value.Equals("row")).ToList();
}
I know something is wrong with my linq, but I'm quite new to linq and would like some help.
Thanks!
XNamespace ns = "http://www.w3.org/2001/XMLSchema-instance";
var xDocument = XDocument.Load("path");
var result = xDocument.Descendants(ns + "row").ToList();
I hope this will work. Please try this.
var xDocument = XDocument.Load(#"XmlFilePath");
//Use below if you have xml in string format
// var xDocument = XDocument.Parse("XmlString");
XNamespace ns = xDocument.Root.GetDefaultNamespace();
var result = xDocument.Descendants(ns + "row").ToList();

Can't get attribute value with C# XPath

I've spent so much time with this already, still can't get the value of NTE attribute. Can someone please help?
C#
StreamReader sr = new StreamReader(resp.GetResponseStream());
XPathDocument xmlDoc = new XPathDocument(sr); // holds xml document
XPathNavigator xmlNav = xmlDoc.CreateNavigator(); //evaluates XPath expressions
XPathNodeIterator node = xmlNav.Select("/DATA2SC/CALL");
string dne = xmlNav.GetAttribute("NTE", "");
Console.WriteLine(dne);
sr.Close();
XML
<?xml version="1.0"?>
<DATA2SC PIN="00000">
<CALL
TR_NUM="00000001"
STATUS="WAITING_FOR_APPROVAL"
NTE="$15.00">
<PROBLEM>
Text
</PROBLEM>
</CALL>
</DATA2SC>
Can you try this code please ?
I already check and it's work
StreamReader sr = new StreamReader("c:\\x.xml");
XPathDocument xmlDoc = new XPathDocument(sr); // holds xml document
XPathNavigator xmlNav = xmlDoc.CreateNavigator(); //evaluates XPath expressions
var node = xmlNav.SelectSingleNode("/DATA2SC/CALL");
string dne = node.GetAttribute("NTE", "");
Console.WriteLine(dne);
OR
XDocument docXmlWorld = XDocument.Load("c:\\x.xml");
foreach (var node1 in docXmlWorld.Descendants("DATA2SC"))
{
foreach (var node2 in node1.Descendants("CALL"))
{
string dne = node2.Attribute("NTE").Value;
Console.Out.WriteLine(dne);
}
}
Or you can do like this too:
XDocument docXmlWorld = XDocument.Load("c:\\x.xml");
//Get the first child => [DATA2SC]
XElement elementNodeDATA2SC = docXmlWorld.Element("DATA2SC");
//Get the first child => [CALL]
XElement elementNodeCALL = elementNodeDATA2SC.Element("CALL");
//Get the attribute NTE from [CALL] node
string dne = elementNodeCALL.Attribute("NTE").Value;
Console.Out.WriteLine(dne);
The Select method, returns a collection of all nodes with the specified XPath.
You can use SelectSingleNode, to select the first node.
var node = xmlNav.SelectSingleNode("/DATA2SC/CALL");
string dne = node.GetAttribute("NTE", "");

getting a specific value using linq to xml

I'm working on windows 8 metro apps and i need to get some information from a XML file.
i parse it with LINQ to XML but I've got a problem.
here is the XML:
<feed xmlns="http://www.allocine.net/v6/ns/">
<page>1</page>
<count>1</count>
<results type="movie">10</results>
<results type="person">0</results>
<totalResults>10</totalResults>
<movie code="61282">
<originalTitle>Avatar</originalTitle>
<title>Avatar</title>
<productionYear>2009</productionYear>
<release>
<releaseDate>2010-09-01</releaseDate>
</release>
<castingShort>
<directors>James Cameron</directors>
<actors>Sam Worthington, Zoe Saldana, Sigourney Weaver, Stephen Lang, Michelle Rodriguez</actors>
</castingShort>
<statistics>
<pressRating>4.33333</pressRating>
<userRating>4.31338</userRating>
</statistics>
<poster path="/medias/nmedia/18/78/95/70/19485155.jpg"
href="http://images.allocine.fr/medias/nmedia/18/78/95/70/19485155.jpg"/>
<linkList>
<link rel="aco:web"
href="http://www.allocine.fr/film/fichefilm_gen_cfilm=61282.html"/>
</linkList>
</movie>
</feed>
I need to get "code" value of the "movie" node and the "href" value of the node "link" but all the things i tried failed ...
You can consider that the beginning of the XML is <movie> because I get the file and i parse it to keep the XML clean as I want. my file start with <movie code="">
For a classic value like "actors" i do :
Actors = (string)query.Element("castingShort").Element("actors")
It is working perfectly! My problem is for the specific value with a name.
edit :
that's what i did with your advices.
var group1 = new SampleDataGroup("Group-1", "Films", "", "Assets/icone_groupe_all_movies.jpg", "Films sur le DD");
movieName = "avatar";
Uri = "http://api.allocine.fr/rest/v3/search?partner=YW5kcm9pZC12M3M&filter=movie,person&count=1&page=1&q=" + movieName + "&format=xml";
var httpResponse = await new HttpClient().GetAsync(Uri);
string sourceCode = get_new_xml(await httpResponse.Content.ReadAsStringAsync());
XDocument doc = XDocument.Parse(sourceCode);
XNamespace ns = "http://www.allocine.net/v6/ns/";
XElement movie = doc.Root.Element(ns + "movie");
XElement castingShort = movie.Element(ns + "castingShort");
XElement statistics = movie.Element(ns + "statistics");
Data data = new Data
{
MovieCode = (string)movie.Attribute("code"),
OriginalTitle = (string)movie.Element(ns + "originalTitle"),
Title = (string)movie.Element(ns + "title"),
ProductionYear = (string)movie.Element(ns + "productionYear"),
Directors = (string)castingShort.Element(ns + "directors"),
Actors = (string)castingShort.Element(ns + "actors"),
PressRating = (string)statistics.Element(ns + "pressRating"),
UserRating = (string)statistics.Element(ns + "userRating"),
Cover = (string)movie.Element(ns + "linkList").Element(ns + "link").Attribute("href")
};
group1.Items.Add(new SampleDataItem("Group-1-Item-1", data.Title, data.Cover, data.ProductionYear, "", data.ReleaseDate, group1));
this.AllGroups.Add(group1);
but unfortunately it still doesent work ...
Thus you have namespace declared in your xml, you should declare and initialize an XNamespace object, and to use it when specifying XName objects (arguments to Element methods):
XDocument xdoc = XDocument.Load(path_to_xml);
XNamespace ns = "http://www.allocine.net/v6/ns/";
XElement movie = xdoc.Root.Element(ns + "movie");
var code = (int)movie.Attribute("code");
var href = (string)movie.Element(ns + "linkList")
.Element(ns + "link").Attribute("href");
If you have only one <movie> element, then you don't need to operate on sequence of movie elements and treat single movie as list. Simply get movie node and create new data object via parsing that node:
XNamespace ns = "http://www.allocine.net/v6/ns/";
XElement movie = xdoc.Root.Element(ns + "movie");
XElement castingShort = movie.Element(ns + "castingShort");
XElement statistics = movie.Element(ns + "statistics");
Data data = new Data
{
MovieCode = (int)movie.Attribute("code"),
OriginalTitle = (string)movie.Element(ns + "originalTitle"),
Title = (string)movie.Element(ns + "title"),
ProductionYear = (string)movie.Element(ns + "productionYear"),
Directors = (string)castingShort.Element(ns + "directors"),
Actors = (string)castingShort.Element(ns + "actors"),
PressRating = (string)statistics.Element(ns + "pressRating"),
UserRating = (string)statistics.Element(ns + "userRating"),
Cover = (string)movie.Element(ns + "linkList")
.Element(ns + "link").Attribute("href")
};

Categories