2011-08-01 3 views
1

私のようなデータを持つXMLファイルがあります。のC#/に属性値によってXML要素をソートするための最良の方法は何であるネット3.5

<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が提供するソリューションとの説明が好きでした。私はnullを処理する必要があると思います。皆さんありがとう。

答えて

2

さらに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からXMLへは匿名型を作成している、などの:

foreach(var element in sortedElements.Where(e => !e.IsHidden).OrderBy(e => e.Position) 
{ 
    // ... 
} 
+0

また、あなたは第二の例から放出されたきたことに基づいてフィルタリングできます。 –

+0

本当に、それを確実に破棄したいかどうかによって異なります。 –

+0

私は解決策と説明が好きでした。ありがとう。 –

0

サンプルアプローチ:

  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に存在するものとします。そうでない場合は、もちろんnullを確認する必要があります。

2
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

試してみてください。

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

この方法では、すべての操作は、ソートやフィルタリングのような、容易に行われます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(); 

さて、opList<XElement>になります。それを操作するにはforまたはforeachを使用してください。あなたがlet文に匿名で入力されたオブジェクトをバインドする場合

+0

ノードに 'Position'属性または 'IsHidden'属性がない場合、int値ではなくPosition属性の文字列値に基づいて順序付けされます(つまり、10は2より前になります) – Jason

+0

非常に真実。更新しました。 – naveen

1

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(); 
関連する問題