Страницы

Поиск по вопросам

воскресенье, 8 марта 2020 г.

Как вывести файл Xml деревом в консоль с рекурсией. Вроде все читается, но вот как вывести именно деревом, как и сам файл Xml никак не соображу

#c_sharp


вот код 

using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.IO;

namespace TestApp_Dipl
{
    class Program
    {
        static int iter;
        static void Main(string[] args)
        {
            Program ThisClass = new Program();
            Console.WriteLine("Main");
            XmlDocument XmlDoc = new XmlDocument();
            XmlDoc.Load("File.xml");
            XmlNodeList _fnames = XmlDoc.GetElementsByTagName("CD");
            Console.WriteLine(_fnames.Count.ToString());
            ThisClass.GetNodes(_fnames);



            Console.ReadKey();
        }


        void GetNodes(XmlNodeList NodeListVar)
        {
            int i = 1;
            foreach (XmlNode el in NodeListVar)
            {
                if (el.HasChildNodes)
                {
                    Console.WriteLine(i++ + ". " + el.Name);
                    GetNodes(el.ChildNodes);
                }
                else
                {
                    Console.WriteLine("-> " + el.InnerText);
                }
            }
        }


    }
}


Xml file.xml



    
        Empire Burlesque
        Bob Dylan
        USA
        Columbia
        10.90
        1985
    
    
        Hide your heart
        Bonnie Tyler
        UK
        CBS Records
        9.90
        1988
    



Хотелось бы в консоли получить так:

CATALOG
1.CD
TITLE Empire Burlesque
ARTIST Bob Dylan
COUNTRY USA
COMPANY Columbia
PRICE 10.90
YEAR 1985
2.CD
TITLE Hide your heart
ARTIST Bonnie Tyler
COUNTRY UK
COMPANY CBS Records
PRICE 9.90
YEAR 1988

    


Ответы

Ответ 1



Если вам не требуется специфический для класса XmlDocument функционал, то проще воспользоваться XDocument из пространства имен System.Xml.Linq. Это позволит получить более компактный код. Для вывода на консоль в том виде, который вы указали есть три пути. 1. Рекурсивный обход дерева XML Реализуется довольно просто: static void Main(string[] args) { XElement doc = XElement.Load(@"H:\test.xml"); PrintElementV1(doc); Console.ReadKey(); } static void PrintElementV1(XElement elem) { if (elem.Elements().Count() > 0) { Console.WriteLine(elem.Name); foreach (XElement e in elem.Elements()) { PrintElementV1(e); } } else { Console.WriteLine("{0}: {1}", elem.Name, elem.Value); } } Но вставить в этот вод избирательную нумерацию конкретных элементов без "костылей" не выйдет. "Костыль" для нумерации может выглядеть так: static void PrintElementV1(XElement elem, int num) { if (elem.Elements().Count() > 0) { Console.WriteLine("{0}. {1}", num, elem.Name); int i = 1; foreach (XElement e in elem.Elements()) { PrintElementV1(e, i++); } } else { Console.WriteLine("{0}: {1}", elem.Name, elem.Value); } } При этом будут пронумерованы все элементы кроме тех, которые не содержат в себе других элементов. 2. Фиксированный обход дерева XML С точки зрения дерева, рекурсия сохраняется, такова уж структура дерева, но если эта структура фиксирована и известна, то можно обойтись без рекурсивного вызова методов а использовать цепочку вызовов в цикле. Покажу на примере: static void Main(string[] args) { XElement doc = XElement.Load(@"H:\test.xml"); Console.WriteLine(doc.Name); PrintCDList(doc); Console.ReadKey(); } static void PrintCDList(XElement elem) { int i = 1; foreach (XElement e in elem.Elements()) { Console.WriteLine("{0}. {1}", i++, e.Name); PrintContent(e); } } static void PrintContent(XElement elem) { foreach (XElement e in elem.Elements()) { Console.WriteLine("{0}: {1}", e.Name, e.Value); } } как видите, рекурсия отсутствует, но если структура XML будет отличаться от заложенной в коде, "все превратится в тыкву" и будет давать неверные результаты. 3. Ручной парсинг Можно выполнить всю работу руками, получив исходный текст XML в виде текста. Для этого можно воспользоваться любым известным вам способом получения текста из файла. Далее к строке исходного XML текста применяем всевозможные регулярные выражения или другие известные вам способы преобразования строки до получения строки или массива строк нужного вида и выводим полученное. Приводить код данного способа не стану, так как вариантов для подобного решения существует масса, а взглядов на то, как это сделать правильно еще больше. К тому же, я сильно сомневаюсь, что подобный вариант будет существенно производительнее чем два предыдущих, скорее наоборот. Выбирайте какой вариант вам больше подходит =) PS: Если важно использовать именно XmlDocument, пишите в комментарии, дополню соответствующим примером.

Ответ 2



Можно попробовать что-то такое: int i = 1; var xElems = XDocument.Load(file, LoadOptions.SetLineInfo).Descendants("CD"); foreach (var xElem in xElems) { Console.WriteLine($"{i++} - {xElem.Name}"); foreach (var xElem2 in xElem.Descendants()) { Console.WriteLine($"{xElem2.Name} - {xElem2.Value}"); } }

Комментариев нет:

Отправить комментарий