XmlDocument in an array like object - c#

I googled for hours and didn't find anything.
I'm trying to make a Metro App which is reading from an online XML Service. Getting the XML is not the problem, i'm simply doing it like this ->
var xmlDoc = await XmlDocument.LoadFromUriAsync(new Uri(url));
but now the problem is, how to convert it into a list or something readable like this.
The XML I want to read is really huge and i don't want to go through all nodes with foreach.
A simple Array/List with all nodes and innerText as Value would be awesome.
Is this possible? If yes.. how ?
The structure of my XML is like this ->
<?xml version="1.0" encoding="UTF-8"?>
<city>
...
<credit>
...
</credit>
<forecast>
<date value="2013-11-08">
...
<time value="06:00">
...
</time>
<time value="11:00">
...
</time>
<time value="17:00">
...
</time>
<time value="23:00">
...
</time>
...
</date>
<date value="2013-11-09">
<same content here>
</date>
<date value="2013-11-09">
<same content here>
</date>
</forecast>
</city>
as you can see... there's a lot of information in the XML and I need nearly everything. In Actionscript I would realize it with a XMLList and make 3 Lists of the date Tags with content, so i can use
xmllist1.time[0] - xmllist1.time[3]
xmllist2.time[0] - xmllist2.time[3]
xmllist3.time[0] - xmllist3.time[3]
to get my data.
And now i want this XMLList in C#... I hope it's possible...Thx 4 help

If I understand you correctly, you want to parse the list of "city" items from the xml.
I do something similar using XDocument and Linq like this and it should work for you:
XDocument xdoc = <add your code to get xml from url>;
var ns = xdoc.Root.GetDefaultNamespace();
var cityList = from query in xdoc.Descendants(ns + "city")
select new CityItem
{
Date = (string)query.Element(ns + "date").Attribute("value").Value,
Time = (string)query.Element(ns + "time").Attribute("value").Value
};
public class CityItem
{
public string Date {get;set;}
public string Time {get;set;}
}

Related

How to get enclosure url with XElement C# Console

I read multiple feed from many sources with C# Console, and i have this code where i load XML From sources:
XmlDocument doc = new XmlDocument();
doc.Load(sourceURLX);
XElement xdoc = XElement.Load(sourceURLX);
How to get enclosure url and show as variable?
If I understand your question correctly (I'm making a big assumption here) - you want to select an attribute from the root (or 'enclosing') tag, named 'url'?
You can make use of XPath queries here. Consider the following XML:
<?xml version="1.0" encoding="utf-8"?>
<root url='google.com'>
<inner />
</root>
You could use the following code to retrieve 'google.com':
String query = "/root[1]/#url";
XmlDocument doc = new XmlDocument();
doc.Load(sourceURLX);
String value = doc.SelectSingleNode(query).InnerText;
Further information about XPath syntax can be found here.
Edit: As you stated in your comment, you are working with the following XML:
<item>
<description>
</description>
<enclosure url="blablabla.com/img.jpg" />
</item>
Therefore, you can retrieve the url using the following XPath query:
/item[1]/enclosure[1]/#url
With xml like below
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
<channel>
<title>title</title>
<link>https://www.link.com</link>
<description>description</description>
<item>
<title>RSS</title>
<link>https://www.link.com/xml/xml_rss.asp</link>
<description>description</description>
<enclosure url="https://www.link.com/media/test.wmv"
length="10000"
type="video/wmv"/>
</item>
</channel>
</rss>
You will get url by reading attribute
var document = XDocument.Load(sourceURLX);
var url = document.Root
.Element("channel")
.Element("item")
.Element("enclosure")
.Attribute("url")
.Value;
To get multiple urls
var urls = document.Descendants("item")
.Select(item => item.Element("enclosure").Attribute("url").Value)
.ToList();
Using foreach loop
foreach (var item in document.Descendants("item"))
{
var title = item.Element("title").Value;
var link = item.Element("link").Value;
var description = item.Element("description").Value;
var url = item.Element("enclosure").Attribute("url").Value;
// save values to database
}

Read a specific string from an xml file c#

Hi i need to extract a specific string form my xml file. How can i go about this? i have searched the internet but cant find an answer specific enough for me to understand. ^^
I want to get my SavePath string using the corresponding GameName
heres my xml file
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Game>
<entry>
<GameName>test</GameName>
<SavePath>C:\Users\allen\Downloads\GameOfLife\GameOfLife\obj\Debug\CoreCompileInputs.cache</SavePath>
<ExePath>C:\Users\allen\Downloads\GameOfLife\GameOfLife\obj\Debug\GameOfLife.exe</ExePath>
</entry>
<entry>
<GameName>test2</GameName>
<SavePath>C:\Users\allen\Downloads\GameOfLife\GameOfLife\obj\Debug\TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs</SavePath>
<ExePath>C:\Users\allen\Downloads\AdobeAIRInstaller.exe</ExePath>
</entry>
</Game>
and here's the code I've been trying to use
var xmlStr = File.ReadAllText(Properties.Resources.docname);
var str = XElement.Parse(xmlStr);
var result = str.Elements("entry")
.Where(x => x.Element("GameName").Value.Equals(SelectGame_Combobox.Text))
.Descendants("SavePath")
.ToString();
You are almost there. Just get rid of ToString() so it returns a collection of XElement (just one, of course), and then you can get it like this:
var result = str.Elements("entry").
Where(x => x.Element("GameName").Value.Equals(search)).Descendants("SavePath");
string value = result.First().Value;

How to query XElement with two namespaces

I'm trying to find the inner text value of an element using LINQ-to-XML (an XElement object). I make my service call and get an XML response back that I've successfully loaded into an XElement object. I want to extract the inner text of one of the elements - however, every time I try to do this, I get a null result.
I feel like I'm missing something super-simple, but I'm fairly new to LINQ-to-XML. Any help is appreciated.
I'm trying to get the inner text value of the StatusInfo/Status element. Here's my XML document that's returned:
<feed xml:lang="en-us" xmlns="http://www.w3.org/2005/Atom">
<title type="text">My Response</title>
<id>tag:foo.com,2012:/bar/06468dfc-32f7-4650-b765-608f2b852f22</id>
<author>
<name>My Web Services</name>
</author>
<link rel="self" type="application/atom+xml" href="http://myServer/service.svc/myPath" />
<generator uri="http://myServer" version="1">My Web Services</generator>
<entry>
<id>tag:foo.com,2012:/my-web-services</id>
<title type="text" />
<updated>2012-06-27T14:22:42Z</updated>
<category term="tag:foo.com,2008/my/schemas#system" scheme="tag:foo.com,2008/my/schemas#type" />
<content type="application/vnd.my.webservices+xml">
<StatusInfo xmlns="tag:foo.com,2008:/my/data">
<Status>Available</Status> <!-- I want the inner text -->
</StatusInfo>
</content>
</entry>
</feed>
Here's a snippet of code that I'm using to extract the value (which doesn't work):
XElement root = XElement.Load(responseReader);
XNamespace tag = "tag:foo.com,2008:/my/data";
var status = (from s in root.Elements(tag + "Status")
select s).FirstOrDefault();
My status variable is always null. I've tried several variations on this, but to no avail. The part that's confusing me is the namespace -- tag and 2008 are defined. I don't know if I'm handling this correctly or if there's a better way to deal with this.
Also, I don't have control over the XML schema or the structure of the XML. The service I'm using is out of my control.
Thanks for any help!
Try Descendants() instead of Elements():
XElement x = XElement.Load(responseReader);
XNamespace ns = "tag:foo.com,2008:/my/data";
var status = x.Descendants(ns + "Status").FirstOrDefault().Value;
There are 2 Namespaces in the feed:
the Atom namespace
the tag namespace
The outer xml needs to use the Atom namespace, while a portion of the inner xml needs to use the tag namespace. i.e.,
var doc = XDocument.Load(responseReader);
XNamespace nsAtom = "http://www.w3.org/2005/Atom";
XNamespace nsTag = "tag:foo.com,2008:/my/data";
// get all entry nodes / use the atom namespace
var entry = doc.Root.Elements(nsAtom + "entry");
// get all StatusInfo elements / use the atom namespace
var statusInfo = entry.Descendants(nsTag + "StatusInfo");
// get all Status / use the tag namespace
var status = statusInfo.Elements(nsTag + "Status");
// get value of all Status
var values = status.Select(x => x.Value.ToString()).ToList();

Load info from xml, save related (changed) info using c#

Friends,
My school project is having an xml data file:
<patients>
<patient>
<regNo>2012/Mar/003</regNo>
<name>Jhon</name>
<add>Somewhere</add>
<mobile>0000</mobile>
.
.
.
<stay>2</stay>
<costofroom>100</costofroom>
<total>200</total>
</patient>
</patients>
My Windowsform "EditPatients_Load" is able to fetch all info of patient Jhon, and now let's assume that the Admin needs to change some information in the form & resubmit.
Then how to write back all values to Jhon's account in the same xml
file????
I'm not able to makeup the logical code, even if I check the node if (patients.paptient.name = "nameComboBox.text").... how to make sure that I'm writing other values on proper place?
Rgrdz,
Try this:
//string xml =
//#"<patients><patient><regNo>2012/Mar/003</regNo><name>Jhon</name><add>Somewhere
//</add><mobile>0000</mobile><stay>2</stay><costofroom>100</costofroom><total>200</total>
//</patient></patients>";
XDocument xmlDoc = XDocument.Load(#"c:\abc.xml");
var items = (from item in xmlDoc.Descendants("patient")
where item.Element("name").Value == "Jhon"
select item);
if (items.Count() > 0)
{
var item = items.First();
item.SetElementValue("add", "New New Address");
xmlDoc.Save(#"c:\abc.xml", SaveOptions.None);
}
You can get single element using
var item = (from item in xmlDoc.Descendants("patient")
where item.Element("name").Value == "Jhon"
select item).FirstOrDefault();
then update it using SetElementValue() method.
//Updated Xml
<?xml version="1.0" encoding="utf-8"?>
<patients>
<patient>
<regNo>2012/Mar/003</regNo>
<name>Jhon</name>
<add>New Address</add>
<mobile>0000</mobile>
<stay>2</stay>
<costofroom>100</costofroom>
<total>200</total>
</patient>
</patients>
Reference:
Update XML with C# using Linq
I would take the xml serialization/deserialization route to solve this:
http://support.microsoft.com/kb/815813
How to Deserialize XML document
That way you can work with objects and not have to parse xml files manually.
If you're using .NET 3.5 onward you can use the XDocument class like the following. I'm assuming your content is in a .xml file.
XDocument xdoc = XDocument.Load(#"C:\Tmp\test.xml");
//this would ensure you get the right node and set its text content/value
xdoc.Element("patients")
.Element("patient").Element("add").Value = "some new address?";
xdoc.Save(#"C:\Tmp\test.xml");
The file test.xml would change to:
<patients>
<patient>
<regNo>2012/Mar/003</regNo>
<name>Jhon</name>
<add>some new address?</add>
<mobile>0000</mobile>
<stay>2</stay>
<costofroom>100</costofroom>
<total>200</total>
</patient>
</patients>

Linq To Xml problems using XElement's method Elements(XName)

I have a problem using Linq To Xml.
A simple code. I have this XML:
<?xml version="1.0" encoding="utf-8" ?>
<data xmlns="http://www.example.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.com/directory file.xsd">
<contact>
<name>aaa</name>
<email>email#email.ext</email>
<birthdate>2002-09-22</birthdate>
<telephone>000:000000</telephone>
<description>Description for this contact</description>
</contact>
<contact>
<name>sss</name>
<email>email#email.ext</email>
<birthdate>2002-09-22</birthdate>
<telephone>000:000000</telephone>
<description>Description for this contact</description>
</contact>
<contact>
<name>bbb</name>
<email>email#email.ext</email>
<birthdate>2002-09-22</birthdate>
<telephone>000:000000</telephone>
<description>Description for this contact</description>
</contact>
<contact>
<name>ccc</name>
<email>email#email.ext</email>
<birthdate>2002-09-22</birthdate>
<telephone>000:000000</telephone>
<description>Description for this contact</description>
</contact>
I want to get every contact mapping it on an object Contact. To do this I use this fragment of code:
XDocument XDoc = XDocument.Load(System.Web.HttpRuntime.AppDomainAppPath + this.filesource);
XElement XRoot = XDoc.Root;
//XElement XEl = XElement.Load(this.filesource);
var results = from e in XRoot.Elements("contact")
select new Contact((string)e.Element("name"), (string)e.Element("email"), "1-1-1", null, null);
List<Contact> cntcts = new List<Contact>();
foreach (Contact cntct in results) {
cntcts.Add(cntct);
}
Contact[] c = cntcts.ToArray();
// Encapsulating element
Elements<Contact> final = new Elements<Contact>(c);
Ok just don't mind that all: focus on this:
When I get the root node, it is all right, I get it correctly.
When I use the select directive I try to get every node saying: from e in
XRoot.Elements("contact")
OK here's the problem: if I use: from e in XRoot.Elements() I get all contact nodes, but if I use: from e in XRoot.Elements("contact") I GET NOTHING: Empty SET.
OK you tell me: Use the other one: OK I DO SO, let's use:
from e in XRoot.Elements(), I get all nodes anyway, THAT's RIGHT BUT HERE COMES THE OTHER PROBLEM:
When Saying: select new Contact((string)e.Element("name"), (string)e.Element("email"), "1-1-1", null, null); I Try to access <name>, <email>... I HAVE TO USE .Element("name") AND IT DOES NOT WORK TOO!!!!!!!!WHAT THE HELL IS THIS????????????? IT SEEMS THAT I DOES NOT MATCH THE NAME I PASS But how is it possible. I know that Elements() function takes, overloaded, one argument that is an XName which is mapped onto a string. Please consider that the code I wrote come from an example, It should work.
Pretty easy: there's a XML namespace in play, which you're ignoring:
<data xmlns="http://www.example.com"
**************************
You need to add that to your Linq-to-XML queries!
Something like:
XNamespace ns = "http://www.example.com";
and then
XRoot.Elements(ns + "contact")
and of course, also use the XML namespace when accessing the child elements:
var results = from e in XRoot.Elements("contact")
select new Contact(e.Element(ns + "name").Value,
e.Element(ns + "email").Value,
"1-1-1", null, null);
That should help. See the MSDN docs on Working with XML Namespaces for more details.
For me I solved it like that because I didn't had a namespace in my XML:
xmldoc.Root.Elements("contact");
I forgot to use the "Root" method.

Categories

Resources