XML

XML (МФА: , аббр. от ) — «расширяемый язык разметки». Рекомендован Консорциумом Всемирной паутины (W3C). Спецификация XML описывает XML-документы и частично описывает поведение XML-процессоров (программ, читающих XML-документы и обеспечивающих доступ к их содержимому). XML разрабатывался как язык с простым формальным синтаксисом, удобный для создания и обработки документов как программами, так и человеком, с акцентом на использование в Интернете. Язык называется расширяемым, поскольку он не фиксирует разметку, используемую в документах: разработчик волен создать разметку в соответствии с потребностями к конкретной области, будучи ограниченным лишь синтаксическими правилами языка. Расширение XML — это конкретная грамматика, созданная на базе XML и представленная словарём тегов и их атрибутов, а также набором правил, определяющих, какие атрибуты и элементы могут входить в состав других элементов. Сочетание простого формального синтаксиса, удобства для человека, расширяемости, а также базирование на кодировках Юникод для представления содержания документов привело к широкому использованию как, собственно, XML, так и множества производных специализированных языков на базе XML в самых разнообразных программных средствах.

XML является подмножеством SGML.

Файлы в формате XML используется при проектировании структуры программ, в частности, концептуальных карт и диаграмм связей,

Язык XML 
Спецификация XML описывает язык и ряд вопросов, касающихся кодировки и обработки документов. Материал этой секции представляет собой сокращённое изложение описания языка в Спецификации XML, адаптированное для настоящей статьи.

Нормативным считается английский вариант документа, поэтому основные термины приводятся с их английскими оригиналами.

Перевод основных терминов в основном следует доступному в интернете переводу Спецификации на русский язык, исключение составляют термины tag и declaration. Для термина tag здесь используется перевод тег. Для термина declaration отдано предпочтение распространённому переводу объявление (против также распространённой кальки декларация).

В литературе и интернете могут встречаться и иные переводы основных терминов.

Физическая и логическая структуры документа 
С физической точки зрения документ состоит из сущностей (), из которых каждая может ссылаться на другую сущность. Единственный корневой элемент — документная сущность.
Содержание сущностей — символы.

С логической точки зрения документ состоит из комментариев (), объявлений (), элементов  (), ссылок на сущности () и инструкций обработки (). Всё это в документе структуризуется разметкой  ().

Физическая структура 
Сущность — мельчайшая часть в документе. Все сущности что-нибудь содержат, и у всех них есть имя (существуют исключения, напр. документная сущность). Проще говоря, термин «сущность» описывает «сущую вещь», «что-то».

Документ состоит из сущностей, содержание которых — символы. Все символы разделены на два типа: символы данных () и символы разметки.
К разметке относятся: 
теги () <- обозначают границы элементов
объявления и инструкции обработки, включая их атрибуты ()
ссылки на сущности
комментарии
а также последовательности символов, обрамляющие секции «CDATA»
Часть документа, не принадлежащая разметке, составляет символьные данные документа.

Логическая структура 
Все составляющие части документа обобщаются в пролог и корневой элемент.
Корневой элемент — обязательная часть документа, составляющая всю его суть (пролог, вообще говоря, может отсутствовать). Корневой элемент может включать (а может не включать) вложенные в него элементы, символьные данные и комментарии. Вложенные в корневой элемент элементы, в свою очередь, могут включать вложенные в них элементы, символьные данные и комментарии, и так далее.
Пролог может включать объявления, инструкции обработки, комментарии. Его следует начинать с объявления XML, хотя в определённой ситуации допускается отсутствие этого объявления.

Элементы документа должны быть правильно вложены: любой элемент, начинающийся внутри другого элемента (то есть любой элемент документа, кроме корневого), должен заканчиваться внутри элемента, в котором он начался.
Символьные данные могут встречаться внутри элементов как непосредственно так и в специальных секциях «CDATA».
Объявления, инструкции обработки и элементы могут иметь связанные с ними атрибуты. Атрибуты используются для связывания с логической единицей текста пар имя-значение.

Символы разметки 
Разметка всегда начинается символом < и заканчивается символом >.

Наряду с символами < и >, специальную роль для разметки играет также символ &. Угловые скобки обозначают границы элементов, инструкций обработки и некоторых других последовательностей. Амперсанд позволяет выполнить замену текста при помощи сущностей ().

Решение проблемы неоднозначности разметки 
Употребление разметочных символов в символьных данных затрудняет распознавание конструкций разметки и может создать проблему неоднозначности структуры. В XML эта проблема решается следующим образом: <, > и & не могут присутствовать в символьных данных и в значениях атрибутов в их непосредственном виде, для их представления в этих случаях зарезервированы специальные сущности:

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

Правило замены разметочных символов на их обозначающие сущности не распространяется на символьные данные в секциях «CDATA», зато выполняется во всех остальных местах документа.

Числовые ссылки на символы 
Числовые ссылки на символы указывают кодовую позицию символа в наборе символов документа. Числовые ссылки на символы могут принимать две формы:
 синтаксис «&#D;», где D — десятичное число;
 синтаксис «&#xH;» или «&#XH;», где H — шестнадцатеричное число (шестнадцатеричные числа в числовых символьных ссылках не чувствительны к регистру).

Примеры числовых ссылок на символы:
 &#229; — (в десятичной форме) представляет букву «а» с маленьким кружком над ней (используется, например, в норвежском языке);
 &#xE5; — (в шестнадцатеричном) представляет собой тот же символ;
 &#Xe5; — (в шестнадцатеричном) также представляет тот же символ;
 &#1048; — (в десятичной форме) представляет заглавную букву кириллицы «I»;
 &#x6C34; — (в шестнадцатеричном) представляет китайский иероглиф «вода»;

Имена 
В языке XML все имена должны начинаться с буквы, символа подчёркивания (_) и продолжаться только допустимыми для имён символами, а именно: они могут содержать только буквы, входящие в секцию букв кодировки Unicode, арабские цифры, дефисы, знаки подчёркивания, точки. Так как буквы не ограничены исключительно символами ASCII, то в именах можно использовать буквы из любого языка.

Пролог

Объявление XML 
Объявление XML указывает версию языка, на которой написан документ. Поскольку интерпретация содержимого документа зависит от версии языка, то Спецификация предписывает начинать документ с объявления XML. В первой (1.0) версии языка использование объявления не было обязательным, в последующих версиях оно обязательно. Таким образом, версия языка определяется из объявления, и если объявление отсутствует, то принимается версия 1.0.

Кроме версии XML объявление может также содержать информацию о кодировке документа и «оставаться ли документу со своим собственным DTD, или с подключённым».

Пример:

<?xml version="1.1" encoding="UTF-8" ?>

или:
<?xml version="1.0" encoding="windows-1251"?>

Во всех этих примерах отсутствовал атрибут «standalone», который как раз и определяет, подключить ли документу описания разметки извне. По умолчанию он равен «no»:
<?xml version="1.0" encoding="windows-1251" standalone="no"?>

если XML-документ ссылается на другие DTD-файлы, которые описывают, что документ может содержать, вы должны указать standalone="no"

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

если XML-документ не ссылается на другие файлы и будет пользоваться своим DTD, вы должны указать standalone="yes"

Объявление типа документа 
Для объявления типа документа существует специальная инструкция !DOCTYPE. Она позволяет задать при помощи языка DTD, какие в документ входят элементы, каковы их атрибуты, какие сущности могут использоваться и кое-что ещё.

Например, вот корректный документ:
<?xml version="1.0"?>
<greeting>Hello, world!</greeting>

В нём есть корневой элемент <greeting>Hello, world!</greeting>, и с логической точки зрения документ существует. Однако он недействителен ().

При помощи Объявления типа документа (DTD) возможно описывать его содержание и логическую структуру, а также связывать с определённым элементом пару «имя — значение».
Вот как выглядит пролог в записи Бэкуса — Наура:
prolog        ::= XMLDecl? Misc* (doctypedecl Misc*)?
XMLDecl       ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
VersionInfo   ::= S 'version' Eq ("'" VersionNum "'" | '"' VersionNum '"')
Eq            ::= S? '=' S?
VersionNum    ::= '1.' [0-9]+
Misc          ::= Comment | PI | S
doctypedecl   ::= '<!DOCTYPE' S Name (S ExternalID)? S? ('[' intSubset ']' S?)? '>'
DeclSep       ::= PEReference | S
intSubset     ::= (markupdecl | DeclSep)*
markupdecl    ::= elementdecl | AttlistDecl | EntityDecl | NotationDecl | PI | Comment
extSubset     ::= TextDecl? extSubsetDecl
extSubsetDecl ::= ( markupdecl | conditionalSect | DeclSep)*
После XML-объявления могут следовать комментарии, инструкции обработки или же пустые пространства, но затем идёт Объявления типа документа, где «Name» — имя корневого тега, «ExternalID» — внешний идентификатор, а «intSubset» — объявление разметки или же ссылка на сущность. Как гласит спецификация, если внешний идентификатор объявляется вместе с внутренним объявлением, то последнее идёт перед первым.

Например:
<?xml version="1.0"?>
<!DOCTYPE greeting SYSTEM "hello.dtd">
<greeting>Hello, world!</greeting>

Здесь «SYSTEM "hello.dtd"» — внешний идентификатор: адрес «hello.dtd» позволяет задействовать данные в документе «hello.dtd» как объявления разметки.
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE greeting [
  <!ELEMENT greeting (#PCDATA)>
]>
<greeting>Hello, world!</greeting>
Здесь же разметка была объявлена локально в инструкции !DOCTYPE.

Инструкция обработки 
Инструкции обработки (), позволяют размещать в документе инструкции для приложений.
В следующем примере показана инструкция обработки xml-stylesheet, передающая xml-stylesheet-приложению (например, браузеру) инструкции в файле my-style.css посредством атрибута href:

<?xml-stylesheet type="text/css" href="my-style.css"?>

Комментарий 
Комментарии () не относятся к символьным данным документа.
Комментарий начинается последовательностью «<!--» и заканчивается последовательностью «-->», внутри не может встречаться комбинация символов «--». Символ & не используется внутри комментария в качестве разметки.

Пример:

<!-- это комментарий -->

Корневой элемент

Элемент и его разметка 
Элемент () является понятием логической структуры документа. Каждый документ содержит один или несколько элементов. Границы элементов представлены начальным и конечным тегами. Имя элемента в начальном и конечном тегах элемента должно совпадать. Элемент может быть также представлен тегом пустого элемента, то есть не включающего в себя другие элементы и символьные данные.

Тег () — конструкция разметки, которая содержит имя элемента.

Начальный тег: Конечный тег: 

Тег пустого элемента: 

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

Пример кулинарного рецепта, размеченного с помощью XML:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE recipe>
<recipe name="хлеб" preptime="5min" cooktime="180min">
   <title>
      Простой хлеб
   </title>
   <composition>
      <ingredient amount="3" unit="стакан">Мука</ingredient>
      <ingredient amount="0.25" unit="грамм">Дрожжи</ingredient>
      <ingredient amount="1.5" unit="стакан">Тёплая вода</ingredient>
   </composition>
   <instructions>
     <step>
        Смешать все ингредиенты и тщательно замесить. 
     </step>
     <step>
        Закрыть тканью и оставить на один час в тёплом помещении. 
     </step>
     <!-- 
        <step>
           Почитать вчерашнюю газету. 
        </step>
         - это сомнительный шаг...
      -->
     <step>
        Замесить ещё раз, положить на противень и поставить в духовку.
     </step>
   </instructions>
</recipe>

Секция CDATA 
Секция CDATA не является логической единицей текста.
Секция может встречаться в любом месте документа, где синтаксис позволяет размещать символьные данные. Секция начинается <![CDATA[ и завершается ]]>.
Между этой разметкой находятся символьные данные; символьные данные при этом включают символы < > & в их непосредственной форме.

Корректный документ 
Корректный () документ соответствует всем общим правилам синтаксиса XML, применимым к любому XML-документу: правильная структура документа, совпадение имен в начальном и конечном теге элемента и т. п. Документ, который неправильно построен, не может считаться документом XML.

Пространства имён 
Пример документа:
<?xml version="1.0" encoding="UTF-8"?>
<!-- login screen -->
<edsscript>
   <sequence name="start">
      <action cmd="triggeron">
         btn*
      </action>
      <action cmd="triggeron">
         msg_generic
      </action>
      <action cmd="disablenbb">
         all
      </action>
      <action cmd="setscrtext">
         @@Sisteme Giriş@@
      </action>
      <action cmd="enablenbb">
         forward,mainmenu
      </action>
      <action cmd="switchmsgtarget">
         LOGIN_DLG
      </action>
      <action cmd="sendmsg">
         start
      </action>
      <action cmd="jump">
         step2
      </action>
   </sequence>
   <sequence name="step2">
      <action cmd="waittrigger">
         btnforward
      </action>
      <action cmd="triggeron">
         login*
      </action>
      <action cmd="disablenbb">
         all
      </action>
      <action cmd="sendmsg">
         check
      </action>
   </sequence>
   <trigger name="login_succeded">
      <condition type="appmsg">
         login_succeeded
      </condition>
      <sequence>
         <action cmd="endscript" />
      </sequence>
   </trigger>
   <trigger name="login_unknownuser">
      <condition type="appmsg">
         login_unknownuser
      </condition>
      <sequence name="login_unknownuser">
         <action cmd="disablenbb">
            all
         </action>
         <action cmd="setscrtext">
            @@Hata@@
         </action>
         <action cmd="showhtml">
            generic_neg.htm,@@Yanlış kullanıcı ismi@@,@@Lütfen kullanıcı ismini doğru giriniz.@@
         </action>
         <action cmd="enablenbb">
            back
         </action>
         <action cmd="waittrigger">
            btnback
         </action>
         <action cmd="jump">
            start
         </action>
      </sequence>
   </trigger>
   <trigger name="login_incorrectpwd">
      <condition type="appmsg">
         login_incorrectpwd
      </condition>
      <sequence name="login_incorrectpwd">
         <action cmd="disablenbb">
            all
         </action>
         <action cmd="setscrtext">
            @@Hata@@
         </action>
         <action cmd="showhtml">
            generic_neg.htm,@@Hatalı parola@@,@@Lütfen parolanızı doğru giriniz.@@
         </action>
         <action cmd="enablenbb">
            back
         </action>
         <action cmd="waittrigger">
            btnback
         </action>
         <action cmd="jump">
             start
         </action>
      </sequence>
   </trigger>
   <!-- generic triggers -->
   <trigger name="btnback">
      <condition type="buttonclick">
         back
      </condition>
      <sequence name="btnback">
         <action cmd="triggeron">
            btnback
         </action>
      </sequence>
   </trigger>
   <trigger name="btnforward">
      <condition type="buttonclick">
        forward
      </condition>
      <sequence name="btnforward">
         <action cmd="triggeron">
            btnforward
         </action>
      </sequence>
   </trigger>
   <trigger name="btnmainmenu">
      <condition type="buttonclick">
         mainmenu
      </condition>
      <sequence>
         <action cmd="jumpscript">
            <value label="mainmenuscript" scope="local" />
         </action>
      </sequence>
   </trigger>
   <trigger name="btnquitapp">
      <condition type="buttonclick">
         quitapplication
      </condition>
      <sequence name="btnquitapp">
         <action cmd="callscript">
            quitapp.xml
         </action>
         <action cmd="jump">
            start
         </action>
      </sequence>
   </trigger>
   <trigger name="error_generic">
      <condition type="appmsg">
         error*
      </condition>
      <sequence>
         <action cmd="showhtml">
            errdsc_null.htm,@@Hata@@
         </action>
         <action cmd="disablenbb">
            all
         </action>
         <action cmd="enablenbb">
            forward
         </action>
         <action cmd="waittrigger">
            btnforward
         </action>
         <action cmd="endscript" />
      </sequence>
   </trigger>
   <trigger name="msg_generic">
      <condition type="appmsg">
         msg_generic
      </condition>
      <sequence>
         <action cmd="showhtml">
            generic_msg.htm
         </action>
         <action cmd="triggeron">
            msg_generic
         </action>
      </sequence>
   </trigger>
   <!-- An unhandled exception is thrown from the hard code side. -->
   <trigger name="error_hardcodeside">
      <condition type="appmsg">
         error_hardcodeside
      </condition>
      <sequence>
         <action cmd="triggeroff">
            *
         </action>
         <action cmd="triggeron">
            btnmainmenu
         </action>
         <action cmd="triggeron">
            btnquitapp
         </action>
         <action cmd="disablenbb">
            all
         </action>
         <action cmd="enablenbb">
            mainmenu
         </action>
         <action cmd="showhtml">
            errdsc_null.htm,Hata, @@İşlem sırasında bir hata meydana geldi.@@
         </action>
         <action cmd="waittrigger">
            btnmainmenu
         </action>
      </sequence>
   </trigger>
</edsscript>

Регламентация работы с документами: правила, языки, программные интерфейсы 
Этот раздел содержит изложение некоторых положений рекомендаций W3C, касающихся работы с документами. Соответствующие рекомендации могут относиться как к документам XML, так и к более широкому классу документов. Ссылки, как правило, даются на средства работы с документами, рекомендованные W3C.

Кодировка документов 
Спецификация требует, чтобы обрабатывающие программы поддерживали по крайней мере две кодировки Юникод: UTF-8 и UTF-16.

XML-процессор и приложение 
Спецификация XML определяет понятия XML-процессор и приложение.
XML-процессор (парсер) — программа, анализирующая разметку и передающая информацию о структуре документа другой программе — приложению.

Спецификация XML налагает определённые требования на процессор, не касаясь требований к приложению.

Действительный документ. Проверяющие и непроверяющие процессоры 
Документ является действительным, если с ним связано определение типа документа и если этот документ отвечает представленным в определении типа документа ограничениям.

XML-процессоры делятся на два класса: проверяющие и непроверяющие.

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

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

Описание типов документов: языки схем 
Для описания типов документов используются языки схем ().
Поскольку XML является подмножеством языка SGML, то он унаследовал разработанный для SGML язык Document Type Definition (DTD).
Позднее были разработаны и другие языки схем, наиболее известны из которых XML Schema, RELAX NG.

Преобразование документа XML 
Для решения задачи преобразования документа XML в другую схему или другой формат предназначен язык XSLT.

Формат для визуализации документа 
Для форматированного документа (документа, подготовленного к визуализации) предназначен формат XSL-FO.

Языки запросов 
XPath — синтаксис для адресации содержимого документа, представленного в форме дерева. Выражения XPath используются в языке XQuery.
Выражения XPath, вообще говоря, могут использоваться в любом контексте, где уместно использовать формальные ссылки на элементы дерева, в частности, в качестве параметров методов интерфейсов доступа к документу.

XQuery — язык программирования, ориентированный на работу с документами.

Чтение XML: три варианта API 

Для чтения XML есть три варианта API.

Событийный API (event-driven API, push-style API) — XML-процессор читает XML; при определённом событии (появлении открывающего или закрывающего тега, текстовой строки, атрибута) вызывается callback-функция.
 + Расходует мало памяти.
 + При обработке огромного XML есть стандартная точка, позволяющая мгновенно остановить обработчик.
 − Крайне сложен для прикладного программиста: приходится держать в памяти информацию, в каком месте документа мы находимся.
 + Библиотека проста в программировании.
 − Только последовательный доступ к XML, это затрудняет разбор перекрёстных ссылок и «почти правильных» XML с перепутанным порядком элементов.
 − API только для чтения, для записи потребуется другой API.
 ± Естественный выбор, когда из огромного XML надо извлечь немного данных.
 ± Естественный выбор, когда XML надо преобразовать в структуру предметной отрасли.
 Примеры библиотек: SAX, Expat

<?xml version="1.0" encoding="UTF-8" ?>
<document>
  <thing name="A">Alpha</thing>
  <thing name="B">Bravo</thing>
</document>

enum class Place { ROOT, DOCUMENT, THING, N }

Place parentPlace[static_cast<int>(Place::N)] = { ROOT, ROOT, DOCUMENT };

class MyEvent : public Xml::Event
{
private:
  Place place = Place::ROOT;
  Thing* currThing = nullptr;
public:
  /// @return  true — тег нужен;  false — пропустить его и всё, что внутри
  bool onTagOpen(const std::string& aName) override;
  void onTagClose() override;
  void onAttr(const std::string& aName, const std::string& aValue) override;
  void onText(const std::string& aText) override;
}

bool MyEvent::onTagOpen(const std::string& aName)
{
  switch (place) {
  case Place::ROOT:
    if (aName == "document") {
      place = Place::DOCUMENT;
      return true;
    }
    break;
  case Place::DOCUMENT:
    if (aName == "thing") {
      place = Place::THING;
      currThing = &things.emplace_back();
      return true;
    }
    break;
  }
  return false;
}

void MyEvent::onTagClose()
{
  place = parentPlace[place];
}

void MyEvent::onAttr(const std::string& aName, const std::string& aValue)
{
  if (place == Place::THING && aName == "name")
    currThing->name = aValue;
}

void MyEvent::onText(const std::string& aText)
{
  if (place == Place::THING)
    currThing->value = aText;
}

xml::eventDrivenRead("in.xml", MyEvent());

Потоковый API (также pull-style API) — устроен на манер потоков ввода-вывода. Прикладной код запрашивает у процессора части XML, тот умеет только двигаться по XML вперёд, забывая уже пройденные части.
 + Расходует мало памяти.
 + Информация, в каком месте документа мы находимся, неявно задаётся местом в потоке выполнения. Это серьёзно упрощает работу прикладного программиста. На продуманных API объём кода приближается к таковому для DOM.
 − Библиотека сложна в программировании.
 + Позволяет одновременный доступ к двум XML-документам.
 − Только последовательный доступ к XML, это затрудняет разбор перекрёстных ссылок и «почти правильных» XML с перепутанным порядком элементов.
 − API только для чтения, для записи потребуется другой API. (StAX, хоть относится и к потоковым, содержит отдельный API прямой записи.)
 Примеры библиотек: StAX

xml::StreamReader reader("in.xml");
std::string name, value;
reader.enterTag("document");
while (reader.getTag("thing") {
  Thing thing;
  thing.name = reader.requireStringAttr("name");
  reader.enterTag();
  thing.value = reader.getText();
  reader.leaveTag();

  things.emplace_back(std::move(thing)); 
}

Объектный API (Document Object Model, DOM, «объектная модель документа») — считывает XML и воссоздаёт его в памяти в виде объектной структуры.
 − Расходует много памяти — намного больше, чем сам XML занимает на диске. На pugixml расход памяти втрое и более превышает длину XML.
 + Прост для прикладного программиста.
 + Библиотека проста в программировании.
 + Позволяет произвольный доступ к XML. Это, например, упрощает работу с перекрёстными ссылками. Зачастую удаётся распознать «почти верные» XML с перепутанным порядком тегов.
 + Общий API для чтения и записи.
 ± Естественный выбор, когда объектом предметной области является сам XML: в веб-браузере, XML-редакторе, в импортёре к программе-локализатору, который извлекает строки из XML произвольной структуры.
 ± Естественный выбор, когда нужно загрузить XML, слегка переработать и сохранить. Те части, которые трогать не нужно, не требуют никакого кода.
 Примеры библиотек: JDOM, TinyXML, pugixml

#include <iostream>
#include <vector>
#include "pugixml.hpp"

struct Thing {
    std::string name, value;
};

// Если какая-то сущность pugixml конвертируется в bool как false — выкинуть ошибку!
template <class T>
inline T need(T&& val, const char* errmsg)
{
    if (!val) throw std::logic_error(errmsg);
    return std::forward<T>(val);
}

int main()
{
    std::vector<Thing> things;

    pugi::xml_document doc;
    need(doc.load_file("in.xml"), "Cannot load XML!");

    auto elDocument = need(doc.root().child("document"), "Need <document>");
    for (pugi::xml_node elThing : elDocument.children("thing")) {
        auto attrName = need(elThing.attribute("name"), "Need <thing>.name!");
        things.emplace_back( Thing { attrName.as_string(), elThing.text().as_string() } );
    }

    for (auto &v : things) {
        std::cout << v.name << "=" << v.value << std::endl;
    }

    return 0;
}

Бывают и гибридные API: внешние и маловажные части читаются потоковым методом, а внутренние и важные — объектным.

xml::StreamReader reader("in.xml");
std::string name, value;
reader.enterTag("document");
while (reader.getTag("thing") {
  xml::Element* elThing = reader.readEntireSubtree();
  things.emplace_back();
  Thing& thing = things.back();
  thing.name = elThing.requireStringAttr("name");
  thing.value = elThing.text();
}

Запись XML: два варианта API 
API прямой записи записывает XML тег за тегом, атрибут за атрибутом.
 + Быстр, нет промежуточных объектов.
 − Примитивная библиотека может делать неоптимальный XML (например, <tag></tag> вместо <tag />). Работающая оптимально сложнее в программировании.
 − Непригоден для отдельных специфических задач.
 − Если структуры предметной области работают ненадёжно, без специальных мер (записать в память или в другой файл, потом переименовать) можно остаться с «упавшей» программой и потерянным файлом.
 − При ошибке программиста может получиться синтаксически некорректный XML.
 − API только для записи, для чтения потребуется другой API.
 Примеры библиотек: StAX.

xml::Writer wri("out.xml");
wri.openTag("document");
for (auto &v : things) {
  wri.openTag("thing");
  wri.writeAttr("name", v.name);
  wri.writeText(v.value);
  wri.closeTag("thing");
}
wri.closeTag("document");

Объектный API, он же Document Object Model.
 − Создаёт объектную структуру для XML, что может отнять памяти больше, чем структура предметной отрасли.
 ± Универсален (впрочем, в большинстве задач преимущества над хорошо проработанным API прямой записи нет — в отличие от чтения).
 + Даже если структуры предметной области работают ненадёжно, а программист не предусмотрел никакой «защиты», единственный сценарий, когда файл перезаписывается на неполный — ошибка ввода-вывода (в частности, нехватка места на диске).
 + При правильно написанном API невозможно создать синтаксически некорректный XML.
 + Общий API для записи и чтения.
 Примеры библиотек: те же, что и для чтения XML методом DOM.

#include "pugixml.hpp"

struct Thing {  std::string name, value; };

Thing things[] { { "A", "Alpha", }, { "B", "Bravo", }, { "C", "Charlie" } };

int main()
{
    pugi::xml_document doc;
    auto root = doc.append_child("document");
    for (auto& thing : things) {
        auto node = root.append_child("thing");
        node.append_attribute("name") = thing.name.c_str();
        node.append_child(pugi::node_pcdata).set_value(thing.value.c_str());
    }
    doc.save_file("test.xml");
    return 0;
}

Инструменты работы с документами: парсеры, средства создания и визуализации, системы баз данных

Реализации парсеров 
XML имеет реализации парсеров для всех современных языков программирования.

Веб-браузеры как инструмент визуализации документа

Визуализация без использования стилей CSS 
Без использования CSS или XSL XML-документ отображается как простой текст в большинстве веб-браузеров. Некоторые браузеры, такие как Internet Explorer, Mozilla Firefox и Opera (встроенный инструмент Opera Dragonfly) отображают структуру документа в виде дерева, позволяя сворачивать и разворачивать узлы с помощью нажатий клавиши мыши.

Применение стилей CSS 
Процесс аналогичен применению CSS к HTML-документу для отображения.
Для применения CSS при отображении в браузере, XML-документ должен содержать специальную ссылку на таблицу стилей. Например:
<?xml-stylesheet type="text/css" href="myStyleSheet.css"?>
Это отличается от подхода HTML, где используется элемент <link>.

Применение преобразований к формату XSL-FO 
Современные браузеры принадлежат к числу программных средств, способных выполнять преобразования XSLT. В браузере такое преобразование выполняется, как правило, для форматирования документа (преобразования документа в формат XSL-FO).
Следующая инструкция в прологе документа XML предписывает браузеру выполнить XSLT-преобразование, описанное в файле transform.xsl:

<?xml-stylesheet type="text/xsl" href="transform.xsl"?>

Редакторы XML 
С документом XML можно работать в обычном текстовом редакторе, однако обычные редакторы не поддерживают структуру документа. Существуют специальные редакторы XML, которые делают работу с документом более удобной и эффективной.

Системы управления базами данных, работающие с данными в формате XML 
Система управления базами данных DB2 позволяет хранить данные в формате XML и предоставляет доступ к таким данным с помощью языка XQuery.

Поддержка на аппаратном уровне 
XML поддерживается на низком аппаратном, микропрограммном и программном уровнях в современных аппаратных решениях.

Область применения, ограничения, перспективы развития

Эффективность использования XML 
XML — язык разметки, другими словами, средство описания документа. Именно в нише документов, текстов, где доля разнотипных символьных данных велика, а доля разметки мала — XML успешен. С другой стороны, обмен данными в открытых системах не сводится к обмену документами. Избыточность разметки XML (а в целях разработки языка прямо указано, что лаконичность не является приоритетом проекта) сказывается в ситуациях, когда данные не вписываются в традиционную модель документа. Лента новостей, например, оформляемая с использованием синтаксиса XML (форматы RSS, Atom), представляет собой не документ в традиционном понимании, а поток однотипных мини-документов — многословная и избыточная разметка в этом случае составляет существенную часть передаваемых данных.

W3C озабочен эффективностью применения XML, и соответствующие рабочие группы занимаются этой проблемой (к началу 2013 года нормативные документы не разработаны).

Другая ситуация, когда форматы XML могут оказаться не лучшим решением — работа с данными с простой структурой и небольшим объёмом символьных данных (поля данных). В этом случае доля разметки в общем объёме велика, а программная обработка XML может оказаться неоправданно затратной по сравнению с работой с данными более простой структуры. В этой области разработчики рассматривают средства, изначально ориентированные на данные, такие как INI, YAML, JSON.

Скриптовый язык для работы с XML 
W3C работает над созданием скриптового языка для работы с XML (к началу 2013 года нормативные документы не разработаны).

См. также 
 XML-RPC
 XML Schema
 SOAP () — протокол передачи данных, в котором для сообщений используется формат XML.
 REST
 XHTML — версия HTML, отвечающая синтаксическим требованиям XML.
 XSD — язык описания структуры XML-документов.
 FB2 — формат описания книг, основанный на XML
 W3C DOM
 DITA
 WDDX
 APML

Примечания

Литература

Ссылки 

 XML на сайте Консорциума Всемирной паутины (W3C)
 Официальная спецификация стандарта XML 1.0
 Официальная спецификация стандарта XML 1.1
 Doug Tidwell. Введение в XML
 Документация по XML на сайте IBM статьи, форумы
 Просмотр XML Просмотр и редактирование данных XML
 Форматирование XML Машина для онлайн-форматирования XML

 
Файлы конфигурации
Протоколы представительского уровня
Протоколы прикладного уровня
Стандарты W3C