我有以下XML:
<propertyMetrics month="12" year="2003" propertyId="3923837">
<metric name="siteTotal" uom="kBtu" dataType="numeric">
<value>241609.4</value>
</metric>
<metric name="waterUseTotal" dataType="numeric">
<value xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
</metric>
<metric name="propGrossFloorArea" uom="ft²" dataType="numeric">
<value>20429</value>
</metric>
<metric name="totalGHGEmissions" uom="MtCO2e" dataType="numeric">
<value>21.2</value>
</metric>
<metric name="greenPowerOnSite" dataType="numeric">
<value xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
</metric>
<metric name="energyBaselineDate" dataType="date">
<value>2010-12-31</value>
</metric>
<metric name="score" dataType="numeric">
<value xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
</metric>
我正在尝试关联&#34;名称&#34;属性为&#34;值&#34;元素和&#34; uom&#34;属性(如果存在)。
我原来是这样做的:
var propMetrics = doc.Descendants("metric")
.Where(e => !string.IsNullOrEmpty(e.Element("value").Value))
.ToDictionary(e => e.Attribute("name").Value, e => new { uom = e.Attribute("uom").Value, value =(double) e.Element("value") });
当没有&#34; uom&#34;属性。所以现在我做了两个LIQN调用,看起来更加丑陋的代码:
var propMetrics = doc.Descendants("metric")
.Where(e => !string.IsNullOrEmpty(e.Element("value").Value) && !(e.FirstAttribute.Value == "energyBaselineDate") && !(e.FirstAttribute.Value == "score"))
.ToDictionary(e => e.Attribute("name").Value,
e => new
{
uom = e.Attribute("uom").Value,
value = (double)e.Element("value")
});
foreach(var x in propMetrics)
{
builder.Append(x.Key + ": " + x.Value.value + "<br>\n" + "uom: " + x.Value.uom + "<br>\n");
}
var score = doc.Descendants("metric")
.Where(e => !string.IsNullOrEmpty(e.Element("value").Value) && (e.FirstAttribute.Value == "energyBaselineDate") || (e.FirstAttribute.Value == "score"))
.Select(e => new {
name = e.Attribute("name").Value,
value = (string)e.Element("value")});
foreach(var x in score)
{
builder.Append(x.name + ": " + x.value + "<br>\n");
}
有一种简单的方法吗?可能在单个LINQ查询中?
答案 0 :(得分:2)
我想建议使用序列化模型进行复杂的xml读取和编辑会更容易。您可以轻松地将xml转换为c#对象,然后根据需要编辑对象属性。将xml转换为对象可以像这样轻松地完成:
static List<Metric> DeserializeFromXML(string xmlString)
{
XmlSerializer deserializer = new XmlSerializer(typeof(List<Metric>));
List<Metric> metrics;
metrics = (List<Metric>)deserializer.Deserialize(xmlString);
return metrics;
}
同样,您可以使用以下内容将对象转换回xml:
static public string SerializeToXML(List<Metric> metrics)
{
XmlSerializer serializer = new XmlSerializer(typeof(List<Metric>));
using (StringWriter writer = new StringWriter())
{
serializer.Serialize(writer, metrics);
return writer.ToString();
}
}
根据您提供的xml,您将用于序列化进出的c#Metric对象看起来应该如下所示:
public class Metric
{
public string name { get; set; }
public string uom { get; set; }
public string dataType { get; set; }
public string value { get; set; }
}
答案 1 :(得分:0)
var propMetrics = (
from e in doc.Descendants( "metric" )
where !string.IsNullOrEmpty( e.Element( "value" ).Value )
let auom = e.Attribute( "uom" )
select new {
key = e.Attribute( "name" ).Value,
value = new {
value = (double)e.Element( "value" ),
uom = auom != null ? auom.Value : ""
}
} ).ToDictionary( p => p.key, p => p.value );