使用Linq to XML按数值属性在正确位置添加新条目
按Number属性数值顺序插入XML新条目
现有C#函数SetOutlineInfo用于维护XML文件中的PublicTalk条目,支持更新已有条目或新增条目,但新增时条目会被追加到对应语言节点的末尾,无法按Number属性的数值顺序插入到正确位置。
原函数代码
public void SetOutlineInfo(string talksdatabase, int talknumber, string languageCode, bool talkExcluded, DateTime dateExcudedFrom, string excludedNote) { try { XDocument doc = XDocument.Load(talksdatabase); var ptLang = doc.Descendants(languageCode).FirstOrDefault(); if (ptLang != null) { var ptInfo = ptLang .Descendants("PublicTalk") .Where(p => p.Attribute("Number").Value == talknumber.ToString()).FirstOrDefault(); if (ptInfo != null) { ptInfo.Attribute("Excluded").Value = talkExcluded ? "true" : "false"; ptInfo.Attribute("ExcludedFromDate").Value = dateExcudedFrom.ToString("yyyy-MM-dd"); ptInfo.Attribute("ExcludedNote").Value = excludedNote; } else { ptLang.Add(new XElement("PublicTalk", new XAttribute("Number", talknumber), new XAttribute("Excluded", talkExcluded), new XAttribute("ExcludedFromDate", dateExcudedFrom.ToString("yyyy-MM-dd")), new XAttribute("ExcludedNote", excludedNote) )); } doc.Save(talksdatabase); } } catch (Exception ex) { SimpleLog.Log(ex); } }
解决方案实现
要实现新增时按Number数值插入到对应位置,核心是找到第一个Number值大于当前新增条目编号的元素,然后在该元素之前插入新条目;如果所有元素的Number都小于新增编号,则将条目追加到末尾。
修改后的函数代码:
public void SetOutlineInfo(string talksdatabase, int talknumber, string languageCode, bool talkExcluded, DateTime dateExcudedFrom, string excludedNote) { try { XDocument doc = XDocument.Load(talksdatabase); var ptLang = doc.Descendants(languageCode).FirstOrDefault(); if (ptLang != null) { var ptInfo = ptLang .Elements("PublicTalk") // 改用Elements直接获取子节点,避免递归 .FirstOrDefault(p => int.Parse(p.Attribute("Number").Value) == talknumber); if (ptInfo != null) { // 更新已有条目 ptInfo.Attribute("Excluded").Value = talkExcluded ? "true" : "false"; ptInfo.Attribute("ExcludedFromDate").Value = dateExcudedFrom.ToString("yyyy-MM-dd"); ptInfo.Attribute("ExcludedNote").Value = excludedNote; } else { // 创建新条目 var newTalk = new XElement("PublicTalk", new XAttribute("Number", talknumber), new XAttribute("Excluded", talkExcluded ? "true" : "false"), // 统一字符串格式 new XAttribute("ExcludedFromDate", dateExcudedFrom.ToString("yyyy-MM-dd")), new XAttribute("ExcludedNote", excludedNote) ); // 找到第一个Number值大于当前编号的元素 var firstLargerTalk = ptLang.Elements("PublicTalk") .FirstOrDefault(t => int.Parse(t.Attribute("Number").Value) > talknumber); if (firstLargerTalk != null) { // 在目标元素前插入新条目 firstLargerTalk.AddBeforeSelf(newTalk); } else { // 所有元素编号都更小,追加到末尾 ptLang.Add(newTalk); } } doc.Save(talksdatabase); } } catch (Exception ex) { SimpleLog.Log(ex); } }
关键修改说明
- 优化条目查询:将
Descendants改为Elements,直接获取语言节点下的PublicTalk子节点,避免不必要的递归查询。 - 统一属性格式:新增条目时将
Excluded属性统一转换为字符串"true"/"false",和更新逻辑保持一致。 - 定位插入位置:通过LINQ找到第一个编号大于当前新增值的元素,使用
AddBeforeSelf插入到该元素之前;如果没有找到,则追加到节点末尾。
测试验证
- 初始XML包含
Number="47"的条目,新增Number="1"时,会插入到Number="47"条目之前。 - 若已有
Number="10"、Number="20"的条目,新增Number="15"时,会插入到两者之间。 - 新增
Number="50"时,会追加到所有条目末尾。
内容的提问来源于stack exchange,提问作者Andrew Truckle
相关产品推荐
相关产品推荐

