简体   繁体   English

在c#/。net 3.5中按属性值对xml元素进行排序的最佳方法是什么

[英]What is the best way to sort xml elements by attribute values in c#/.net 3.5

I have a XML file with data like: 我有一个XML文件,其数据如下:

<Details>
  <TableDef>
    <Column Name="Calldate" HeaderName="Calldate" SourceColumnName="Calldate" IsHidden = "false" Position="4" />
    <Column Name="Issue" HeaderName="Issues" SourceColumnName="Issues" IsHidden = "false" Position="3" />
    <Column Name="ParamortizedValue" HeaderName="paramortizedvalue" SourceColumnName="Value" IsHidden = "false" Position="1" />
    <Column Name="PercentBondTotal" HeaderName="percentbondtotal" SourceColumnName="Percentage" IsHidden = "false" Position="2" />
  </TableDef>
</Details>

I was wondering what would be the best and efficient way to filter and sort the elements by an attribute so that I can use that sorted elements further in my code? 我想知道按属性对元素进行过滤和排序的最佳,有效方法是什么,以便可以在代码中进一步使用排序后的元素?

In above example, I want to filter by "IsHidden = false" and then sort the elements by "Position" attribute. 在上面的示例中,我想按“ IsHidden = false”进行过滤,然后按“ Position”属性对元素进行排序。

I have the following code that will read all the elements without any sort: 我有以下代码,无需任何排序即可读取所有元素:

var doc = XDocument.Load("data.xml");
var nodeTableDefInfo = doc.XPathSelectElements("/Details");
var elements = nodeTableDefInfo.Elements("TableDef").Elements();
foreach (var e in elements)
{
  //want to work on the sorted elements
}

Guys, Thanks for all the solutions. 伙计们,感谢您提供的所有解决方案。 before I could read your solution I came up with this: 在我读懂您的解决方案之前,我想出了这一点:

var elements = nodeTableDefInfo.Elements("TableDef").Elements();
var sortedElements = (from element in elements 
                where element.Attribute("IsHidden").Value == "false" 
                orderby element.Attribute("Position").Value ascending 
                select element);
foreach (var e in sortedElements)
{
//work on the sorted elements
}

Now, after going through the solutions, I really liked the solution and explanation provided by GFK . 现在,在完成解决方案之后,我真的很喜欢GFK提供的解决方案和说明。 I guess I need some handling for nulls. 我想我需要对null进行一些处理。 Thanks all. 谢谢大家

Use some more LINQ! 再使用一些LINQ!

var sortedElements =
    from element in elements
    let hiddenAttribute = element.Attribute("IsHidden")
    let positionAttribute = element.Attribute("Position")
    where hiddenAttribute != null
        && positionAttribute != null
        && hiddenAttribute.Value == "false"
   let position = int.Parse(positionAttribute)
   orderby position
   select element;

foreach (var e in sortedElements)
{
    // ...
}

Edit: also, what I do usually with LINQ-to-XML is create an anonymous type so I can parse once and for all the attributes into strongly typed values (and handle missing or invalid values), like: 编辑:此外,我通常使用LINQ-to-XML进行的工作是创建一个匿名类型,这样我就可以将所有属性一次解析为强类型值(并处理缺失或无效值),例如:

int parsedInt;
var sortedElements =
    from element in elements
    let hiddenAttribute = element.Attribute("IsHidden")
    let positionAttribute = element.Attribute("Position")
    // add other attributes here
    select new
        {
            IsHidden = hiddenAttribute == null || hiddenAttribute.Value != "false",
            Position = positionAttribute == null || !int.TryParse(positionAttribute.Value, out parsedInt)
                ? default(int?)
                : parsedInt,
            // add other parsed attributes here
        };

This way, all operations is made easier, like sorting or filtering: 这样,使所有操作变得更容易,例如排序或过滤:

foreach(var element in sortedElements.Where(e => !e.IsHidden).OrderBy(e => e.Position)
{
    // ...
}
var tableDefs = nodeTableDefInfo.Elements("TableDef").Elements();
foreach(var column in tableDefs.Where(x=>
                                 x.Attributes("IsHidden") != null && 
                                 bool.Parse(x.Attributes("IsHidden").value) == false && 
                                 x.Attributes("Position") != null)
                               .OrderBy(x=>int.Parse(x.Attributes("Position"))

Try Linq2XML. 尝试使用Linq2XML。

XDocument ip = XDocument.Load(Server.MapPath("~/data.xml"));
var op = ip.Descendants("Column")
    .Where(node => node.Attribute("IsHidden").Value == "false")
    .OrderBy(node => int.Parse(node.Attribute("Position").Value))
    .ToList();

Now, op will be List<XElement> . 现在, op将为List<XElement> Use for or foreach to manipulate it. 使用forforeach进行操作。

linq.. linq ..

string str = @"
            <Details>
                <TableDef>
                    <Column Name='Calldate' HeaderName='Calldate' SourceColumnName='Calldate' IsHidden='false' Position='4' />
                    <Column Name='Issue' HeaderName='Issues' SourceColumnName='Issues' IsHidden='false' Position='3' />
                    <Column Name='ParamortizedValue' HeaderName='paramortizedvalue' SourceColumnName='Value' IsHidden = 'false' Position='1' />
                    <Column Name='PercentBondTotal' HeaderName='percentbondtotal' SourceColumnName='Percentage' IsHidden = 'false' Position='2' />
                </TableDef>
            </Details>";
XDocument xml = XDocument.Parse(str);
List<XElement> columns = (from t in xml.Descendants("TableDef").Descendants("Column") where (bool)t.Attribute("IsHidden") == false orderby (int)t.Attribute("Position") ascending select t).ToList();

Sample approach: 示例方法:

            var list = new List<KeyValuePair<string, XElement>>();
            foreach(var element in elements)
            {
                list.Add(new KeyValuePair<string,XElement>(
                    element.Attribute("someAttr").Value,
                    element));
            }
            var sorted = from entry in list
                         orderby entry.Value.Attribute("someAttr").Value
                         select entry;
            // just test:
            foreach (var entry in sorted)
            {
                Debug.WriteLine(String.Format("attribute value: {0} - element: {1}", entry.Key, entry.Value.ToString()));
            }

We're retrieving your chosen attribute values and treat it as an index. 我们正在检索您选择的属性值,并将其视为索引。

We create a dictionary (a list of key-value pairs to be precise, as those values may not be unique) and then we just sort the list by the key. 我们创建一个字典(精确的键值对列表,因为这些值可能不是唯一的),然后我们按键对列表进行排序。

I assume that this attribute will be present for every XElement - if that's not the case, you need to check for null of course. 我假设每个XElement都将存在此属性-如果不是这种情况,则当然需要检查是否为null。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用C#/。net 3.5从xml元素检索属性的最佳方法 - The best way to retrieve the attributes from xml elements using C#/.net 3.5 从c#中的xml字符串读取属性的最佳方法是什么? - What is the best way to read an attribute from an xml string in c# 收藏集是否可能和/或最佳方式? C#.Net 3.5 - Is a Collection of Collections possible and/or the best way? C# .Net 3.5 C#ASP.NET按自定义属性对XML节点进行排序 - C# ASP.NET Sort XML Nodes by custom attribute 使用C#.NET 3.5进行XML反序列化 - XML Deserialization with C# .NET 3.5 在Visual Studio Compact Framework 3.5 C#中隐藏和重新排列GUI元素的最佳方法? - Best way to hide and rearrange GUI elements in Visual Studio Compact Framework 3.5 C#? 在 C# 中,解析并按时间字符串排序的最佳方法是什么? - In C#, what is the best way to Parse out and sort by time string? 从 C# 中的托管对象属性获取值的最佳方法 - Best Way to get values from Managed Objects Attribute in C# 根据 C# 中的 RunBefore 属性订购方法的最佳方式是什么 - What is the best way to order methods based on a RunBefore attribute in C# C#.NET 3.5:Expression <>用于什么? - C# .NET 3.5: What is Expression<> used for?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM