【问题标题】:Sort by two attributes from the same element in an xml file按 xml 文件中同一元素的两个属性排序
【发布时间】:2017-10-13 15:09:44
【问题描述】:

如何从 xml 文件中的同一元素中获取两个属性,比较它们并按数字顺序对它们进行排序?

XML 元素是:

<Parent>
      <Nice to="647429920" from="20200935" />
      <Nice to="647431008" from="20200969" />
      <Nice to="647432224" from="20201007" />
      <Nice to="647437984" from="20201187" />
      <Nice to="647441632" from="20201301" />
      <Nice to="647441760" from="20201305" />
      <Nice to="647443360" from="20201355" />
      <Nice to="647445728" from="20201429" />
      <Nice to="647446144" from="20201442" />
      <Nice to="647447296" from="20201478" />
      <Nice to="647450400" from="20201575" />
      <Nice to="647450752" from="20201586" />
      <Nice to="647451232" from="20201601" />
</Parent>

我尝试这样做作为获取属性的开始:

foreach (XElement node in xDoc.DocumentElement)
            {
                    Console.Write(node.Element("Nice").Attribute("to").Value);
                    Console.Write(node.Element("Nice").Attribute("from").Value);
                Console.WriteLine(node.Element("Entry").Attribute("from").Value);
            }

这会因 Cast 异常而中断。

编辑:

更新到这个:

 var xDoc1 = XDocument.Load(xmlPath);
foreach (XElement node in xDoc1.Elements())
{
Console.WriteLine(node.Element("Nice").Attribute("to").Value);
Console.WriteLine(node.Element("Nice").Attribute("from").Value);
}

但是主体中的代码只被读取一次,然后程序就退出了。它不会循环遍历整个 xml 文件。

【问题讨论】:

  • 什么是base.Write()?什么“演员例外”在哪里?
  • 我的错误 Console.Write,我认为异常是在 XElement 引发的,因为它没有到达正文
  • “在 XElement 上,因为它没有到达身体”是什么意思?
  • 代码不在循环内执行。 XElement 是 XElement 节点。节点似乎是空的,它通过循环并退出。
  • XDocument 没有 DocumentElement 属性。这实际上是XmlDocument,不是吗?所以在任何地方都没有XElement。是的,丹尼尔有。

标签: c# xml linq-to-xml


【解决方案1】:

Daniele's Answer Works 但可能存在一些问题,使用 linq 您可以跳过 foreach 循环:

首先,您的值看起来像整数,因此使用 Value 而不将其解析为整数可能会导致问题(IE 比较字符串 "10" &lt; "2" 时)。

其次,没有检查属性是否存在空值,会抛出空引用异常。

var xDoc1 = XDocument.Load(/* xml path */);
var nodes = xDoc1.Root.Elements("Nice");

var values = nodes
    .Where(n => n.Attributes().Any(a => a.Name == "to"))
    .Select(n => {
      int result;
      int.TryParse(n.Attributes().First(a => a.Name == "to").Value, out result);
      return result;
    })
    .ToList();

values.AddRange(nodes
    .Where(n => n.Attributes().Any(a => a.Name == "from"))
    .Select(n => {
      int result;
      int.TryParse(n.Attributes().First(a => a.Name == "from").Value, out result);
      return result;
    })
    .ToList());

values = values.OrderBy(n => n).ToList();

【讨论】:

  • 已修复。很抱歉,某些代码在 SO 编辑器中粘贴两次。
  • 仍然错误:n.Attributes:XElement 属性是一种未在正确上下文中给出的方法。 values.AddRange(
  • 谢谢,但仍然显示此错误:AddRange( n.Attributes().Any(a => a.Name == "来自"))
  • 你可能自己修好了,但我添加了节点。
【解决方案2】:

也许您正在尝试将从“DocumentElement”返回的“Xml.XmlElement”转换为“Linq.XElement”。
可能你需要这样的东西:

var xDoc = new XmlDocument();
var orderedList = new List<int>();
xDoc.Load(/* xml path */);
var els = xDoc.GetElementsByTagName("Nice").Cast<XmlNode>();
foreach (var el in els)
{
   Console.WriteLine(el.Attributes.Item(0).Value);
   Console.WriteLine(el.Attributes.Item(1).Value);
}

如果你想使用 xml.linq 或者这个代码
在@Ed Plunkett 提示之后编辑

var xDoc1 = XDocument.Load(/* xml path */);
var nodes = xDoc1.Elements("Parent").Elements("Nice");
if(nodes != null && nodes.Any()) 
{
   foreach (XElement node in nodes)
   {
       orderedList.Add(int.Parse(node.Attribute("to").Value));
       orderedList.Add(int.Parse(node.Attribute("from").Value));
   }
}
orderedList.Sort();
foreach (var a in orderedList)
{
   Console.WriteLine(a);
}
Console.ReadLine();

【讨论】:

  • 用xml.linq试过第二个还是进不了正文
  • 将 xDoc 打印到控制台会得到 xml
  • 取出 where 子句,它通过第一行,然后退出给我第一个属性
  • @EdPlunkett 是的,我已经看到了错误并更正了对空引用添加一些检查。
  • 在重构之前正在工作,现在在这一行节点上中断!= null && nodes.Any()
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-03-25
  • 2022-01-06
  • 1970-01-01
  • 2011-02-16
  • 1970-01-01
  • 2014-12-18
  • 1970-01-01
相关资源
最近更新 更多