[C++] How to use RapidXML to read and create XML files

Wednesday afternoon, October 11, 2023

Table of Contents

  • RapidXML’s official website
  • Use rapidXML to read the attributes and values of elements in XML files
  • The XML file to be read this time: ReadExample.xml
  • C++ code for reading this XML file
  • Run result
  • Use rapidXML to create XML files
  • C++ code for creating XML files
  • If the above code cannot run
  • Run results
  • ?Edit

RapidXML’s official website

https://rapidxml.sourceforge.net/

RapidXML only has header files and does not require compilation or configuration.

Use rapidXML to read attributes and values of elements in XML files

The XML file to be read this time: ReadExample.xml

<?xml version="1.0" encoding="UTF-8"?> <!-- XML declaration, specify version and encoding -->
<root> <!-- root element -->
    <Connector connectionTimeout="20000" maxParameterCount="1000" port="8088" protocol="HTTP/1.1" redirectPort="8443"/><!--Sub-element Connector-->
    <book> <!-- child element book -->
        <name>C++ Primer</name>
        <author>Stanley B. Lippman</author>
        <price>59.00</price>
    </book>
    <book>
        <name>Head First Java</name>
        <author>Kathy Sierra</author>
        <price>35.99</price>
    </book>
</root>

C++ code for reading this XML file

#include "rapidxml.hpp"
#include <iostream>
#include <fstream>

int main() {
    rapidxml::xml_document<> doc;

    //Open XML file
    std::ifstream file("ReadExample.xml");
    if (!file) {
        std::cerr << "Failed to open the XML file." << std::endl;
        return 1;
    }

    //Read the contents of the XML file into memory
    std::string xml_contents((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
    file.close();

    // Parse XML document
    doc.parse<rapidxml::parse_default>( & amp;xml_contents[0]);

    // Get the root element
    rapidxml::xml_node<>* root = doc.first_node("root");

    // Traverse the child elements book
    for (rapidxml::xml_node<>* book = root->first_node("book"); book; book = book->next_sibling("book")) {
        // Get the book title
        rapidxml::xml_node<>* name = book->first_node("name");
        if (name) {
            std::cout << "Book Name: " << name->value() << std::endl;
        }

        // Get the author
        rapidxml::xml_node<>* author = book->first_node("author");
        if (author) {
            std::cout << "Author: " << author->value() << std::endl;
        }

        // get price
        rapidxml::xml_node<>* price = book->first_node("price");
        if (price) {
            std::cout << "Price: " << price->value() << std::endl;
        }

        std::cout << std::endl;
    }

    // Get the attributes of the Connector element
    rapidxml::xml_node<>* connector = root->first_node("Connector");
    if (connector) {
        std::cout << "Connector Attributes:" << std::endl;
        for (rapidxml::xml_attribute<>* attr = connector->first_attribute(); attr; attr = attr->next_attribute()) {
            std::cout << "Attribute Name: " << attr->name() << ", Value: " << attr->value() << std::endl;
        }
    }

    return 0;
}

Run results

Use rapidXML to create XML files

C++ code for creating XML files

#include "rapidxml.hpp"
#include "rapidxml_print.hpp" // Used to format output XML
#include <iostream>
#include <fstream>

int main() {
    rapidxml::xml_document<> doc;

    //Create the root element
    rapidxml::xml_node<>* root = doc.allocate_node(rapidxml::node_element, "root");
    doc.append_node(root);

    //Create an element book
    rapidxml::xml_node<>* book = doc.allocate_node(rapidxml::node_element, "book");
    root->append_node(book);

    // Create child elements of the book element
    rapidxml::xml_node<>* name = doc.allocate_node(rapidxml::node_element, "name", "C++ Primer");
    book->append_node(name);

    rapidxml::xml_node<>* author = doc.allocate_node(rapidxml::node_element, "author", "Stanley B. Lippman");
    book->append_node(author);

    rapidxml::xml_node<>* price = doc.allocate_node(rapidxml::node_element, "price", "59.00");
    book->append_node(price);

    //Create a second book element
    book = doc.allocate_node(rapidxml::node_element, "book");
    root->append_node(book);

    name = doc.allocate_node(rapidxml::node_element, "name", "Head First Java");
    book->append_node(name);

    author = doc.allocate_node(rapidxml::node_element, "author", "Kathy Sierra");
    book->append_node(author);

    price = doc.allocate_node(rapidxml::node_element, "price", "35.99");
    book->append_node(price);

    // Output XML to file
    std::ofstream file("created.xml");
    file << doc;
    file.close();

    return 0;
}

If the above code cannot run

If you also encounter an error like the following

Then you can create a rapidxml_ext.hpp file according to the following two articles

c++ – RapidXML: Unable to print – compile time error – IT Tools Network (coder.work)

c++ – RapidXML: Unable to print – Compile-time Error – Stack Overflow

The code of rapidxml_ext.hpp file is as follows

//rapidxml_ext.hpp
#pragma once

#include "rapidxml.hpp"

// Adding declarations to make it compatible with gcc 4.7 and greater
// See https://stackoverflow.com/a/55408678
namespace rapidxml {
    namespace internal {
        template <class OutIt, class Ch>
        inline OutIt print_children(OutIt out, const xml_node<Ch>* node, int flags, int indent);

        template <class OutIt, class Ch>
        inline OutIt print_attributes(OutIt out, const xml_node<Ch>* node, int flags);

        template <class OutIt, class Ch>
        inline OutIt print_data_node(OutIt out, const xml_node<Ch>* node, int flags, int indent);

        template <class OutIt, class Ch>
        inline OutIt print_cdata_node(OutIt out, const xml_node<Ch>* node, int flags, int indent);

        template <class OutIt, class Ch>
        inline OutIt print_element_node(OutIt out, const xml_node<Ch>* node, int flags, int indent);

        template <class OutIt, class Ch>
        inline OutIt print_declaration_node(OutIt out, const xml_node<Ch>* node, int flags, int indent);

        template <class OutIt, class Ch>
        inline OutIt print_comment_node(OutIt out, const xml_node<Ch>* node, int flags, int indent);

        template <class OutIt, class Ch>
        inline OutIt print_doctype_node(OutIt out, const xml_node<Ch>* node, int flags, int indent);

        template <class OutIt, class Ch>
        inline OutIt print_pi_node(OutIt out, const xml_node<Ch>* node, int flags, int indent);
    }
}

#include "rapidxml_print.hpp"

Then based on the original code, introduce the header file rapidxml_ext.hpp

Pay attention to the order of the header files, rapidxml_ext.hpp must be introduced before rapidxml_print.hpp

The corrected code is as follows

#include "rapidxml.hpp"
#include "rapidxml_ext.hpp" //Only this extra line
#include "rapidxml_print.hpp" // Used to format output XML
#include <iostream>
#include <fstream>

int main() {
    rapidxml::xml_document<> doc;

    //Create the root element
    rapidxml::xml_node<>* root = doc.allocate_node(rapidxml::node_element, "root");
    doc.append_node(root);

    //Create an element book
    rapidxml::xml_node<>* book = doc.allocate_node(rapidxml::node_element, "book");
    root->append_node(book);

    // Create child elements of the book element
    rapidxml::xml_node<>* name = doc.allocate_node(rapidxml::node_element, "name", "C++ Primer");
    book->append_node(name);

    rapidxml::xml_node<>* author = doc.allocate_node(rapidxml::node_element, "author", "Stanley B. Lippman");
    book->append_node(author);

    rapidxml::xml_node<>* price = doc.allocate_node(rapidxml::node_element, "price", "59.00");
    book->append_node(price);

    //Create a second book element
    book = doc.allocate_node(rapidxml::node_element, "book");
    root->append_node(book);

    name = doc.allocate_node(rapidxml::node_element, "name", "Head First Java");
    book->append_node(name);

    author = doc.allocate_node(rapidxml::node_element, "author", "Kathy Sierra");
    book->append_node(author);

    price = doc.allocate_node(rapidxml::node_element, "price", "35.99");
    book->append_node(price);

    // Output XML to file
    std::ofstream file("created.xml");
    file << doc;
    file.close();

    return 0;
}

Run results