LINQ to XML выбирает атрибуты подзапроса в список строк

1

У меня возникли проблемы с получением необходимых результатов из запроса и списка подзапросов из документа 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 следующие сведения:

  • Имя человека
  • Адрес электронной почты человека
  • Тема письма

Все вышеперечисленные подробности я могу извлечь и отобразить на своем datagrid.

Тем не менее, для каждого пользователя есть несколько тревожных сообщений, которые мне нужно отображать в datagrid, в качестве дочерних строк под данным, указанным пользователем. На данный момент я не могу этого сделать. Каков наилучший способ достижения требуемого результата?

Из приведенного выше XML-документа следующий типичный элемент, который мне нужно извлечь как дочерний список под каждым пользователем:

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

См. Ниже мой код на С#.

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

Любая помощь будет высоко ценится.

ура

Alain

Теги:
linq
wpf
datagrid

1 ответ

0

Удалось решить проблему самостоятельно. Для тех, кто, возможно, стек с аналогичной проблемой, проблема была в том, как я определил класс, который содержит данные, которые позже будут отображаться в DataGrid.

Как только я изменил строку "Источники в первом классе" на "Список", мне удалось получить список тревог на человека.

    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>

Спасибо за прочтение,

Alain

Ещё вопросы

Сообщество Overcoder
Наверх
Меню