Как перебрать все элементы в XML в Select Nodes

Я действительно новичок в С#. Я создаю проект, в котором мне нужно извлечь данные из файла XML. Я могу выбрать один единственный узел и просмотреть внутренний текст этого элемента. Но у меня есть несколько элементов в файле XML. Я хочу зациклить все элементы сразу в столбце. Как я могу это сделать. Я подробно объясняю.

Вот мой XML-файл.

    <?xml version="1.0" encoding="utf-8"?>
<tlp:WorkUnits xmlns:tlp="http://www.timelog.com/XML/Schema/tlp/v4_4"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:schemaLocation="http://www.timelog.com/XML/Schema/tlp/v4_4 http://www.timelog.com/api/xsd/WorkUnitsRaw.xsd">
  <tlp:WorkUnit ID="130">
    <tlp:EmployeeID>3</tlp:EmployeeID>
    <tlp:AllocationID>114</tlp:AllocationID>
    <tlp:TaskID>239</tlp:TaskID>
    <tlp:ProjectID>26</tlp:ProjectID>
    <tlp:ProjectName>LIK Template</tlp:ProjectName>
    <tlp:CustomerId>343</tlp:CustomerId>
    <tlp:CustomerName>Lekt Corp Inc.</tlp:CustomerName>
    <tlp:IsBillable>1</tlp:IsBillable>
    <tlp:ApprovedStatus>0</tlp:ApprovedStatus>
    <tlp:LastModifiedBy>AL</tlp:LastModifiedBy>
  </tlp:WorkUnit>
  <tlp:WorkUnit ID="131">
    <tlp:EmployeeID>3</tlp:EmployeeID>
    <tlp:AllocationID>114</tlp:AllocationID>
    <tlp:TaskID>239</tlp:TaskID>
    <tlp:ProjectID>26</tlp:ProjectID>
    <tlp:ProjectName>LIK Template</tlp:ProjectName>
    <tlp:CustomerId>343</tlp:CustomerId>
    <tlp:CustomerName>Lekt Corp Inc.</tlp:CustomerName>
    <tlp:IsBillable>1</tlp:IsBillable>
    <tlp:ApprovedStatus>0</tlp:ApprovedStatus>
    <tlp:LastModifiedBy>AL</tlp:LastModifiedBy>
  </tlp:WorkUnit>

И вот мой класс ConsumeReportingApi, в котором я хочу перебирать значения.

    public class ConsumeReportingApi
    {
        private static readonly ILog Logger = LogManager.GetLogger(typeof (ConsumeReportingApi));

        public static void Consume()
        {
            if (ServiceHandler.Instance.TryAuthenticate())
            {
                if (Logger.IsInfoEnabled)
                {
                    Logger.Info("Successfully authenticated on reporting API");
                }

               var customersRaw = ServiceHandler.Instance.Client.GetWorkUnitsRaw(ServiceHandler.Instance.SiteCode,
                    ServiceHandler.Instance.ApiId,
                    ServiceHandler.Instance.ApiPassword,
                    WorkUnit.All,
                    Employee.All,
                    Allocation.All,
                    Task.All,
                    Project.All,
                    Department.All,
                    DateTime.Now.AddDays(-5).ToString(),
                    DateTime.Now.ToString()
                 );

                if (customersRaw.OwnerDocument != null)
                {
                    var namespaceManager = new XmlNamespaceManager(customersRaw.OwnerDocument.NameTable);
                    namespaceManager.AddNamespace("tlp", "http://www.timelog.com/XML/Schema/tlp/v4_4");

                    var customers = customersRaw.SelectNodes("tlp:WorkUnit", namespaceManager);
                    if (customers != null)
                    {
                        foreach (XmlNode customer in customers)
                        {
                             var taskId = customer.SelectSingleNode("tlp:TaskId", namespaceManager);
                          if (taskId != null)
                          {
                              if (Logger.IsDebugEnabled)
                              {
                                  Logger.Debug("Task ID "+taskId.InnerText);
                              }
                          }
                          var department = customer.SelectSingleNode("tlp:ProjectName", namespaceManager);
                          if (department != null)
                          {
                              if (Logger.IsDebugEnabled)
                              {
                                  Logger.Debug("Department ID: "+department.InnerText);
                              }
                          }
        }
    }
}

На данный момент я установил tlp:TaskID внутри метода customersRaw.SelectNodes. Но я хочу получить все остальные элементы os xml и распечатать эти значения. Но я не уверен, как это сделать.

Мой основной класс программы

public class Program
{
    private static readonly ILog Logger = LogManager.GetLogger(typeof(Program));
    private static readonly DirectoryInfo AppPath = new FileInfo(Assembly.GetExecutingAssembly().Location).Directory;

    public static void Main(string[] args)
    {
   ....

        try
        {
            if (Logger.IsInfoEnabled)
            {
                Logger.Info("Running application");
            }

            // Run example classes
            ConsumeReportingApi.Consume();

        }
        catch (Exception ex)
        {
            ...
        }

        if (Logger.IsInfoEnabled)
        {
            Logger.Info("---");
            Logger.Info("Application loop ended. Click to exit");
        }

        // Wait for the user to end the application.
        Console.ReadKey();
    }
}

}


person tamrezh21    schedule 11.12.2017    source источник
comment
Возможный дубликат Поиск в дереве с использованием LINQ   -  person netaholic    schedule 11.12.2017
comment
@netaholic Я использовал var customerName в методе .SelectSingleNode. как я могу перебрать xml здесь   -  person tamrezh21    schedule 11.12.2017


Ответы (2)


Попробуйте это, если вы хотите регистрировать внутренний текст всех дочерних узлов:

var customers = customersRaw.SelectNodes("tlp:WorkUnit", namespaceManager);
if (customers != null)
{
    foreach (XmlNode customer in customers)
    {
        var childNodes = customer.SelectNodes("./*");
        if(childNodes != null)
        {
            foreach(XmlNode childNode in childNodes)
            {
                if (Logger.IsDebugEnabled)
                {
                    Logger.Debug(customerName.InnerText);
                }
            }
        }
    }
}

Если вы хотите получить внутренний текст определенного узла, имя которого вы знаете, вы можете использовать SelectSingleNode:

var childNode = customer.SelectSingleNode("./tlp:CustomerId", namespaceManager);
if(childNode != null)
    Debug.WriteLine(childNode.InnerText);
person mm8    schedule 11.12.2017
comment
Спасибо, но если я хочу получить какое-то конкретное значение для exmaple taskId, projectId и Customer id, то как мне зациклить этот XML - person tamrezh21; 11.12.2017
comment
Мой образец проходит через все узлы, включая TaskId, ProjectId и CustomerId, поэтому я не очень понимаю ваш вопрос...? Что ты хочешь? - person mm8; 11.12.2017
comment
Мне нужно получить все значения сразу и некоторые конкретные значения в некоторых случаях. В вашем коде вы перебираете весь xml-файл. это нормально. но что мне делать, если я хочу получить некоторые определенные атрибуты здесь var childNodes = customer.SelectNodes(./*); - person tamrezh21; 11.12.2017
comment
Используйте SelectSingleNode, если вы хотите выбрать один узел. Смотрите мою правку. - person mm8; 11.12.2017
comment
Я отредактировал свой вопрос и написал один узел 2 раза. Но я очень новичок в С#. Поскольку вы очень опытны, как вы думаете, это хороший способ получить ценность таким образом? - person tamrezh21; 11.12.2017
comment
да. Или вы можете перебрать все узлы, как я показал вам, и сравнить имя узла, например: if(childNode.Name == "tlp:CustomerId"). Вероятно, будет лучше, если вы сделаете что-то особенное с более чем одним дочерним узлом. - person mm8; 11.12.2017
comment
Привет, извините за беспокойство. Где я могу это проверить, если (childNode.Name == tlp:CustomerId) - person tamrezh21; 11.12.2017
comment
Внутри foreach(XmlNode childNode in childNodes), в том же блоке, что и if (Logger.IsDebugEnabled) в моем примере кода. - person mm8; 11.12.2017

Код ниже анализирует рабочую единицу xml в таблицу данных, а затем взаимодействует с таблицей для получения значений.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Data;

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(FILENAME);

            XElement firstWorkUnit = doc.Descendants().Where(x => x.Name.LocalName == "WorkUnit").FirstOrDefault();
            XNamespace ns = firstWorkUnit.GetNamespaceOfPrefix("tlp");

            //create datatable
            DataTable dt = new DataTable();
            foreach (XElement col in firstWorkUnit.Elements())
            {
                dt.Columns.Add(col.Name.LocalName, typeof(string));
            }

            List<XElement> workUnits = doc.Descendants(ns + "WorkUnit").ToList();
            foreach (XElement workUnit in workUnits)
            {
                DataRow newRow = dt.Rows.Add();
                foreach(XElement col in workUnit.Elements())
                { 
                       newRow[col.Name.LocalName] = (string)col;
                }
            }

            List<string> projId = dt.AsEnumerable().Select(x => x.Field<string>("ProjectID")).ToList();

        }
    }
}
person jdweng    schedule 12.12.2017