четверг, 26 ноября 2009 г.

[comp.prog.flame] Для меня XML, как для некоторых C++ ;)

Вдогонку к моему вчерашнему выплеску ненависти к XML.

Долго думал над комментарием ув.тов.Зверька. Пришел к выводу, что это у меня такое же субъективное неприятие XML, как у многих программистов неприятие C++ ;)

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

Правда же, все вышесказанное отлично подходит под C++? ;) Хотя я об XML. А мог бы и о Java ;)

PS. А все-таки мне бы для работы с XML данными в С++ хотелось бы иметь простой, легкий в освоении и бесплатный инструмент, который бы позволял писать как-то так:

/*
 * Разбор XML-сообщений вида:
 *
 * <message>
 *   <report>
 *     <status date="...">OK</status>
 *   </report>
 * </message>
 *
 * или
 *
 * <message>
 *   <report>
 *     <status errorCode="..." description="...">...</status>
 *   </report>
 * </message>
 */
AutoPtr< Document > doc = parse_document_from_stream( message_stream );
element_proxy_t status =
  root( *doc, EL_MESSAGE )
    .single_mandatory_element( EL_REPORT )
    .single_mandatory_element( EL_STATUS );
if( EL_STATUS_OK == status.text() )
  handle_success( status.mandatory_attribute( EL_ATTR_DATE ) );
else
  handle_failure(
    status.text(),
    status.mandatory_attribute< int >( EL_ATTR_ERROR_CODE ),
    status.mandatory_attribute( EL_ATTR_ERROR_DESCRIPTION ) );

PPS. У меня есть маленькая просьба. Я знаю, что мой блог читают и не C++ программисты. Обращаюсь к ним: поделитесь, плз, ссылочками на хорошие описания разных способов работы с XML в других статически-типизированных языках (C#, Java, OCaml или F#). Какие-нибудь статьи, чтобы прочитать и просто составить мнение о том, что в мире делается. Чтобы узнать, до чего, так сказать, передовая мысль дошла ;)

4 комментария:

Анонимный комментирует...

Совсем недавно появилось в Boost, возможно, это тебе подойдет. Там есть парсинг из XML.

http://www.boost.org/doc/libs/1_41_0/doc/html/property_tree.html

eao197 комментирует...

На вскидку, там такая же беда, как и у Poco::Utils::XMLConfiguration: пути к ключам/тегам приходится хардкодить в виде строк (парсинг которых выполняется при каждом обращении).

Т.е. программиста вынуждают писать в стиле:

error_code = m.get<int>( "message.report.status.errorCode" );
error_desc = m.get( "message.report.status.errorDescription" );

Если человек захочет вынести имена тегов из кода в константы, то как ему это делать?

const std::string error_code_path( "message.report.status.errorCode" );
const std::string error_code_desc( "message.report.status.errorDescription" );

Или же:

#define MESSAGE "message"
#define REPORT "report"
#define STATUS "status"
#define DOT "."

const std::string error_code_path( MESSAGE DOT REPORT DOT STATUS DOT "errorCode" );
const std::string error_code_desc( MESSAGE DOT REPORT DOT STATUS DOT "errorDescription" );

Утрирую, конечно, но суть такая -- мне не нравится указание полных путей к значению. Имхо, это не правильно.

Анонимный комментирует...

А вы не думали об использовании xslt? Для конкретной задачи не подойдёт идея дёргать из xslt преобразования функции на плюсах? Мы использовали xalan для целей преобразования xml с вычислениями на плюсах, всё в меру удобно.
Понятно, что в вашей задаче само преобразование не нужно, но тем не менее.

eao197 комментирует...

>А вы не думали об использовании xslt?

Чесно говоря, не думал. Имхо, это был бы какой-то слишком навороченный комбайн -- подключить XSLT, чтобы преобразовать XML в какой-то другой формат, затем разобрать этот формат... Через чур все это.

В моем случае лучше всего бы подошел XPath, но чтобы его использовать в С++ пришлось бы тянуть в проект libxml2. Проще оказалось сделать чуть больше телодвижений с помощью POCO.