2015-04-05 57 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>

感谢您的阅读,

阿兰