[英]Retrieve data from xml (malformed?) c#
我從xml和C#和linq開始。
我有這種xml
<allegati tot_ele="2">
<record>
<dato nome="IdUnivoco">35516</dato>
<dato nome="Nome">QUOTAZIONE</dato>
<dato nome="RelationID">1268</dato>
<dato nome="nomeFile">1268.pdf</dato>
</record>
<record>
<dato nome="IdUnivoco">35516</dato>
<dato nome="Nome">CONFERMA D`ORDINE</dato>
<dato nome="RelationID">1267</dato>
<dato nome="nomeFile">1267.pdf</dato>
</record>
</allegati>
創建它的人使用相同的元素名稱,並使用屬性指定值的名稱
有沒有一種簡單的方法來為每個記錄創建一個結構,並使用linq創建一個結構列表?
目前,我設法創建了4個不同的字符串列表(我只發布2個,而不是全部4個)
List<string> NomeFile1 = (from c in listaAttch.Descendants("dato")
where c.Attribute("nome").Value == "nomeFile"
select c.Value).ToList();
List<string> Relation = (from c in listaAttch.Descendants("dato")
where c.Attribute("nome").Value == "RelationID"
select c.Value).ToList();
然后用for我將使用4個字符串滿足我的需求
for (int i = 0; i < Relation.Count; i++)
{
byte[] file = Adiuto.getAttachContent1(login, 35516, Int32.Parse(Relation [i]));
System.IO.File.WriteAllBytes("c:\\navision\\" + NomeFile1[i], file);
.
.
.
}
有更快,更優雅的方法嗎? 無需重復linq 4次? 還可以用所有4個屬性值創建結構列表嗎
提前謝謝了
法布里奇奧
您可以將查詢提取到專用方法,然后將不同的值作為參數注入:
private List<string> GetDescendantsValues(SomeType source, string attributeValue)
{
return source.Descendants("dato")
.Where(c => c.Attribute("nome").Value == attributeValue)
.Select(c => c.Value).ToList();
}
用法:
List<string> NomeFile1 = GetDescendantsValues(listaAttch, "nomeFile");
List<string> Relation = GetDescendantsValues(listaAttch, "RelationID");
當然,您也可以根據需要注入其他字符串,我只為1完成了此操作,因為這是與您提供的代碼唯一不同的一個。
是的,您可以使用XmlNodeReader
反序列化非標准xml字符串。 在我的一個項目中,我做了同樣的事情。
轉換任意xml字符串的擴展方法-
public static class XmlSerializerExtensions
{
public static T DeserializeFromNonStandardXmlString<T>(string content)
{
var xmlDoc = new XmlDocument();
xmlDoc.LoadXml(content);
var serializer = typeof(T).IsGenericType ? new XmlSerializer(typeof(T), typeof(T).GenericTypeArguments) : new XmlSerializer(typeof(T));
using (var reader = new XmlNodeReader(xmlDoc))
{
return (T)serializer.Deserialize(reader);
}
}
public static object DeserializeFromNonStandardXmlString(Type type, string content)
{
var xmlDoc = new XmlDocument();
xmlDoc.LoadXml(content);
var serializer = type.IsGenericType ? new XmlSerializer(type, type.GenericTypeArguments) : new XmlSerializer(type);
using (var reader = new XmlNodeReader(xmlDoc))
{
return serializer.Deserialize(reader);
}
}
}
然后生成反序列化所需的類。 就您而言,它類似於-
[XmlRoot(ElementName = "dato")]
public class Dato
{
[XmlAttribute(AttributeName = "nome")]
public string Nome { get; set; }
[XmlText]
public string Text { get; set; }
}
[XmlRoot(ElementName = "record")]
public class Record
{
[XmlElement(ElementName = "dato")]
public List<Dato> Dato { get; set; }
}
[XmlRoot(ElementName = "allegati")]
public class Allegati
{
[XmlElement(ElementName = "record")]
public List<Record> Record { get; set; }
[XmlAttribute(AttributeName = "tot_ele")]
public string Tot_ele { get; set; }
}
然后,您可以通過這種方式序列化-
var dt = XmlSerializerExtensions.DeserializeFromNonStandardXmlString<Allegati>(text);
然后獲取項目列表為-
var NomeFile1 = dt.Record.Select(x => x.Dato.FirstOrDefault(d => d.Nome == "nomeFile")?.Text).Select(x => x != null).ToList();
var Relation = dt.Record.Select(x => x.Dato.FirstOrDefault(d => d.Nome == "RelationID")?.Text).Select(x => x != null).ToList();
您也可以使用一種方法來減少此代碼-
[XmlRoot(ElementName = "allegati")]
public class Allegati
{
...
public List<string> GetItemsWithKey(string key)
{
return Record.Select(x => x.Dato.FirstOrDefault(d => d.Nome == key)?.Text).ToList();
}
}
var dt = XmlSerializerExtensions.DeserializeFromNonStandardXmlString<Allegati>(text);
var a = dt.GetItemsWithKey("nomeFile");
var b = dt.GetItemsWithKey("RelationID");
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.