Reputation: 35
I apologize if this question has been asked, but I have not yet found a solution here that works for me. I am new to working with XML.
I have an SQL Server table (called "Answers") that contains a column of type XML (called "XmlColumn"). The rows look something like this (each line being a distinct record).
<value type="option" />
<value type="numeric" value="250" />
<value type="string" value="Sample Text" />
<value type="numeric" value="" />
My question is, from my ASP project, how can I:
Currently, I have something that works, but I'm not convinced it's an ideal solution:
var allAnswers = MyModel.Context.Answers.Select(a => a.XmlColumn);
List<int> allNumericAnswers = new List<int>();
foreach (var answer in allAnswers)
{
string type = (string)XElement.Parse(answer).Attribute("type");
string value = (string)XElement.Parse(answer).Attribute("value");
if (type == "numeric")
{
int numericVal;
bool res = int.TryParse(value, numericVal);
if (res)
{
allNumericAnswers.Add(numericVal);
}
}
}
//Now allNumericAnswers is holding all integer values of type "numeric"
//and I can manipulate them as necessary.
My goal is to perform queries such as "Find the average of all numeric values" or "Select all numeric values > 50", etc. So far, all searches have lead me to solutions for traversing, filtering, parsing, etc within a single XML document, however I want to parse and manipulate thousands of these records at a time, and store them in something like an array for further calculations.
Is there a more elegant solution to what I'm doing above?
Upvotes: 0
Views: 46
Reputation: 4710
Doing this in SQL would be much more efficient. You wouldn't have to send the entire table contents over the wire and SQL is optimized to handle this type of data interrogation.
Here is a way to get the values where (type="numeric" and value != "") and return the values as an integer.
select convert(int, XmlColumn.value('(/value[@type="numeric" and @value!=""]/@value)[1]', 'varchar(20)')) as NumericValue
from Answers
where XmlColumn.value('(/value[@type="numeric" and @value!=""]/@value)[1]', 'varchar(20)') is not null
Throw an avg on that to get the average
select avg(convert(int, XmlColumn.value('(/value[@type="numeric" and @value!=""]/@value)[1]', 'varchar(20)'))) as NumericValue
from Answers
where XmlColumn.value('(/value[@type="numeric" and @value!=""]/@value)[1]', 'varchar(20)') is not null
Make it a sub-query to get all the ones that have a value > 50
select NumericValue from
(
select convert(int, XmlColumn.value('(/value[@type="numeric" and @value!=""]/@value)[1]', 'varchar(20)')) as NumericValue
from Answers
where XmlColumn.value('(/value[@type="numeric" and @value!=""]/@value)[1]', 'varchar(20)') is not null
) a
where NumericValue > 50
Upvotes: 2