2015-04-05 81 views
1

我有一些麻煩試圖從XML文檔中查詢和子查詢列表中獲取所需的結果。LINQ to XML選擇子查詢屬性到一個字符串列表

我有下面的XML文檔(砍倒版)

<ObjectSet ExportMode="Special" Version="1.5.0.2307" Note="TypesFirst"> 
 
    <MetaInformation> 
 
    <ExportMode Value="Special" /> 
 
    <RuntimeVersion Value="1.5.0.2307" /> 
 
    <SourceVersion Value="1.5.0.2307" /> 
 
    <ServerFullPath Value="/WW_C27" /> 
 
    </MetaInformation> 
 
    <ExportedObjects> 
 
    <OI NAME="Source Notifications" TYPE="system.base.Folder"> 
 
     <OI NAME="Joe Blow" TYPE="notification.EmailNotification"> 
 
     <PI Name="EmailAddress" Value="[email protected]" /> 
 
     <PI Name="EmailSubject" Value="TEST ALARM" /> 
 
     <PI Name="NotificationText" Value="Alarm text: @(AlarmText) Triggered: @(TimeStamp)" /> 
 
     <PI Name="Status" Value="1" /> 
 
     <OI NAME="Filter" TYPE="event.filter.Filter" declared="1" hidden="1"> 
 
      <OI NAME="AlarmState" TYPE="event.filter.expression.Enum" declared="1"></OI> 
 
      <OI NAME="Source" TYPE="event.filter.expression.Text" flags="aggregated"> 
 
      <PI Name="Column" Value="Source" /> 
 
      <PI Name="DisplayName" Value="Source" /> 
 
      <OI NAME="Value1" TYPE="event.filter.expression.TextValue" flags="aggregated"> 
 
       <PI Name="Value" Value="LG Gas Panel Exhaust Fan" /> 
 
      </OI> 
 
      <OI NAME="Value3" TYPE="event.filter.expression.TextValue" flags="aggregated"> 
 
       <PI Name="Value" Value="LG Dewer Alm" /> 
 
      </OI> 
 
      </OI> 
 
     </OI> 
 
     </OI> 
 
     <OI NAME="John Smith" TYPE="notification.EmailNotification"> 
 
     <PI Name="EmailAddress" Value="[email protected]" /> 
 
     <PI Name="EmailSubject" Value="Work ALARM" /> 
 
     <PI Name="NotificationText" Value="Alarm text: @(AlarmText) Triggered: @(TimeStamp)" /> 
 
     <PI Name="Status" Value="1" /> 
 
     <OI NAME="Filter" TYPE="event.filter.Filter" declared="1" hidden="1"> 
 
      <OI NAME="AlarmState" TYPE="event.filter.expression.Enum" declared="1"> 
 
      <PI Name="Column" Value="AlarmState" /> 
 
      <PI Name="DisplayName" Value="Alarm state" /> 
 
      <PI Name="EnumType" Value="alarm.pt.AlarmState" /> 
 
      <OI NAME="1" TYPE="event.filter.expression.EnumValue" flags="aggregated"> 
 
       <PI Name="Value" Value="1" /> 
 
      </OI> 
 
      <OI NAME="0" TYPE="event.filter.expression.EnumValue" flags="aggregated" /></OI> 
 
      <OI NAME="Source" TYPE="event.filter.expression.Text" flags="aggregated"> 
 
      <PI Name="Column" Value="Source" /> 
 
      <PI Name="DisplayName" Value="Source" /> 
 
      <OI NAME="Value1" TYPE="event.filter.expression.TextValue" flags="aggregated"> 
 
       <PI Name="Value" Value="Rm 7 FrzAlm" /> 
 
      </OI> 
 
      <OI NAME="Value2" TYPE="event.filter.expression.TextValue" flags="aggregated"> 
 
       <PI Name="Value" Value="Dewer Alm" /> 
 
      </OI> 
 
      </OI> 
 
     </OI> 
 
     </OI> 
 
    </OI> 
 
    </ExportedObjects> 
 
</ObjectSet>

總之,我需要從上面的XML文檔中提取以下細節:

  • Person Name
  • Person Email Address
  • 電子郵件主題

以上所有詳細信息我可以提取並顯示在我的數據網格中。

但是,對於每個用戶,我都需要在數據網格中顯示一些警報消息,作爲數據網格給定用戶下方的子行。 目前我無法做到這一點。達到預期結果的最佳方式是什麼?

從上面的XML文檔,下面是一個典型的元素,我需要提取每個用戶以下的兒童名單:

<PI Name="Value" Value="Dewer Alm" />

見下面我的C#代碼。

List<EmailNotificationClass> NotificationList = 
       (
       from n in XDocument.Load(str_XMLFilePath).Root.Descendants("ExportedObjects").Descendants("OI").Descendants("OI") 
       where (string)n.Attribute("TYPE") == "notification.EmailNotification"          

       let attrib_NAME = n.Attribute("NAME") 

       let attrib_EMAIL = n.XPathSelectElement("./PI[@Name='EmailAddress']").Attribute("Value") 
       let attrib_SUBJECT = n.XPathSelectElement("./PI[@Name='EmailSubject']").Attribute("Value") 
       let attrib_NotificationText = n.XPathSelectElement("./PI[@Name='NotificationText']").Attribute("Value") 
       let attrib_Status = n.XPathSelectElement("./PI[@Name='Status']").Attribute("Value") 

       let attrib_SourceList = n.XPathSelectElement("//OI/OI[@NAME='Source']/OI/PI[@Name='Value']") 



       select new EmailNotificationClass 
       { 
        EN_NotificationName = attrib_NAME.Value, 
        EN_EmailAddress = attrib_EMAIL.Value, 
        EN_EmailSubject = attrib_SUBJECT.Value, 
        EN_NotificationText = attrib_NotificationText.Value, 
        EN_Status = attrib_Status.Value, 

        EN_SourceList = attrib_SourceList.Value //Need to turn this result into a child list 
       } 
       ).ToList(); 

      //Set DataGrid source 
      DG_Notifications.ItemsSource = NotificationList; 

     } 
     else 
     { 
      MessageBox.Show("Please load XML file from the import tab first"); 
     }    
    } 

任何幫助將不勝感激。

乾杯

阿蘭

回答

0

設法解決這個問題我自己。對於任何可能堆棧出現類似問題的人來說,問題是我定義保存數據的類的方式,稍後將顯示在DataGrid中。

一旦我將第一個類中的字符串源更改爲List,我就可以檢索每個人的警報列表。

public class EmailNotificationClass 
{ 
    //EN = EmailNotification OI in the XML document  
    public string EN_NotificationName { get; set; } 
    public string EN_EmailAddress { get; set; } 
    public string EN_EmailSubject { get; set; } 
    public string EN_NotificationText { get; set; } 
    public string EN_Status { get; set; } 
    public string EN_FilterType { get; set; } 
    public List<EN_F_SourceClass> Sources { get; set; } 

} 


public class EN_F_SourceClass 
{ 
    public string FilterSource { get; set; } 
} 

我然後修改爲遵循

List<EmailNotificationClass> NotificationList = 
       (

       from n in XDocument.Load(str_XMLFilePath).Root.Descendants("ExportedObjects").Descendants("OI").Descendants("OI") 
       where (string)n.Attribute("TYPE") == "notification.EmailNotification"          

       let attrib_NAME = n.Attribute("NAME") 

       let attrib_EMAIL = n.XPathSelectElement("./PI[@Name='EmailAddress']").Attribute("Value") 
       let attrib_SUBJECT = n.XPathSelectElement("./PI[@Name='EmailSubject']").Attribute("Value") 
       let attrib_NotificationText = n.XPathSelectElement("./PI[@Name='NotificationText']").Attribute("Value") 
       let attrib_Status = n.XPathSelectElement("./PI[@Name='Status']").Attribute("Value") 


       select new EmailNotificationClass 
       { 
        EN_NotificationName = attrib_NAME.Value, 
        EN_EmailAddress = attrib_EMAIL.Value, 
        EN_EmailSubject = attrib_SUBJECT.Value, 
        EN_NotificationText = attrib_NotificationText.Value, 
        EN_Status = attrib_Status.Value, 

        Sources = 
        (
        from source in n.XPathSelectElements("OI/OI[@NAME='Source']/OI/PI[@Name='Value']") 
        select new EN_F_SourceClass 
        { 
         FilterSource = (string)source.Attribute("Value") 
        }).ToList() 

       } 
       ).ToList(); 


      //Set DataGrid source 
      DG_Notifications.ItemsSource = NotificationList; 

     } 
     else 
     { 
      MessageBox.Show("Please load XML file from the import tab first"); 
     }    

的xalm部分是容易後面的代碼。只是增加了一個RowDeetailsTemplate如下

<DataGrid.RowDetailsTemplate> 
 
    <DataTemplate> 
 
    <Grid MaxHeight="100"> 
 
     <ScrollViewer> 
 
     <Border BorderThickness="0" Background="#FFB8E8A1" Padding="5"> 
 
      <DataGrid ItemsSource="{Binding Sources}" IsReadOnly="True" SelectionMode="Single" SelectionUnit="FullRow" AutoGenerateColumns="False"> 
 
      <DataGrid.Columns> 
 
       <DataGridTextColumn Width="400" Header="Alarms" Binding="{Binding FilterSource}"></DataGridTextColumn> 
 
      </DataGrid.Columns> 
 
      </DataGrid> 
 
     </Border> 
 
     </ScrollViewer> 
 
    </Grid> 
 
    </DataTemplate> 
 
</DataGrid.RowDetailsTemplate>

感謝您的閱讀,

阿蘭