Как стать автором
Обновить

Комментарии 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);

Исходники есть на гитхабе
И с другой семантикой: теги надо закрывать самому.
Думаю, тут можно навернуть что-то типа:
<code>
element page = xml 
    (html,
        (head,
            (title,
                "Vasya Pupkin's home page")),
        (body,
            (h1, align("center"),
                "Welcome to my home page!!!")));
</code>

Что, конечно, не сильно лучше, но выглядит более легковесно.
Очень похоже на (fab) :)
О, ещё вспомнил. Есть библиотека xsmell, там синтаксис ещё больше похож на XML:
document doc = 
    _
    <html>_
        <head>_
            <title>"XSMELL demo"<!title>_
        <!head>_
        <body>_
            <p>"Yesssssssssssssssss!"<!p>_
            <img .src("chucknorris.png") .alt("sneezing eyes open")>_ <!img>_
        <!body>_
    <!html>
    _;
Да, к такому тоже приходил, и без _ похоже не решаемая задача :)

— не парсится
-- не парсится, пардон.
Не парсится вот это:
<head><html>

Тысяча извинений!
Машинерия красивая, одобряю. А зачем, если не секрет? Обычно для таких задач описывают сериализумые объекты на каком-нибудь google protocol buffers после чего перед компиляцией препроцессором генерируют необходимый код в котором красивые C++ные объекты с методами toXml() и fromXml().
Руки бы поотрывал за такие красивые обьекты! Сериализовывать и парсить фабрики должны, а то потом будет куча обьектов с toXml, toJSON, toVasyaPupkinObjectNotation!
Какая разница, если эти объекты и их методы создает генератор из описания? Фабрики — введение лишней сущности которое должно быть чем то обусловлено. Желание отрывать руки — вроде как недостаточный повод для введения еще и фабрик :). С этим обычно к психотерапевту обращаются ^_^.
Сущность эта обусловлена тем, что один и тот же обьект нужно сериализовывать и парсить во множество форматов. И вообще, по хорошему обьект не должен знать ни о каком формате своего хранения.
Экий вы, батенька, прыткий — сами задачи придумываете, сами им решения даете :). Объект может себе позволить ничего не знать о формате хранения только если у нас есть какое-нибудь introspection чтобы внимательно изучить его внутреннюю структуру. А вот если мы пишем не на C# и под рукой нету Qt (например, как автор статьи — на C++), то кодогенерация — самое то. Формат хранения один раз прописывается в кодогенераторе, после чего объем сгенерированного кода никого не волнует. А вызывается напрямую у объета toXml или это делате какой-нибудь абстрактный слой — это уже от совсем других архитектурных вещей зависит.
А не надо считать сериализуемые в XML struct'ы объектами. Это не объекты, а сгруппированные basic/POD types, которые кроме сериализации ничего и не умеют.
Считайте, что это не объект, а ассоциативный массив с намертво прописанными ключами (полями класса/структуры). slave data structure, не более того.
Остроумное использование перегрузки.
Хотел было съехидничать по поводу заново изобретённого boost::serialization, но потом вспомнил, что в нём нет таких залихватских трюков с переопределением операторов. Снимаю перед автором шляпу.
В свое время игрался с С++. Пытался максимально воспользоваться его статикой.

В результате удалось написать «парсер» 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.

Но вообще решение очень красивое, получайте плюс :) Если не жалко, опубликуйте исходники, кому-нибудь да пригодится.
Класс называется 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, но можно и на что-нибудь другое переложить.

Хочу попробовать что-нибудь сделать со списками инициализации…
Я вынужден был отказаться от QtXml после того, как обнаружил абсолютную невменяемость работы с пространствами имён в QDom*. Разработчики из KDAB в своём KDSoap это тоже обнаружили и используют XMLStream (и я с ними, так как довольно активно дорабатываю эту библиотеку). Так что рекомендую :)
Да, с точку с запятой промахнулся, каюсь.
Да, жир хорошо убирается в языках с повышенным содержанием сахара.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории