Table of Contents

This is some frequently used APIs and functionalities I used. For a complete reference, refer to http://pugixml.org.

1 load

1.1 parse result

struct xml_parse_result {
  xml_parse_status status;
  ptrdiff_t offset;
  xml_encoding encoding;

  operator bool() const;
  const char* description() const;


  • statusok
  • statusfilenotfound

1.2 parse options

The usual bitwise arithmetics: `mask | flag` and `mask & ~flag`.

  • parsetrimpcdata: off. if the leading and trailing whitespace are to be removed.
  • parsewspcdata: off. if PCDATA nodes that consist only of whitespace are to be sustained.
  • parseminimal: all options turned off
  • parsedefault
  • parsefull

1.3 Load

1.3.1 from file


xml_parse_result xml_document::load_file(
  const char* path,
  unsigned int options = parse_default,
  xml_encoding encoding = encoding_auto


pugi::xml_document doc;
pugi::xml_parse_result result = doc.load_file("tree.xml");

1.3.2 from memory


// immutable buffer
xml_parse_result xml_document::load_buffer(
  const void* contents,
  size_t size,
  unsigned int options = parse_default,
  xml_encoding = encoding_auto
// equivalent with call load_buffer with size strlen(contents)
// null terminated string
xml_parse_result xml_document::load_string(
  const char_t* contents,
  unsigned int options = parse_default


const char source[] = "<hello>world</hello>";
size_t size = sizeof(source);
pugi::xml_parse_result result = doc.load_buffer(source, size);

pugi::xml_parse_result result = doc.load_string("<hello>world</hello>");

1.3.3 from IO streams


xml_parse_result xml_document::load(
  std::istream& stream,
  unsigned int options = parse_default,
  xml_encoding encoding = encoding_auto


std::ifstream stream("a.xml");
pugi::xml_parse_result result = doc.load(stream);

2 read

if some node doesn't have name or value, the function will return "".


const char_t* xml_node::name() const;
const char_t* xml_node::value() const;
// value of the first child with type node_pcdata or node_cdata
const char_t* xml_node::child_value() const;
// wrapper for child(name).child_value()
const char_t* xml_node::child_value(const char_t* name) const;


const char_t* xml_attribute::name() const;
const char_t* xml_attribute::value() const;
// as_xx
int xml_attribute::as_int(int def = 0) const;
unsigned int xml_attribute::as_uint(unsigned int def = 0) const;
double xml_attribute::as_double(double def = 0) const;
float ...
bool ...
long long ...
unsigned long long ...


xml_text xml_node::text() const;
xml_node xml_text::data() const;

if the node is `nodepcdata` or `nodecdata`, return the node's data. else, return the first child node of `nodepcdata` or `nodecdata`.


bool xml_text::empty() const;
// equal to text.data().value()
const char_t* xml_text::get() const;
bool xml_text::set(const char_t* rhs);


const char_t* xml_text::as_string(const char_t* def = "") const;
int xml_text::as_int(int def = 0) const;
unsigned int xml_text::as_uint(unsigned int def = 0) const;
double xml_text::as_double(double def = 0) const;
float xml_text::as_float(float def = 0) const;
bool xml_text::as_bool(bool def = false) const;
long long xml_text::as_llong(long long def = 0) const;
unsigned long long xml_text::as_ullong(unsigned long long def = 0) const;
bool xml_text::set(int rhs);
bool xml_text::set(unsigned int rhs);
bool xml_text::set(double rhs);
bool xml_text::set(float rhs);
bool xml_text::set(bool rhs);
bool xml_text::set(long long rhs);
bool xml_text::set(unsigned long long rhs);
xml_text& xml_text::operator=(const char_t* rhs);
xml_text& xml_text::operator=(int rhs);
xml_text& xml_text::operator=(unsigned int rhs);
xml_text& xml_text::operator=(double rhs);
xml_text& xml_text::operator=(float rhs);
xml_text& xml_text::operator=(bool rhs);
xml_text& xml_text::operator=(long long rhs);
xml_text& xml_text::operator=(unsigned long long rhs);

3 modify

3.1 set

bool xml_node::set_name(const char_t* rhs);
bool xml_node::set_value(const char_t* rhs);
bool xml_attribute::set_name(const char_t* rhs);
bool xml_attribute::set_value(const char_t* rhs);

attribute can use different type other than string:

bool xml_attribute::set_value(int rhs);
bool xml_attribute::set_value(unsigned int rhs);
bool xml_attribute::set_value(double rhs);
bool xml_attribute::set_value(float rhs);
bool xml_attribute::set_value(bool rhs);
bool xml_attribute::set_value(long long rhs);
bool xml_attribute::set_value(unsigned long long rhs);
xml_attribute& xml_attribute::operator=(const char_t* rhs);
xml_attribute& xml_attribute::operator=(int rhs);
xml_attribute& xml_attribute::operator=(unsigned int rhs);
xml_attribute& xml_attribute::operator=(double rhs);
xml_attribute& xml_attribute::operator=(float rhs);
xml_attribute& xml_attribute::operator=(bool rhs);
xml_attribute& xml_attribute::operator=(long long rhs);
xml_attribute& xml_attribute::operator=(unsigned long long rhs);

3.2 add/remove


xml_node xml_node::append_child(xml_node_type type = node_element);
xml_node xml_node::prepend_child(xml_node_type type = node_element);
xml_node xml_node::insert_child_after(xml_node_type type, const xml_node& node);
xml_node xml_node::insert_child_before(xml_node_type type, const xml_node& node);
// node_element with tagname name
xml_node xml_node::append_child(const char_t* name);
xml_node xml_node::prepend_child(const char_t* name);
xml_node xml_node::insert_child_after(const char_t* name, const xml_node& node);
xml_node xml_node::insert_child_before(const char_t* name, const xml_node& node);


xml_attribute xml_node::append_attribute(const char_t* name);
xml_attribute xml_node::prepend_attribute(const char_t* name);
xml_attribute xml_node::insert_attribute_after(const char_t* name, const xml_attribute& attr);
xml_attribute xml_node::insert_attribute_before(const char_t* name, const xml_attribute& attr);


bool xml_node::remove_attribute(const xml_attribute& a);
bool xml_node::remove_attribute(const char_t* name);
bool xml_node::remove_child(const xml_node& n);
bool xml_node::remove_child(const char_t* name);


// delete all nodes with specified name
while (node.remove_child("tool"));

3.3 clone


xml_node xml_node::append_copy(const xml_node& proto);
xml_node xml_node::prepend_copy(const xml_node& proto);
xml_node xml_node::insert_copy_after(const xml_node& proto, const xml_node& node);
xml_node xml_node::insert_copy_before(const xml_node& proto, const xml_node& node);


xml_attribute xml_node::append_copy(const xml_attribute& proto);
xml_attribute xml_node::prepend_copy(const xml_attribute& proto);
xml_attribute xml_node::insert_copy_after(
  const xml_attribute& proto,
  const xml_attribute& attr
xml_attribute xml_node::insert_copy_before(
  const xml_attribute& proto,
  const xml_attribute& attr

3.4 move node

copy the node and remove the origin. But this is expensive. The following API avoid that.

xml_node xml_node::append_move(const xml_node& moved);
xml_node xml_node::prepend_move(const xml_node& moved);
xml_node xml_node::insert_move_after(const xml_node& moved, const xml_node& node);
xml_node xml_node::insert_move_before(const xml_node& moved, const xml_node& node);

4 traversal


xml_node xml_node::parent() const;
xml_node xml_node::first_child() const;
xml_node xml_node::last_child() const;
xml_node xml_node::next_sibling() const;
xml_node xml_node::previous_sibling() const;
xml_node xml_node::root() const;
// tag name
xml_node xml_node::child(const char_t* name) const;
xml_node xml_node::next_sibling(const char_t* name) const;
xml_node xml_node::previous_sibling(const char_t* name) const;
// find by attr
xml_node xml_node::find_child_by_attribute(
  const char_t* name,
  const char_t* attr_name,
  const char_t* attr_value
xml_node xml_node::find_child_by_attribute(
  const char_t* attr_name,
  const char_t* attr_value


xml_attribute xml_node::first_attribute() const;
xml_attribute xml_node::last_attribute() const;
xml_attribute xml_attribute::next_attribute() const;
xml_attribute xml_attribute::previous_attribute() const;
// tag name
xml_attribute xml_node::attribute(const char_t* name) const;

Attributes do not have a link to their parent nodes because of memory consumption reasons.

4.1 range based loop(C++11)

implementation-defined-type xml_node::children() const;
implementation-defined-type xml_node::children(const char_t* name) const;
implementaiton-defined-type xml_node::attributes() const;


for (pugi::xml_node tool : tools.children("Tool")) {
  // ...

4.2 iterators


class xml_node_iterator;
class xml_attribute_iterator;

typedef xml_node_iterator xml_node::iterator;
iterator xml_node::begin() const;
iterator xml_node::end() const;

typedef xml_attribute_iterator xml_node::attribute_iterator;
attribute_iterator xml_node::attributes_begin() const;
attribute_iterator xml_node::attributes_end() const;


for (pugi::xml_node_iterator it=tools.begin();it!=tools.end();it++) {
  // it->xxx

4.3 xmltreewalker


class xml_tree_walker {
  virtual bool begin(xml_node& node);
  virtual bool for_each(xml_node& node) = 0;
  virtual bool end(xml_node& node);
  int depth() const;
bool xml_node::traverse(xml_tree_walker& walker);
  • `begin` is called with root
  • `foreach` is called for all nodes in Depth First Order, except root.
  • `end` is called with root

if `begin`, `end`, or any of `foreach` return false, the traversal terminates and return false.


struct simple_walker : pugi::xml_tree_walker {
  virtual bool for_each(pugi::xml_node& node) {
    // node
    return true; // continue
simple_walker walker;

4.4 simple path

string_t xml_node::path(char_t delimiter = '/') const;
xml_node xml_node::first_element_by_path(
  const char_t* path,
  char_t delimiter = '/'

path can be relative or absolute(start with delimiter).

5 xpath

5.1 types

`xpathnode` can be either a node or an attribute.

xml_node xpath_node::node() const;
xml_attribute xpath_node::attribute() const;
xml_node xpath_node::parent() const;


xpath_node xpath_node_set::first() const;
const xpath_node& xpath_node_set::operator[](size_t index) const;
size_t xpath_node_set::size() const;
bool xpath_node_set::empty() const;

5.2 query

// equal to select_nodes().first()
xpath_node xml_node::select_node(
  const char_t* query,
  xpath_variable_set* variables = 0
) const;
xpath_node_set xml_node::select_nodes(
  const char_t* query,
  xpath_variable_set* variables = 0
) const;
// precompiled version
xpath_node xml_node::select_node(const xpath_query& query) const;
xpath_node_set xml_node::select_nodes(const xpath_query& query) const;

5.2.1 precompiled query


explicit xpath_query::xpath_query(
  const char_t* query,
  xpath_variable_set* variables = 0


bool xpath_query::evaluate_boolean(const xpath_node& n) const;
double xpath_query::evaluate_number(const xpath_node& n) const;
string_t xpath_query::evaluate_string(const xpath_node& n) const;
// equal to node.select_nodes()
xpath_node_set xpath_query::evaluate_node_set(const xpath_node& n) const;
// equal to node.select_node()
xpath_node xpath_query::evaluate_node(const xpath_node& n) const;

Author: Hebi Li

Created: 2017-03-27 Mon 14:36