LINUX.ORG.RU

Конвертировать INI в XML.


0

0

Знаю Python и C++, задача - перевести INI файл в XML. Трудность в наличии комментариев в INI. Там перед каждым параметром несколько строк, начинающихся с «//» в качестве комментария для данного параметра. Структура XML простая. Есть какая-нибудь библиотека для Python, которая может комментарии из INI доставать? И какая-нибудь библиотека, которая может записывать XML с комментариями в любом месте?

Можно для C++ то же самое.

Спасибо!

★☆

Последнее исправление: kiverattes (всего исправлений: 1)

[offtop]
Может, не надо? Зачем усугублять? [/offtop]

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от kiverattes

План встудию

да, без него бывает совсем худо

anonymous
()

Решение за пару минут. Не универсальное, конечно.

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

namespace IniToXml
{
    class Program
    {
        static void Main()
        {
            const string input = @"C:\\Users\\c0deCrew\\Desktop\\input.ini";
            const string output = @"C:\\Users\\c0deCrew\\Desktop\\output.xml";

            var lines = File
                .ReadAllLines(input, Encoding.Default)
                .Where(s => !string.IsNullOrWhiteSpace(s))
                .Where(s => !(s.StartsWith(";") || s.StartsWith("//")));

            var dict = new Dictionary<string, List<string>> {{string.Empty, new List<string>()}};
            string currSection = string.Empty;

            foreach (string line in lines)
            {
                if (line.StartsWith("[") && line.EndsWith("]"))
                {
                    string sectionName = line.Substring(1, line.Length - 2);
                    if (!dict.ContainsKey(sectionName))
                        dict.Add(sectionName, new List<string>());
                    currSection = sectionName;
                }
                else
                    dict[currSection].Add(line);
            }

            var doc = new XmlDocument();
            XmlElement root = doc.CreateElement("root");
            foreach (KeyValuePair<string, List<string>> kvp in dict)
            {
                XmlElement sect = doc.CreateElement("section");
                XmlAttribute nameAttrib = doc.CreateAttribute("name");
                nameAttrib.Value = kvp.Key;
                sect.Attributes.Append(nameAttrib);

                foreach (string s in kvp.Value)
                {
                    string[] pair = s.Split(new[] { "=" }, StringSplitOptions.RemoveEmptyEntries);
                    XmlElement node = doc.CreateElement(pair[0].Trim());
                    node.InnerText = pair[1].Trim();
                    sect.AppendChild(node);
                }

                root.AppendChild(sect);
            }
            doc.AppendChild(root);
            doc.Save(output);
        }
    }
}

// NightmareZ

anonymous
()
Ответ на: комментарий от mv

на sed решение данной задачи займёт строчку байтов так на 256... ну а уж просто комменты убрать, это вообще смешно.

drBatty ★★
()

То есть тебе нужно и комментарии копировать?

anonymous
()

Либо я плохо представляю, что такое INI, либо парсер пишется за 30 - 120 минут в зависимости от требований и скиллов программиста. На любом нормальном языке. На С++ точно, на питоне, я думаю, быстрее, хотя сам питона не знаю.

DELIRIUM ☆☆☆☆☆
()
Ответ на: комментарий от DELIRIUM

Либо я плохо представляю, что такое INI, либо парсер пишется за 30 - 120 минут в зависимости от требований и скиллов программиста.

Ты абсолютно правильно понимаешь, что такое INI.

mv ★★★★★
()

Информацию о структуре XML выложишь?

anonymous
()

regexp

import re
print "<my_ini>"
last = ''
for l in open(infile).readlines():
     obj = re.match("[(?P=<xyz>.*)]")
     if obj:
             if last!="":
                  print "</"+last+">"
             last = obj.to_hache()["xyz"]
             print "<"+last+">"
     else:
         obj = re.match("(?P=<k>.*\)=(?P=<v>)")
         if obj:
             print "<val "+k+"="+v+"/>"
        else:
             print "<!--",l, "-->"

Ну там еще проверку на пробелы sax quoteattr и так далее. Идея понятна?

demmsnt
()
Ответ на: комментарий от DELIRIUM

DELIRIUM

на питоне, я думаю, быстрее, хотя сам питона не знаю.

на пайтоне быстрее однозначно. А ещё быстрее на специализированных под эту задачу perl & sed. Да и в рантайме получится по крайне мере не медленнее сишного велосипеда.

drBatty ★★
()

Знаю Python

configparser?

anonymous
()

Не понял чем моё не устроило?

demmsnt
()
Ответ на: комментарий от DELIRIUM

DELIRIUM

Да, на перле быстрее, чем на С++ однозначно, знаю перл.

С++ - конечно. эта STL содержит 100500 костылей на все случаи жизни, и ВСЕ они включаются в проект. Ибо шаблоны.

Но на С при желании можно сделать конфетку. За неделю. Другое дело, что на sed или perl это будет работать вдвое медленнее, и писаться полчаса. А скорость рантайма совсем не всегда решает.

DELIRIUM

Но ТС про него ничего не писал

может просто не знал?

drBatty ★★
()
Ответ на: комментарий от anonymous

anonymous

Хм... а разве для большинства языков нет готовых парсеров?

есть конечно. А какой смысл разбираться месяц в чужом парсере, если свой скрипт пишется за 5 минут, не имеет зависимостей, не требует сборки, и работает везде? Причём как правило ещё и быстрее.

drBatty ★★
()
Ответ на: комментарий от drBatty

и ВСЕ они включаются в проект. Ибо шаблоны.

на ЛОР можно заходить просто, чтоб поулыбаться с местных «специалистов»

anonymous
()
Ответ на: комментарий от anonymous

anonymous

на ЛОР можно заходить просто, чтоб поулыбаться с местных «специалистов»

аноны тоже не те. Да, в хеловорлдах компилятор выкинет всё лишнее, тут я согласен.

drBatty ★★
()
Ответ на: комментарий от drBatty

эта STL содержит 100500 костылей на все случаи жизни, и ВСЕ они включаются в проект. Ибо шаблоны.

с каких пор неиспользуемые шаблоны компилируются?

seed_stil ★★
()
Ответ на: комментарий от drBatty

Да, в хеловорлдах компилятор выкинет всё лишнее, тут я согласен.

а где не выкинет? и почему?

seed_stil ★★
()
Ответ на: комментарий от hippi90

Код в студию!

Ты што! Это ж интеллектуальная пропердь!

mv ★★★★★
()
Ответ на: комментарий от seed_stil

seed_stil

с каких пор неиспользуемые шаблоны компилируются?

ладно, про «ВСЕ» я что-то погорячился. Но много мусора, всё равно. И на скорости это таки отражается заметно.

seed_stil

а где не выкинет? и почему?

в сложных участках не распарсит, что надо, а что не надо.

drBatty ★★
()
Ответ на: комментарий от drBatty

в сложных участках не распарсит, что надо, а что не надо.

шаблон компилируется при инстанцировании, т.е. только при использовании

anonymous
()
Ответ на: комментарий от anonymous

шаблон компилируется при инстанцировании, т.е. только при использовании

Опередил =)

DELIRIUM ☆☆☆☆☆
()
Ответ на: комментарий от drBatty

эта STL содержит 100500 костылей на все случаи жизни, и ВСЕ они включаются в проект.

Какие такие костыли, которые включаются в проект?

Deleted
()
Ответ на: комментарий от drBatty

ладно, про «ВСЕ» я что-то погорячился. Но много мусора, всё равно.

Неиспользуемые шаблоны вообще не компилируются. Используемые - не мусор.

И на скорости это таки отражается заметно.

Шаблоны на скорости выполнения не отражаются вообще никак, только на скорости компиляции.

Deleted
()
Ответ на: комментарий от Deleted

Шаблоны на скорости выполнения не отражаются вообще никак,

На самом деле могут при использовании ФВП, у компилятора больше возможностей оптимизировать std::sort встроив вызовы функции сравнения, чем qsort.

Begemoth ★★★★★
()
Ответ на: комментарий от Begemoth

ФВП

???

у компилятора больше возможностей оптимизировать std::sort встроив вызовы функции сравнения

Это да, но это скажется на быстродействии только положительно, а не отрицательно.

BTW, std::sort - в большинстве реализаций пирамидальная сортировка, имеющая сложность O(NlogN) в худшем случае, а qsort имеет сложность O(N^2) в худшем случае (при этом в среднем случае - тот же NlogN). Поэтому qsort, по крайней мере, на некоторых тесткейсах сливает std::sort-у.

Deleted
()
Ответ на: комментарий от Deleted

???

Функции высшего порядка, же, т.е. функции аргументами или резултатом которых являются функции (или функциональные объекты).

Begemoth ★★★★★
()
Ответ на: комментарий от anonymous

anonymous

шаблон компилируется при инстанцировании, т.е. только при использовании

безусловно. Но компилируется он ВЕСЬ, а не частями. Если кодер использовал хотя-б по одному разу каждый из шаблонов STL (а там их не так и много), то все они будут откомпилированы. Безусловно, оптимизирующий компилятор выкинет 80% ненужного мусора, и тем не менее
1. где гарантия того, что оптимизирующий компилятор справиться со своей задачей на 100%? Это для нас очевидно, что мы не применяем метод STL::xyz(), а значит он нам и не нужен, и мы про него и не задумываемся. А вот компилятор видит этот метод, и «думает» - а нужен-ли он, или нет? Т.е. ищет, где-же он таки применяется. В сложных случаях он может и «сомневаться», и тогда естественно включает его в результат.
2. Время компиляции. На рантайм оно понятно не влияет, но вот на скорость разработки - очень даже. Кодеру приходится ждать, пока компилятор выкинет эти 80% ненужного кода, который, ЧСХ, этот кодер и не писал. Ессно это не радостно влияет на качество готового ПО.
3. Немало доставляют неоднозначности - по логике моей программы, метод xyz(int) принимает исключительно целые числа. И у меня всё работает. И если числа нет, или это не int, компилятор мне об этом докладывает. С шаблонами типа STL так не бывает: там метод перезагружен Over9000 раз, и может принимать всё что угодно. Но об этом я узнаю уже в рантайме - здравствуй, дебагер!

franchukroman

Неиспользуемые шаблоны вообще не компилируются. Используемые - не мусор.

1. как я уже писал, в достаточно сложных проектах используются все шаблоны.
2. те шаблоны что используются, используются на 20%. Остальное получается - мусор.

franchukroman

Шаблоны на скорости выполнения не отражаются вообще никак, только на скорости компиляции.

только в идеально-сферическом случае, когда компилятор вычищает мусор на 100%. Такое бывает только в хелловорлдах.

franchukroman

std::sort - в большинстве реализаций пирамидальная сортировка, имеющая сложность O(NlogN) в худшем случае, а qsort имеет сложность O(N^2) в худшем случае (при этом в среднем случае - тот же NlogN). Поэтому qsort, по крайней мере, на некоторых тесткейсах сливает std::sort-у.

С другой стороны, в подавляющем количестве тесткейсов, пирамидальная сливает быстрой.

И да, я не против STL, просто не надо заколачивать гвозди микроскопом, и пихать её везде. Например не надо пихать её в сишную программу ТС.

drBatty ★★
()
Ответ на: комментарий от drBatty

где гарантия того, что оптимизирующий компилятор справиться
со своей задачей на 100%? Это для нас очевидно, что мы не
применяем метод STL::xyz(), а значит он нам и не нужен, и мы
про него и не задумываемся. А вот компилятор видит этот метод,
и «думает» - а нужен-ли он, или нет? Т.е. ищет, где-же он таки
применяется. В сложных случаях он может и «сомневаться», и
тогда естественно включает его в результат.

Сомневающийся конечный автомат - это зачот, дайте две.

Время компиляции. На рантайм оно понятно не влияет, но вот на
скорость разработки - очень даже. Кодеру приходится ждать,
пока компилятор выкинет эти 80% ненужного кода, который, ЧСХ,
этот кодер и не писал. Ессно это не радостно влияет на качество
готового ПО.

Приведите конкретный пример. Кодера, который ждал и его ПО, качество которого упало именно из-за долгой сборки проекта.

Немало доставляют неоднозначности - по логике моей программы,
метод xyz(int) принимает исключительно целые числа. И у меня всё
работает. И если числа нет, или это не int, компилятор мне об этом
докладывает. С шаблонами типа STL так не бывает: там метод
перезагружен Over9000 раз, и может принимать всё что угодно. Но
об этом я узнаю уже в рантайме - здравствуй, дебагер!

В программе, даже с шаблонами, нет неоднозначностей, есть недопонимание.

Например не надо пихать её в сишную программу ТС.

Почему не надо? Я что, просил маленькую программу, которая быстро работает? Если STL позволяет решить задачу быстро, мне вообще пох, хоть десять STL с десятью бустами.

kiverattes ★☆
() автор топика
Ответ на: комментарий от kiverattes

kiverattes

Сомневающийся конечный автомат - это зачот, дайте две.

компилятор конечно ВиУ, без сомнения. Сомневаюсь, что вы хотели именно ЭТОГО.

kiverattes

Приведите конкретный пример. Кодера, который ждал и его ПО, качество которого упало именно из-за долгой сборки проекта.

без комментариев.

kiverattes

В программе, даже с шаблонами, нет неоднозначностей, есть недопонимание.

напишите вторую сотню строк кода, и узнаете, как по английски «неоднозначность». Я гарантирую это.

kiverattes

Почему не надо? Я что, просил маленькую программу, которая быстро работает? Если STL позволяет решить задачу быстро, мне вообще пох, хоть десять STL с десятью бустами.

не надо потому, что много сил, времени и кода уходит на конвертацию типов. В простых случаях проще написать strlen(s), а не городить STL шаблон, только для того, что-бы вычислить длину строки. Даже несмотря на то, что в результате 100500 строчек шаблона всё равно схлопнется до этой strlen().

drBatty ★★
()
Ответ на: комментарий от kiverattes

Приведите конкретный пример. Кодера, который ждал и его ПО, качество которого упало именно из-за долгой сборки проекта.

Да все лисперы будут страдать от того, если им в руки дать что-то отличное от их любимого лиспа. Потому как в лиспе моментальная инкрементная компиляция. Настолько к этому привыкаешь. Нажал на кнопку, и все изменения перекомпилировались тут же.

Ты только представь себе, как бы лисперы мучались, программируя на чем-то тормозном вроде Си++ :)

dave ★★★★★
()
Ответ на: комментарий от drBatty

1. где гарантия того, что оптимизирующий компилятор справиться со своей задачей на 100%? Это для нас очевидно, что мы не применяем метод STL::xyz(), а значит он нам и не нужен, и мы про него и не задумываемся. А вот компилятор видит этот метод, и «думает» - а нужен-ли он, или нет?

Знание С++ на лицо.

не надо потому, что много сил, времени и кода уходит на конвертацию типов.

Если STL использовать систематически, то не уходит.

В простых случаях проще написать strlen(s), а не городить STL шаблон, только для того, что-бы вычислить длину строки.

Простые случаи имеют свойство усложняться и тогда std::string гораздо лучше чем char*.

Begemoth ★★★★★
()
Ответ на: комментарий от drBatty

Если кто-либо передаёт в перегруженную функцию тип const char*, а такой сигнатуры нет и вызывается функция с аргументом bool, это не неоднозначность, а незнание того, что const char* легко неявно преобразуется в тип bool. Это просто степень знания языка. О том, что C++ требует больше сведений в голове, чем другой язык - написано уже стопицот боянов, не надо повторять, что на нём писать сложно и проблемно, это ясно уже стопицот лет до вас (-;

kiverattes ★☆
() автор топика
Ответ на: комментарий от kiverattes

kiverattes

Если кто-либо передаёт в перегруженную функцию тип const char*, а такой сигнатуры нет и вызывается функция с аргументом bool, это не неоднозначность, а незнание того, что const char* легко неявно преобразуется в тип bool. Это просто степень знания языка.

я говорю про опечатки, а не про намеренное использование не того типа. В своём классе это будет выловлено сразу.

Begemoth

Если STL использовать систематически, то не уходит.

да говорю-же - я не против STL, и не собираюсь тут холивар разжигать. В этой задачке STL как раз к месту, и все накладные расходы не играют никакой роли (обычно не бывает больших INI файлов).

PS: так мне кто-нить даст 2 файла: то, что надо преобразовать, и что должно получится? Попробуем perl & sed, и сравним.

drBatty ★★
()
Ответ на: комментарий от Begemoth

Знание С++ на лицо.

Вы так любите кресты, что без Фрейда не обошлось?

anonymous
()

Какое-то мудло потёрло половину сообщений.

anonymous
()
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;

namespace IniToXml
{
    public sealed class Program
    {
        /// <summary>
        /// Read program arguments (input and output filenames).
        /// </summary>
        private static Tuple<string, string> ReadArgs(string[] args)
        {
            if (args == null || args.Length != 2)
            {
                Console.WriteLine(@"Invalid command syntax.");
                return null;
            }

            if (!File.Exists(args[0]))
            {
                Console.WriteLine(@"Input file not found.");
                return null;
            }

            return new Tuple<string, string>(args[0], args[1]);
        }

        public static void Main(string[] args)
        {
            Tuple<string, string> files = ReadArgs(args);
            if (files == null)
                Environment.Exit(1);

            // Read input file and remove empty lines.
            var lines = File
                .ReadAllLines(files.Item1, Encoding.Default)
                .Select(s => s.Trim())
                .Where(s => !string.IsNullOrWhiteSpace(s));

            string currSection = string.Empty;
            // Dictionary (
            //    section name,
            //    pair (
            //        list of pairs (
            //            pair (
            //                item name,
            //                item value
            //            ),
            //            list of comments for item
            //        ),
            //        list of comments for section
            //    )
            // )
            var dict = new Dictionary<string, Tuple<List<Tuple<Tuple<string, string>, List<string>>>, List<string>>>
            {
                {
                    currSection, new Tuple<List<Tuple<Tuple<string, string>, List<string>>>, List<string>>(
                        new List<Tuple<Tuple<string, string>, List<string>>>(), new List<string>())
                }
            };
            var comments = new List<string>();

            // Parse input lines and fill dictionary.
            foreach (string line in lines)
            {
                if (line.StartsWith(";"))
                    comments.Add(line.Substring(1));
                else if (line.StartsWith("//"))
                    comments.Add(line.Substring(2));
                else if (line.StartsWith("[") && line.EndsWith("]"))
                {
                    currSection = line.Substring(1, line.Length - 2);
                    if (!dict.ContainsKey(currSection))
                        dict.Add(currSection, new Tuple<List<Tuple<Tuple<string, string>, List<string>>>, List<string>>(
                            new List<Tuple<Tuple<string, string>, List<string>>>(), comments));
                    comments = new List<string>();
                }
                else
                {
                    string[] pair = line.Split(new[] { "=" }, StringSplitOptions.RemoveEmptyEntries);
                    dict[currSection].Item1.Add(new Tuple<Tuple<string, string>, List<string>>(
                        new Tuple<string, string>(pair[0].Trim(), pair[1].Trim()),
                        comments));
                    comments = new List<string>();
                }
            }
anonymous
()
Ответ на: комментарий от anonymous
// Remove default (nameless) section if they are empty.
            if (dict[string.Empty].Item1.Count == 0)
                dict.Remove(string.Empty);

            var doc = new XmlDocument();
            XmlElement root = doc.CreateElement("root");
            foreach (KeyValuePair<string, Tuple<List<Tuple<Tuple<string, string>, List<string>>>, List<string>>> kvp in dict)
            {
                foreach (string sectCommentText in kvp.Value.Item2)
                    root.AppendChild(doc.CreateComment(sectCommentText));

                XmlElement sectNode = doc.CreateElement("section");
                XmlAttribute sectNameAttrib = doc.CreateAttribute("name");
                sectNameAttrib.Value = kvp.Key;
                sectNode.Attributes.Append(sectNameAttrib);

                var createdItemsArrays = new List<string>();

                foreach (Tuple<Tuple<string, string>, List<string>> item in kvp.Value.Item1)
                {
                    if (item.Item1.Item1.EndsWith("[]"))
                    {
                        // Output array.

                        if (!createdItemsArrays.Contains(item.Item1.Item1))
                        {
                            string arrayName = item.Item1.Item1.Substring(0, item.Item1.Item1.Length - 2);
                            XmlElement arrayNode = doc.CreateElement("array");
                            XmlAttribute arrayNameAttrib = doc.CreateAttribute("name");
                            arrayNameAttrib.Value = arrayName;
                            arrayNode.Attributes.Append(arrayNameAttrib);

                            var arrayItems = from x in kvp.Value.Item1
                                             where x.Item1.Item1.Substring(0, x.Item1.Item1.Length - 2) == arrayName
                                             select x;

                            foreach (Tuple<Tuple<string, string>, List<string>> arrayItem in arrayItems)
                            {
                                foreach (string itemCommentText in arrayItem.Item2)
                                    arrayNode.AppendChild(doc.CreateComment(itemCommentText));

                                XmlElement itemNode = doc.CreateElement("item");
                                itemNode.InnerText = arrayItem.Item1.Item2;
                                arrayNode.AppendChild(itemNode);
                            }

                            sectNode.AppendChild(arrayNode);
                            createdItemsArrays.Add(item.Item1.Item1);
                        }
                    }
                    else
                    {
                        // Output single item.

                        foreach (string itemCommentText in item.Item2)
                            sectNode.AppendChild(doc.CreateComment(itemCommentText));

                        XmlElement itemNode = doc.CreateElement("item");
                        XmlAttribute itemNameAttrib = doc.CreateAttribute("name");
                        itemNameAttrib.Value = item.Item1.Item1;
                        itemNode.Attributes.Append(itemNameAttrib);
                        itemNode.InnerText = item.Item1.Item2;
                        sectNode.AppendChild(itemNode);
                    }
                }

                root.AppendChild(sectNode);
            }
            doc.AppendChild(root);
            doc.Save(files.Item2);
        }
    }
}

// NightmareZ

anonymous
()

Структура XML простая

Толсто. Хотя...

C++

Хотя может быть и нет.

quantum-troll ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.