Каков наилучший способ сортировки элементов XML по значениям атрибутов в c # /. Net 3.5 - PullRequest
1 голос
/ 01 августа 2011

У меня есть 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>

Мне было интересно, что будет лучшим и эффективным способом фильтрации и сортировки элементов по атрибуту, чтобы я мог использовать эти отсортированные элементы далее в моем коде?

В приведенном выше примере я хочу отфильтровать по «IsHidden = false», а затем отсортировать элементы по атрибуту «Position».

У меня есть следующий код, который будет читать все элементы без какой-либо сортировки:

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
}

Ребята, спасибо за все решения. прежде чем я смог прочитать ваше решение, я придумал следующее:

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
}

Теперь, после ознакомления с решениями, мне очень понравилось решение и объяснение, предоставленные GFK. Я думаю, мне нужна некоторая обработка для нулей. Спасибо всем.

Ответы [ 5 ]

2 голосов
/ 01 августа 2011

Используйте еще несколько 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)
{
    // ...
}

Редактировать: кроме того, я обычно делаю с 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
        };

Таким образом, все операции упрощаются, например, сортировка или фильтрация:

foreach(var element in sortedElements.Where(e => !e.IsHidden).OrderBy(e => e.Position)
{
    // ...
}
2 голосов
/ 01 августа 2011
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"))
1 голос
/ 01 августа 2011

.. * LINQ 1001 *

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();
1 голос
/ 01 августа 2011

Попробуйте 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();

Теперь op будет List<XElement>. Используйте for или foreach для манипулирования им.

0 голосов
/ 01 августа 2011

Пример подхода:

            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()));
            }

Мы получаем выбранные вами значения атрибутов и обрабатываем их как индекс.

Мы создаем словарь (точный список пар ключ-значение, поскольку эти значения могут быть не уникальными), а затем просто сортируем список по ключу.

Я предполагаю, что этот атрибут будет присутствовать для каждого XElement - если это не так, вам, конечно, нужно проверить на ноль.

...