C# and LINQ.XML Select from XML - c#

I've been struggling to find out how to select multiple values from an XML file, compare them to a special value and then do something. So far I just managed to select a single value but I also need a different one in the same select, I hope you can assist me
XML Structure
<?xml version="1.0" encoding="utf-8"?>
<userConnectionSettings version="1" lastApplicationUrl="xxx" lastIdentity="yyy">
<application url="xxx" lastFolderId="zzz">
<user name="test" domain="domain.tld" lastFolderId="yyy" />
</application>
</userConnectionSettings>
Now basically, what i want to do is read the lastApplicationURL and the domain value. I managed to do the lastApplicationURL but i can't seem to select the domain and i don't know how to get that value properly. Here's my code :
XDocument foDoc = XDocument.Load(FrontOfficePath);
foreach (var FOurl in foDoc.Descendants("userConnectionSettings"))
{
string FOappURL = (string)FOurl.Attribute("lastApplicationUrl");
if (FOappURL == "something")
{
TODO
}
else
{
TODO
}
}

You can select domain attribute, in two different ways :
1 - Like #Juharr comment :
foreach (var FOurl in foDoc.Descendants("userConnectionSettings"))
{
string domain = FOurl
.Element("application")
.Element("user")
.Attribute("domain")
.Value;
....
}
Or, by getting descendant of application and select the first item, like :
foreach (var FOurl in foDoc.Descendants("userConnectionSettings"))
{
string domain = FOurl.Descendants("application")
.Select(x => x.Element("user").Attribute("domain").Value)
.FirstOrDefault();
....
}
i hope you find this helpful.

Try following :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
List<Application> applications = doc.Descendants("application").Select(x => new Application()
{
url = (string)x.Attribute("url"),
id = (string)x.Attribute("lastFolderId"),
name = (string)x.Element("user").Attribute("name"),
domain = (string)x.Element("user").Attribute("domain"),
folder = (string)x.Element("user").Attribute("lastFolderId")
}).ToList();
}
}
public class Application
{
public string url { get; set; }
public string id { get; set; }
public string name { get; set; }
public string domain { get; set; }
public string folder { get; set; }
}
}

Related

How to Mapping Deserialize XML document using c#

i am new to c # programming and i m stuck in how ot Deserialize this XML document, i have seen this tutorial How to Deserialize XML document and it was helpful but as you can see my XML contains more informations and he is more complex :
<?xml version="1.0" encoding="utf-8"?>
<Classrooms>
<Classroom name="ClassroomA">
<Students name = "John"/>
<Students name = "Bryan"/>
<Students name = "Eva"/>
</Classroom>
<Classroom name="ClassroomB">
<Students name = "Harry"/>
<Students name = "Emma"/>
<Students name = "Joe"/>
</Classroom>
<Classroom name="ClassroomC">
<Students name = "Lionnel"/>
<Students name = "Rio"/>
<Students name = "Eva"/>
</Classroom>
</Classrooms>
My main goal is to create a Map of classrooms from my XML file :
example : Dictionnary<string,List> classrooms ,
Key 1 : classroomA, Values : John,Bryan,Eva
Key 2 : classroomB, Values : Harry,Emma,Joe
Key 3 : classroomC, Values : Lionnel,Rio,Eva
Thanks for help
Try following :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.Xml.Linq;
namespace ConsoleApplication178
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XmlReader reader = XmlReader.Create(FILENAME);
XmlSerializer serializer = new XmlSerializer(typeof(Classrooms));
Classrooms classrooms = (Classrooms)serializer.Deserialize(reader);
reader.Close();
//using xml linq
XDocument doc = XDocument.Load(FILENAME);
Dictionary<string, List<string>> dict = doc.Descendants("Classroom")
.GroupBy(x => (string)x.Attribute("name"), y => y)
.ToDictionary(x => x.Key, y => y.Elements("Students").Select(x => (string)x.Attribute("name")).ToList());
}
}
public class Classrooms
{
[XmlElement()]
public List<Classroom> Classroom { get; set; }
}
public class Classroom
{
[XmlAttribute]
public string name { get; set; }
[XmlElement()]
public List<Students> Students { get; set; }
}
public class Students
{
[XmlAttribute]
public string name { get; set; }
}
}

Remove unnecessary nesting when deserializing XML or access data in parent node?

The XML I'm attempting to deserialize has a lot of fields that have the data nested in a subfield and I'd like to assign this data into the parent property on the class rather than create additional unneeded structure.
<?xml version="1.0" encoding="UTF-8"?>
<x:EventRecord eventid="EVR-1000">
<x:Postcode>
<x:ID>ABC123</x:ID>
</x:Postcode>
</x:EventRecord>
I've created an EventRecord class with a Postcode string property:
public class EventRecord
{
public string EventID { get; set; }
public string Postcode { get; set; }
}
Is there an attribute that can decorate the property that can tell the deserializer to take the value out of the nested ID field? There will never be any other fields in <x:Postcode> aside from <x:ID>.
Also is there a way to assign the eventid XML attribute on the parent x:EventRecord node to the EventID property inside itself?
Using following xml :
<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:x="abc">
<x:EventRecord eventid="EVR-1000">
<x:Postcode>
<x:ID>ABC123</x:ID>
</x:Postcode>
</x:EventRecord>
</root>
Code :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication16
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
XNamespace ns = doc.Root.GetNamespaceOfPrefix("x");
EventRecord record = doc.Descendants(ns + "EventRecord").Select(x => new EventRecord() {
EventID = (string)x.Attribute("eventid"),
Postcode = (string)x.Descendants(ns + "ID").FirstOrDefault()
}).FirstOrDefault();
}
}
public class EventRecord
{
public string EventID { get; set; }
public string Postcode { get; set; }
}
}

Error when get data from xml file

I have profile.xml file in my web folder:
<?xml version="1.0" encoding="utf-8"?>
<myXML>
<RealName>Nguyen Van A</RealName>
<Email>vyclarks#gmail.com</Email>
<Phone>2165421</Phone>
<Address>Ho Chi Minh</Address>
<Link1>dtvt</Link1>
<Link2></Link2>
<Link3></Link3>
</myXML>
As recommended, I get data from that file by code below:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml.Linq;
public class profile
{
public string realname { get; set; }
public string email { get; set; }
public string phone { get; set; }
public string address { get; set; }
public string link1 { get; set; }
public string link2 { get; set; }
public string link3 { get; set; }
}
public void getProfile()
{
string path = this.Server.MapPath("~/Lecturer/");
string targetPath = path + #"\"+username+"\\profile.xml";
bool isExists = System.IO.Directory.Exists(targetPath);
if(isExists)
{
List<profile> profiles = (
from e in XDocument.Load(targetPath)
.Root.Element("myXML")
select new profile
{
realname = (string) e.Element("RealName"),
email = (string) e.Element("Email"),
phone = (string) e.Element("Phone"),
address = (string) e.Element("Address"),
link1 = (string) e.Element("Link1"),
link2 = (string) e.Element("Link2"),
link3 = (string) e.Element("Link3")
}
).ToList();
}
...//code to get list value...
}
But it has an error: Cannot resolve symbol "select"
Is there any better way to get data from profile.xml file???
There is an error in your from e in ... statement.
XDocument.Load(targetPath).Root.Element("myXML") returns only one XML element for you. So you can't do linq query against a single object (don't mix with the collections containing only one object).
To get it working you need to change Element method to Elements:
from e in XDocument.Load(targetPath).Root.Elements("myXML")
select new profile
{
realname = (string) e.Element("RealName"),
email = (string) e.Element("Email"),
phone = (string) e.Element("Phone"),
address = (string) e.Element("Address"),
link1 = (string) e.Element("Link1"),
link2 = (string) e.Element("Link2"),
link3 = (string) e.Element("Link3")
}
Update
If you have only one myXML node in XML file (since it's a root node in your example) then you don't need linq query at all. Try to read data from the XML in a next way:
var prof = XDocument.Load(targetPath).Root;
var p = new profile()
{
realname = prof.Element("RealName").Value,
email = prof.Element("Email").Value,
phone = prof.Element("Phone").Value,
address = prof.Element("Address").Value,
link1 = prof.Element("Link1").Value,
link2 = prof.Element("Link2").Value,
link3 = prof.Element("Link3").Value
}
I've tested it with XML from your sample

How to loop through a set of XElements?

http://www.dreamincode.net/forums/xml.php?showuser=335389
Given the XML above, how can I iterate through each element inside of the 'lastvisitors' element, given that each child group is the same with just different values?
//Load latest visitors.
var visitorXML = xml.Element("ipb").Element("profile").Element("latestvisitors");
So now I have captured the XElement containing everything I need. Is there a way to loop through the elements to get what I need?
I have this POCO object called Visitor whose only purpose is to hold the necesary information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SharpDIC.Entities
{
public class Visitor
{
public string ID { get; set; }
public string Name { get; set; }
public string Url { get; set; }
public string Photo { get; set; }
public string Visited { get; set; }
}
}
Thanks again for the help.
You can probably just do something like this in Linq:
XDocument xml = XDocument.Parse(xmlString);
var visitors = (from visitor in xml.Descendants("latestvisitors").Descendants("user")
select new Visitor() {
ID = visitor.Element("id").Value,
Name = visitor.Element("name").Value,
Url = visitor.Element("url").Value,
Photo = visitor.Element("photo").Value,
Visited = visitor.Element("visited").Value
});
The only caveat here is that I didn't do any null checking.
Just do a linq query to select all the elements as your object.
var visitors = (from v in xml.Element("ipb").Element("profile")
.Element("latestvisitors").Elements()
select new Visitor {
ID = (string)v.Element("id"),
Name = (string)v.Element("name"),
}).ToList();

LINQ XML Read different hierarchies into 1 object

I have an XML file
<searchResponse requestID=“500” status=“success”>
<pso>
<psoID ID=“770e8400-e29b-41d4-a716-446655448549”
targetID=“mezeoAccount”/>
<data>
<email>user2#example.net</email>
<quotaMeg>100</quotaMeg>
<quotaUsed>23</quotaUsed>
<realm>Mezeo</realm>
<path>/san1/</path>
<billing>user2</billing>
<active>true</active>
<unlocked>true</unlocked>
<allowPublic>true</allowPublic>
<bandwidthQuota>1000000000</bandwidthQuota>
<billingDay>1</billingDay>
</data>
</pso>
</searchRequest>
and I want to extract the data into a single business object. Am I better to go
MezeoAccount mcspAccount = new MezeoAccount();
mcspAccount.PsoID = doc.Element("psoID").Attribute("ID").Value;
mcspAccount.Email = doc.Element("email").Value;
...
or build a list even though I know there is only 1 record in the file?
var psoQuery = from pso in doc.Descendants("data")
select new MezeoAccount {
PsoID = pso.Parent.Element("psoID").Attribute("ID").Value,
Email = pso.Element("email").Value,
... };
What would people suggest would be the more correct way, or a better way even, if I missed something.
If you know that your xml only will contain one record of the data in mind you shouldn't create a list for it. So your first example looks fine.
A pattern I personally use is something like this:
public class MezeoAccount
{
public string PsoID { get; set; }
public string Email { get; set; }
public static MezeoAccount CreateFromXml(XmlDocument xml)
{
return new MezeoAccount()
{
PsoID = xml.Element("psoID").Attribute("ID").Value,
Email = doc.Element("email").Value;
};
}
}
//Usage
var mezeoAccount = MezeoAccount.CreateFromXml(xml);
It looks like you didn't get a working answer to this question. Assuming that there can only be one account in the XML file, I would do it like this:
using System;
using System.Linq;
using System.Xml.Linq;
public class MezeoAccount
{
public string PsoId { get; set; }
public string Email { get; set; }
public int QuotaMeg { get; set; }
// Other properties...
}
public class Program
{
public static void Main()
{
XDocument doc = XDocument.Load("input.xml");
XElement pso = doc.Element("searchResponse").Element("pso");
XElement data = pso.Element("data");
MezeoAccount x = new MezeoAccount
{
PsoId = pso.Element("psoID").Attribute("ID").Value,
Email = data.Element("email").Value,
QuotaMeg = int.Parse(data.Element("quotaMeg").Value),
// Other properties...
};
}
}

Categories