I stumbled across this question, and ultimately an answer, while looking at a similar issue with integers. Despite the delay since the last answer, I'm adding here in case it helps anyone else in future.
First your basic answer:
select xml.value('xs:decimal(sum(/List/value))', 'numeric') sum
from (select cast('<List><value>0</value><value>0</value></List>' as xml) xml) a
In XQuery you can cast the value to a standard XML Schema type, which will then be handled correctly by SQL Server.
PLEASE NOTE: the default "numeric" in SQL Server does not have any decimal places(scale of "0")! You probably intended to do something more like:
select xml.value('xs:decimal(sum(/List/value))', 'numeric(20,5))') sum
from (select cast('<List><value>0</value><value>0</value></List>' as xml) xml) a
(you cannot get SQL Server to infer the precision or scale from the value returned from the Xml, you must explicitly specify it)
Finally, the actual issue that I personally needed to address was almost exactly the same, except I was dealing with integers, which also struggle with the xml representation of "0" double
values:
select xml.value('xs:int(sum(/List/value))', 'int') sum
from (select cast('<List><value>0</value><value>0</value></List>' as xml) xml) a
UPDATE: The problem with the decimal-handling solution I posted above (converting to decimal in XQuery before SQL gets to parsing the value) is that the aggregation actually happens with the (assumed/inferred) floating point (double) data type. If the values you have stored in your Xml require a high degree of precision, this may actually be the wrong thing to do - the floating-point aggregation may actually result in a loss of data. EG here we lose the last digit of the number we are summing:
select xml.value('xs:decimal(sum(/List/value))', 'numeric(28, 0)') sum
from (select cast('<List>
<value>1000000000000000000000000001</value>
<value>1000000000000000000000000001</value>
</List>' as xml) xml) a
(comes out to "2000000000000000000000000000", which is wrong)
This issue equally applies to other approaches offered here, such as explicitly reading the value as "float" in T-SQL.
To avoid this, here's a final option using an XQuery FLWOR expression to set the data type before the aggregation operation. In this case, the aggregation occurs correctly, and we have the correct summed value (while also handling "0" values if/when they occur):
select xml.value('sum(for $r in /List/value return xs:decimal($r))', 'numeric(28, 0)') sum
from (select cast('<List>
<value>1000000000000000000000000001</value>
<value>1000000000000000000000000001</value>
</List>' as xml) xml) a
(comes out to "2000000000000000000000000002", the correct value)