Hi Guys
I would like to parse the following xml string in C#
i tried reading the entire string into the dataset and then using it .. there are simply no tables in the dataset.
here is the xml that I am interested to parse.
xml code is here
http://pastebin.com/VfT2wAwY
C# code is here
http://pastebin.com/iwqDK2S6
Thanks and regards,
Gagan Janjua
Have you considered LINQ to XML? If you're using .NET Framework 3.5 or later, then LINQ can save you a lot of time.
I haven't tested this, but you could do something like:
XDocument doc = XDocument.Load(#"C:\mydocument.xml");
var allCases = doc.Element("response").Element("cases").Descendants("case");
foreach (var currentCase in allCases) {
// I can now access each case specifically
var allEvents = currentCase.Descendants("events");
foreach (var currentEvent in allEvents) {
// now I can access each event
int ixBugEvent = (int)currentEvent.Element("ixBugEvent");
// etc...
}
}
Are you aware of XmlReader from System.Xml?
There is no schema in XML that you have provided, so you cannot expect that you can use it to populate DataSet... Unless you define your own schema, that is.
Your code is returning null because of your catch is making it null. It hits the catch, with the following error:
Column name 'ixBugEvent' is defined for different mapping types.
I have the impression that the reason for it is that you have ixBugEvent as both an attribute and a element
<event ixBugEvent='3' ixBug='2'>
<ixBugEvent>3</ixBugEvent>
Removing one of them fix the issue. The code is working, but your xml schema cannot be translated to a dataset.
You can change Scott's code to make it work by changing the following line of code:
// I can now access each case specifically
var allEvents = currentCase.Descendants("events");
Make it:
// I can now access each case specifically
var allEvents = currentCase.Descendants("event");
Doing that you have access to each event element. And from there you can definitely have access to ixBugEvent element.
I hope this helps.
P.s.: Sorry to make this another answer, but I would like to highlight the code, and it seems the only way to do it...
Related
In my application there is an issue part that allows questions and responses. Something like (Pseudo code, as this is actually generated from Entity Framework):
class Response
{
string Author;
string Comment;
DateTime Date;
}
class Issue
{
IEnumerable<Response> Responses;
}
We have a summary page where we just want to show the last two responses. I tried a linq query like this:
from issue in db.Issue
let responses = from response in issue.Responses orderby response.Date
select new
{
Issue = issue,
Question = responses.FirstOrDefault(),
Answer = responses.Skip(1).FirstOrDefault()
}
But this gives me the error that Skip can only be used on ordered collections. I checked responses and it was an IOrderedEnummerable. I thought maybe the problem was that it was Enumerable instead of IOrderedQueryable, and saw that this happened because issue.Response is a collection so I switched the let statement to be:
let response = from response in db.Responses where response.IssueId = issue.ID // etc.
but this did not resolve the issue (but response did become an IOrderedQueryable) so I'm not really sure why entity won't accept the skip here. If I put the skip in the let statement, it works without problem (but then I can't get the first response). The issue seams to only occur by trying to put a portion of this statement in a variable before using it.
The problem here is: how will/should EF translate your query into a SQL statement? There is no straightforward SQL equivalent of Skip(1). Just try to write your query in SQL and you should see what I mean.
If you want an "easy" solution, then just get all responses from the DB and identify the ones you need in code.
If you want to minimize the data being read from the DB, the solutions might range from creating a view to writing a stored procedure to changing your tables so that your tables better reflect the data model in the application.
I'm not quite sure what's going on here, but wouldn't this be maybe a little simpler:
var theResponse = db.Issue.Select(i => new {
Issue = i,
Question = i.Responses.FirstOrDefault(),
Answer = i.Responses.OrderBy(r => r.Date).Skip(1).FirstOrDefault()
});
But this is also weird, because you are getting a full Issue object with all of its properties and whatnot, including the Reponse objects and stuffing it back into an Issue property of your dynamic type beside all of the Response objects...
I have been trying to deserialize the InnerXML into a class and for some reason the XML keeps changing shape and however many times I try to get the class right it seems to change shape again.
So I have given up and decided to try another method.
Is it possible to retrieve the value of a parameter within the InnerXML manually using c#?
Say for example, my XML innerXML looked like this:
<Timestamp>2014-08-22T21:45:00Z</Timestamp>
<Subscriber>https://www.dogdoza.co.uk</Subscriber>
<Order>
<OrderID>111867</OrderID>
<InvoiceNumber>DOZA-9725410</InvoiceNumber>
<CustomerID>4542</CustomerID>
Is it possible to pull out say the value of Subscriber
If this is possible I can just pull out the values I want manually. Not ideal, but there are only about 10...
I have looked around but not managed to find any code I can get working..
Can anyone please give me any guidance?
Thanks
You can do achieve what you want using LINQ to XML:
XElement myXml = XElement.Load(#"XmlLocationHere");
XElement subscriber = myXml.Descendants("Subscriber").FirstOrDefault();
XElement.Descendants returns a collection of the descendant elements for this document or element, in document order. This method will return an IEnumerable<XElement>, since there might be more than one "Subscriber" element, but in your case, we choose FirstOrDefault, which returns the first occurrence.
Try loading your XML into an XDocument. Then try to use XPathSelectElement to find the specific value you want.
It could be that you need to wrap your inner xml into a root element, because it doesn't accept multiple roots.
Pseudo example:
// set up your xml document
string xml = "<rootelement>" + myInnerXml + "</rootelement>";
XDocument doc = new XDocument();
doc.Parse(xml);
XElement subscriber = doc.XPathSelectElement("/rootelement/Subscriber");
string value = subscriber.Value;
I am trying to write a simple Linq to Xml query to extract the serverOpen and onlinePlayers values into my class which has two properties ServerStatus and Players respectively.
The xml I'm dealing with is of this simple form:
<eveapi version="2">
<currentTime>2013-02-10 05:27:33</currentTime>
<result>
<serverOpen>True</serverOpen>
<onlinePlayers>32723</onlinePlayers>
</result>
<cachedUntil>2013-02-10 05:28:39</cachedUntil>
</eveapi>
I feel like this should be a very trivial solution. There is only ever one result in the XML and I want to be able to query it out very simply.
I've tried things like (Results is my xml in a XDocument):
var result = Results.Elements().Elements().First(); //successfully gets result
ServerStatus = result.Element("serverOpen").Value; //this doesn't work
//null reference exception with .Value
Also a few other queries that all return IEnumerables and I have never been able to successfully extract the values.
Thanks.
It would be a bit easier to use xpath here instead, particularly if there isn't a result.
var serverStatus = (bool?)doc.XPathSelectElement("/eveapi/result/serverOpen");
var onlinePlayers = (int?)doc.XPathSelectElement("/eveapi/result/onlinePlayers");
Well, I was able to use an overlooked XDocument method Single() to get just the single result XElement. Then use Element() to extract the correct XElements from the result XElement.
var result = Results.Descendants("result").Single();
ServerStatus = result.Element("serverOpen").Value;
If there is a better way or another flashy way please submit your own suggestion.
Thanks.
I am not completely sure, but if I understand Linq correctly, you already have your object.
Instead of:
ServerStatus = result.Element("serverOpen").Value;
do:
ServerStatus = result.Value;
Hope this helps.
using xmltextreader, how would I load a hashtable.
XML:
<base><user name="john">2342343</user><user name="mark">239099393</user></base>
This was asked before but it was using some funky linq that I am not fully comfortable with just yet.
Well, the LINQ to XML solution is really easy, so I suggest we try to make you comfortable with that instead of creating a more complex solution. Here's the code, with plenty of explanation...
// Load the whole document into memory, as an element
XElement root = XElement.Load(xmlReader);
// Get a sequence of users
IEnumerable<XElement> users = root.Elements("user");
// Convert this sequence to a dictionary...
Dictionary<string, string> userMap = users.ToDictionary(
element => element.Attribute("name").Value, // Key selector
element => element.Value); // Value selector
Of course you could do this all in one go - and I'd probably combine the second and third statements. But that's about as conceptually simple as it's likely to get. It would become more complicated if you wanted to put error handling around the possibility that a user element might not have a name, admittedly. (This code will throw a NullReferenceException in that case.)
Note that this assumes you want the name as the key and id as value. If you want the hashtable the other way round, just switch the order of the lambda expressions.
I am new with learning the possibilities of Linq to XML and I recently have found that I can query an xml like a data base (I am quite fascinated by it now).
My question is How can I query an xml file and save the result in another xml file?:
string url = "employees.xml";
XElement employees= XElement.Load(url);
if (employees.Element("employee") != null)
{
var query = from f in employees.Element("employee").Elements("item").Take(10)
select new { Name = f.Element("name").Value, Surname= f.Element("surname").Value };
foreach (var feed in query)
{
//here... I like to write the result in a different xml file, I tried the
//common
doc.save("xmlout.xml");
}
}
Thanks a lot for your help,
Well, you could do this by creating an XDocument/XElement instance and then populating it with the results of your query (by passing the query to the constructor of the XDocument/XElement), and then saving that.
However, you might want to consider using an XSLT transformation instead, as that is really what you are trying to do here.
This article should help you solve your problem. Btw if you new up as XElement and then populate you can use the save method, instead of using anonymous types.