Комментарии 27
Что тут скажешь — здорово!
Я какое-то время назад делал такую же штуку, только с другим синтаксисом. Вот пример:
Исходники есть на гитхабе
element page = xml
(html)
(head)
(title)
["Vasya Pupkin's home page"]
(!title)
(!head)
(body)
(h1,align="center")
["Welcome to my home page!!!"]
(!h1)
(!body)
(!html);
Исходники есть на гитхабе
Машинерия красивая, одобряю. А зачем, если не секрет? Обычно для таких задач описывают сериализумые объекты на каком-нибудь google protocol buffers после чего перед компиляцией препроцессором генерируют необходимый код в котором красивые C++ные объекты с методами toXml() и fromXml().
Руки бы поотрывал за такие красивые обьекты! Сериализовывать и парсить фабрики должны, а то потом будет куча обьектов с toXml, toJSON, toVasyaPupkinObjectNotation!
Какая разница, если эти объекты и их методы создает генератор из описания? Фабрики — введение лишней сущности которое должно быть чем то обусловлено. Желание отрывать руки — вроде как недостаточный повод для введения еще и фабрик :). С этим обычно к психотерапевту обращаются ^_^.
Сущность эта обусловлена тем, что один и тот же обьект нужно сериализовывать и парсить во множество форматов. И вообще, по хорошему обьект не должен знать ни о каком формате своего хранения.
Экий вы, батенька, прыткий — сами задачи придумываете, сами им решения даете :). Объект может себе позволить ничего не знать о формате хранения только если у нас есть какое-нибудь introspection чтобы внимательно изучить его внутреннюю структуру. А вот если мы пишем не на C# и под рукой нету Qt (например, как автор статьи — на C++), то кодогенерация — самое то. Формат хранения один раз прописывается в кодогенераторе, после чего объем сгенерированного кода никого не волнует. А вызывается напрямую у объета toXml или это делате какой-нибудь абстрактный слой — это уже от совсем других архитектурных вещей зависит.
А не надо считать сериализуемые в XML struct'ы объектами. Это не объекты, а сгруппированные basic/POD types, которые кроме сериализации ничего и не умеют.
Остроумное использование перегрузки.
Хотел было съехидничать по поводу заново изобретённого boost::serialization, но потом вспомнил, что в нём нет таких залихватских трюков с переопределением операторов. Снимаю перед автором шляпу.
Это eDSL.
В свое время игрался с С++. Пытался максимально воспользоваться его статикой.
В результате удалось написать «парсер» XML, который по ходу его использования проверят статически, как его используют.
Идея была следующяя:
Шаблон element специализируется именем, свойствами, типом, способом сериализации и еще предком.
Шаблон аттрибут очень похож на элемент
Есть еще специальные шаблоны для автовыбора значения, подстановок и тд.
Все хочу написать статью. Есть в этом некоторая соль, что ты одновременно анализируешь XML и используешь значение ее узлов, при этом компилятор проверят, что ты не ошибся (ранее описываешь всю структуру XML). Красиво, но вот эффективнее ли это с точки зрения коды — большой вопрос. Но в результате я это использую в наших проектах.
В результате удалось написать «парсер» XML, который по ходу его использования проверят статически, как его используют.
Идея была следующяя:
Шаблон element специализируется именем, свойствами, типом, способом сериализации и еще предком.
Шаблон аттрибут очень похож на элемент
Есть еще специальные шаблоны для автовыбора значения, подстановок и тд.
Все хочу написать статью. Есть в этом некоторая соль, что ты одновременно анализируешь XML и используешь значение ее узлов, при этом компилятор проверят, что ты не ошибся (ранее описываешь всю структуру XML). Красиво, но вот эффективнее ли это с точки зрения коды — большой вопрос. Но в результате я это использую в наших проектах.
Мне всё-таки кажется, что моё решение ещё лаконичнее, читаемей и универсальнее, чем описанные в посте и первых комментариях:
Исходники покажу, если кому интересно.
XML request =
XML("book")
("isbn", "123456789")
("name", "Some book")
("year", 2011)
[
XML("author")
("name", "Freddy")
("surname", "Smith")
][
XML("author")
("name", "Bill")
("surname", "Joe")
][
XML("quote")
[ "This is the best unknown book I've ever quoted!" ]
[ XML("author") ("name", "Mr. Bob") ];
]
Исходники покажу, если кому интересно.
Ну, неуниверсальность решения состоит в том, что имя класса XML не предполагает наличие ещё и парсера в той же библиотеке. Да и сложно, наверное, будет сделать полноценный парсер в таком вот синтаксисе, разве что на ядрёной смеси DOM и XQuery.
Но вообще решение очень красивое, получайте плюс :) Если не жалко, опубликуйте исходники, кому-нибудь да пригодится.
Но вообще решение очень красивое, получайте плюс :) Если не жалко, опубликуйте исходники, кому-нибудь да пригодится.
Класс называется
Вспомнил, что исходник уже выкладывал в составе одной своей библиотечки: code.google.com/p/romashka/.../XmlGenerator.h.
Чуть раньше я экспериментировал с препроцессорной магией:
Но синтаксис получился слишком уж неродным для C++.
Я всё строил поверх библиотеки QtXml, но можно и на что-нибудь другое переложить.
Хочу попробовать что-нибудь сделать со списками инициализации…
XmlGenerator
, а XML
— тайпдеф к нему. Можно затайпдефить хоть _
.Вспомнил, что исходник уже выкладывал в составе одной своей библиотечки: code.google.com/p/romashka/.../XmlGenerator.h.
Чуть раньше я экспериментировал с препроцессорной магией:
QDomDocument sugarxml = QXML"html"
> (QXML"head"
<"title"> "Test page")
> (QXML"body"
<"h1"> "Hello world!"
> (QXML"ul"
<"li"> (QXML"a"
<"@href"> "http://cblp.su/"
> "cblp's page"
)
<"li"> (QXML"<a href=\"http://qt.nokia.com/\">Qt home</a>")
)
);
Но синтаксис получился слишком уж неродным для C++.
Я всё строил поверх библиотеки QtXml, но можно и на что-нибудь другое переложить.
Хочу попробовать что-нибудь сделать со списками инициализации…
Да, с точку с запятой промахнулся, каюсь.
Мне очень понравился подход, реализованный в groovy
Вот уж точно обезжиренно =)
groovy.codehaus.org/Creating+XML+using+Groovy%27s+MarkupBuilder
Вот уж точно обезжиренно =)
groovy.codehaus.org/Creating+XML+using+Groovy%27s+MarkupBuilder
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
DSL для XML в C++