Using Linq to get XML data from database - c#

I'm struggling to get the values of a single xml node using Linq.
Here is my XML.
<?xml version="1.0" encoding="utf-8"?>
<record>
<AddressLine1>abcd street</AddressLine1>
<AddressLine2>xyz AVE</AddressLine2>
<AddressCity>Illinois</AddressCity>
<AddressState>Chicago</AddressState>
<AddressZip>23434</AddressZip>
</record>
And here is my c# code
XElement xmlDoc = XElement.Parse(varQ.Content);
//When I debug I find that xmlDoc contains the XML. So that is alright.
var q = (from lpi in xmlDoc.Descendants("record")
select new { AddressLine1 = lpi.Element("AddressLine1").Value,
AddressLine2 = lpi.Element("AddressLine2").Value,
AddressCity = lpi.Element("AddressCity").Value,
AddressCountry = lpi.Element("AddressCountry").Value,
AddressState = lpi.Element("AddressState").Value,
AddressZip = lpi.Element("AddressZip").Value,
}).FirstOrDefault();
var q shows null. Can u please help me find out what is wrong here?

Replace Descendants on DescendantsAndSelf:
string xml = #"<?xml version=""1.0"" encoding=""utf-8""?>
<record>
<AddressLine1>abcd street</AddressLine1>
<AddressLine2>xyz AVE</AddressLine2>
<AddressCity>Illinois</AddressCity>
<AddressState>Chicago</AddressState>
<AddressZip>23434</AddressZip>
</record>";
XElement xmlDoc = XElement.Parse(xml);
var q = (from lpi in xmlDoc.DescendantsAndSelf("record")
select new
{
AddressLine1 = (string)lpi.Element("AddressLine1"),
AddressLine2 = (string)lpi.Element("AddressLine2"),
AddressCity = (string)lpi.Element("AddressCity"),
AddressCountry = (string)lpi.Element("AddressCountry"),
AddressState = (string)lpi.Element("AddressState"),
AddressZip = (string)lpi.Element("AddressZip"),
}).FirstOrDefault();
Console.WriteLine(q);
Print:
{ AddressLine1 = abcd street, AddressLine2 = xyz AVE, AddressCity = Illinois, AddressCountry = , AddressState = Chicago, AddressZip = 23434 }
Link: https://dotnetfiddle.net/fXQivX

Related

Attempting to get single value from XDocument, nothing appears to work

I am just trying to get the value from MessageInfo.. Sender here is an excerpt of the xml. I just want the "Senders" value. I have tried many different things with XDocument, and wanted to use a Linq Query
I have tried,
var query1 = doc.Descendants("MessageInfo").Select(s => new MessageInfo
{
SYSGENID = s.Element("SysGenID").Value,
TIME_STAMP = s.Element("TimeStamp").Value,
SENDER = s.Element("Sender").Value,
RECEIVER = s.Element("Receiver").Value,
ENTITY_CODE = s.Element("EntityCode").Value
}).FirstOrDefault();
the query1 returns null. Following is example of xml
I also have tried
XDocument doc = XDocument.Load(filePath);
var messageInfo = doc.Root.Elements("MessageInfo");
var res = from m in messageInfo
select new
{
msgInfo = m.Element("MessageInfo").Value
};
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<PutSchedule xmlns="http://www.nwpp.org/eide">
<MessageInfo>
<SysGenID>4431</SysGenID>
<TimeStamp>2014-08-12T10:34:28.068000</TimeStamp>
<Sender>611</Sender>
<Receiver>WECC</Receiver>
<EntityCode>611</EntityCode>
</MessageInfo>
<Schedules>
<Schedule>
<ScheduleDescription>
<StartTime>2014-08-12T00:00:00</StartTime>
<EndTime>2014-08-15T00:00:00</EndTime>
<AccountCode>259S.NRGREEN_G1.BaseMW</AccountCode>
</ScheduleDescription>
<Quantities>
You have a namespace that you have to use.
XNamespace ns = "http://www.nwpp.org/eide";
var query1 = doc.Descendants(ns +"MessageInfo").Select(s => new MessageInfo
{
SYSGENID = s.Element(ns +"SysGenID").Value,
TIME_STAMP = s.Element(ns +"TimeStamp").Value,
SENDER = s.Element(ns +"Sender").Value,
RECEIVER = s.Element(ns +"Receiver").Value,
ENTITY_CODE = s.Element(ns +"EntityCode").Value
}).FirstOrDefault();

XML parsing with LINQ, has 2 tags with the same name but different level and not always has a value

I have the following XML:
<request>
<book>
<id>1833801</id>
<title>The Yiddish Policemen's Union </title>
<work>
<id>1234</id>
<name/>
</work>
<similar_books>
<book><id>243859</id><title>Stations of Tide</title> <isbn>0380817616</isbn>
<authors><author><id>14454</id><name>Michael Swanwick</name></author> </authors>
</book>
</similar_books>
<authors>
<author>
<id>2715</id><name>Michael Chabon</name>
<ratings_count>215884</ratings_count></author>
</authors>
<popular_shelves>
<shelf name="jewish" count="104"/><shelf name="sci-fi" count="100"/>
</popular_shelves>
</book>
</request>
I want to have all tags with their respective values, and I am using following code:
HttpWebRequest oReq = (HttpWebRequest)WebRequest.Create(uriRoot);
HttpWebResponse resp = (HttpWebResponse)oReq.GetResponse();
log.Info(" (ISBN= " + isbn10 + ") Http request has response.");
if (resp.ContentType.StartsWith("application/xml", StringComparison.InvariantCultureIgnoreCase))
{
Stream resultStreamISBN = resp.GetResponseStream();
Encoding encode = System.Text.Encoding.GetEncoding("utf-8"); //encoding for non-latin chars
StreamReader responseReader = new StreamReader(resultStreamISBN, encode);
XDocument xdoc = XDocument.Parse(responseReader.ReadToEnd());
var books = (from u in xdoc.Descendants().Elements("book")
select new
{
id = (string)u.Element("title"),
title = (string)u.Element("title"),
works = (from i in u.Elements("work")
select new
{
work_best_book_id = (int)i.Element("id"),
work_name = (string)i.Element("name"),
}).ToList(),
authors = (from i in u.Elements("authors").Elements("author")
select new
{
id = (int)i.Element("id"),
name = (string)i.Element("name"),
rating = (int)i.Element("rating_count")
}).ToList(),
popular_shelves = (from i in u.Elements("popular_shelves").Elements("shelf")
select new
{
name = (string)i.Attribute("name"),
count = (int)i.Attribute("count")
}).ToList(),
}).ToList();
The code returns null values and is not working properly. I also should note that different xml files may not have values for all the tags.
Any suggestions on how I can improve my code?
Check for missing elements like such:
name = i.Element("name") == null ? null : i.Element("name")
For value types, you make have to change them to nullable types for this to work correctly.
You can transform
id = (int)i.Element("id"),
to
id = (int?)i.Element("id"),
Whole modified code
// I am inserting the following line to demonstrate how I load the XML in test code
// Basically, I copied & pasted xml in a file OP gave named request.xml
//XDocument xdoc = XDocument.Load( #"d:\Data\request.xml");
EDIT
XDocument xdoc = XDocument.Load("http://www.goodreads.com/book/isbn?isbn=0007295685&key=lbScLXWyNGQ1q0BDoFFSg");
var books = (from u in xdoc.Descendants().Elements("book")
select new
{
id = (string)u.Element("title"),
title = (string)u.Element("title"),
works = (from i in u.Elements("work")
select new
{
work_best_book_id = (int?)i.Element("id"),
work_name = (string)i.Element("name"),
}).ToList(),
authors = (from i in u.Elements("authors").Elements("author")
select new
{
id = (int?)i.Element("id"),
name = (string)i.Element("name"),
rating = (int?)i.Element("rating_count")
}).ToList(),
popular_shelves = (from i in u.Elements("popular_shelves").Elements("shelf")
select new
{
name = (string)i.Attribute("name"),
count = (int?)i.Attribute("count")
}).ToList(),
}).ToList();

read xml with same elements name

I have xml in format below:
<?xml version="1.0" encoding="UTF-8" standalone="true"?>
-<draw><drawNo>381555</drawNo>
<drawTime>2013-04-29T19:55:00+03:00</drawTime>
<result>8</result>
<result>10</result>
<result>13</result>
<result>15</result>
<result>20</result>
<result>21</result>
<result>22</result>
<result>25</result>
<result>28</result>
<result>29</result>
<result>34</result>
<result>36</result>
<result>44</result>
<result>46</result>
<result>52</result>
<result>62</result>
<result>63</result>
<result>72</result>
<result>73</result>
<result>75</result>
</draw>
I need to split the data...
I've tried the code below:
XDocument loadeddata = XDocument.Parse(e.Result);
var data = from query in loadeddata.Descendants("draw")
select new KinnoResults()
{
DrawNo = (String) query.Element("drawNo").Value,
DrawTime = (String) query.Element("drawTime").Value,
result1 = (String)query.Element("result").Value,
result2 = (String)query.Element("result").Value
};
List<KinnoResults> list = data.ToList();
But result1 and result2 hava the same value 8.
Any idea please?
var drawNo = loadeddata.Root.Element("drawNo").Value;
var drawTime = loadeddata.Root.Element("drawTime").Value;
var results = loadeddata.Descendants("result").Select(d => d.Value).ToList();
use Elements, it gets you a collection
select new KinnoResults()
{
DrawNo = (String)query.Elements("drawNo").Value,
DrawTime = (String)query.Element("drawTime").Value,
result1 = (String)query.Elements("result").ToList()[0].Value,
result2 = (String)query.Elements("result").ToList()[1].Value
};

One to Many Linq to XML query

I have an XML string that looks like this:
<Attributes>
<ProductAttribute id="1">
<ProductAttributeValue>
<Value>a</Value>
</ProductAttributeValue>
</ProductAttribute>
<ProductAttribute id="2">
<ProductAttributeValue>
<Value>a</Value>
</ProductAttributeValue>
<ProductAttributeValue>
<Value>b</Value>
</ProductAttributeValue>
</ProductAttribute>
</Attributes>
I would like to return an IEnumerable like this:
Id Value
1 a
2 a b
I have tried this and only got the "b" value for Id "2":
XElement e = XElement.Parse(xmlString);
var q = from pa in e.Elements("ProductAttribute")
from pav in pa.Elements("ProductAttributeValue").Elements("Value")
select new
{
Id = (int)pa.Attribute("id"),
Value = (string)pav
};
I tried this:
XElement e = XElement.Parse(xmlString);
var q = from pa in e.Elements("ProductAttribute")
select new
{
Id = (int)pa.Attribute("id"),
Value = pa.Elements("ProductAttributeValue").Elements("Value")
};
But could not cast Value as a string. Using LINQPad the output was like this:
Id Value
1 a
2 <Value>a</Value>
<Value>b</Value>
I am trying to just return the values. Is this even possible?
Thanks.
If you wanted a contatenated string of those values like "a b"
XElement e = XElement.Parse(xmlString);
var q = from pa in e.Elements("ProductAttribute")
select new
{
Id = (int)pa.Attribute("id"),
Value = string.Join(" " ,
pa.Elements("ProductAttributeValue")
.Elements("Value")
.Select(x=>x.Value)
.ToArray())
};
XElement e = XElement.Parse(xmlString);
var q = from pa in e.Elements("ProductAttribute")
select new
{
Id = (int)pa.Attribute("id"),
Value = from pav in pa.Elements("ProductAttributeValue").Elements("Value") select pav.Value
};
Of course, Value will be an IEnumerable<string>.
Edit:
If you want the output to concat the Value elements into one string you can do this:
XElement e = XElement.Parse(xmlString);
var q = from pa in e.Elements("ProductAttribute")
select new
{
Id = (int)pa.Attribute("id"),
Value = string.Join(" ", (from pav in pa.Elements("ProductAttributeValue").Elements("Value")
select pav.Value).ToArray())
};
Then the output will be:
Id Value
1 a
2 a b

Help with Linq to XML

Iv got two DB tables. One containing types(Id, Name) and the other holds datapoints (RefId, Date, Value) that are referenced by the types. I need to create a XML file with the following strukture:
<?xml version='1.0' encoding='utf-8' ?>
<root>
<type>
<name></name>
<data>
<date></date>
<temp></temp>
</data>
<data>
<date></date>
<temp></temp>
</data>
<data>
<date></date>
<temp></temp>
</data>
</type>
</root>
And iv got the following code to do this
public XmlDocument HelloWorld()
{
string tmp = "";
try
{
sqlConn.ConnectionString = ConfigurationManager.ConnectionStrings["NorlanderDBConnection"].ConnectionString;
DataContext db = new DataContext(sqlConn.ConnectionString);
Table<DataType> dataTypes = db.GetTable<DataType>();
Table<DataPoints> dataPoints = db.GetTable<DataPoints>();
var dataT =
from t in dataTypes
select t;
var dataP =
from t in dataTypes
join p in dataPoints on t.Id equals p.RefId
select new
{
Id = t.Id,
Name = t.Name,
Date = p.PointDate,
Value = p.PointValue
};
string xmlString = "<?xml version=\"1.0\" encoding=\"utf-8\" ?><root></root>";
XmlDocument xmldoc = new XmlDocument();
xmldoc.LoadXml(xmlString);
int count = 0;
foreach (var dt in dataT)
{
XmlElement type = xmldoc.CreateElement("type");
XmlElement name = xmldoc.CreateElement("name");
XmlNode nameText = xmldoc.CreateTextNode(dt.Name);
name.AppendChild(nameText);
type.AppendChild(name);
foreach(var dp in dataP.Where(dt.Id = dp.RefId))
{
XmlElement data = xmldoc.CreateElement("data");
XmlElement date = xmldoc.CreateElement("date");
XmlElement temp = xmldoc.CreateElement("temp");
XmlNode dateValue = xmldoc.CreateTextNode(dp.Date.ToString());
date.AppendChild(dateValue);
XmlNode tempValue = xmldoc.CreateTextNode(dp.Value.ToString());
temp.AppendChild(tempValue);
data.AppendChild(date);
data.AppendChild(temp);
type.AppendChild(data);
}
xmldoc.DocumentElement.AppendChild(type);
}
return xmldoc;
}
catch(Exception e)
{
tmp = e.ToString();
}
return null;
}
[Table(Name="DataTypes")]
public class DataType
{
[Column(IsPrimaryKey = true)]
public long Id;
[Column]
public string Name;
}
[Table(Name="DataPoints")]
public class DataPoints
{
[Column]
public long RefId;
[Column]
public DateTime PointDate;
[Column]
public double PointValue;
}
This is not a working code. Im having problems with LINQ and the inner joins. Could someone please help me to get the correct strukture. I hope its kinda clear what im trying to achive.
Best Regards
Marthin
var result =
new XDocument(new XElement("root",
from dt in dataTypes
join dp in dataPoints on dt.Id equals dp.RefId
select new XElement("type",
new XElement("name", dt.Name),
new XElement("data",
new XElement("date", dp.PointDate),
new XElement("temp", dp.PointValue)))));
var result =
new XDocument(new XElement("root",
from dt in dataTypes
select new XElement("type",
new XElement("name", dt.Name),
from dp in dataPoints
where dp.RefId == dt.Id
select new XElement("data",
new XElement("date", dp.PointDate),
new XElement("temp", dp.PointValue)))));

Categories

Resources