Skip to content

graetz23/xmlcc

Repository files navigation

XMLCC - C++ XML Library

Version License C++ Standard

What is XMLCC?

XMLCC is a powerful C++ library for parsing, modifying, creating, and writing XML documents. It implements both DOM (Document Object Model) and SAX (Simple API for XML) parsing approaches with excellent support for malformed XML files.

Key Features

  • Dual Parsing: Choose between DOM (tree-based) or SAX (event-based) parsing
  • Malformed XML Support: Handles badly-formed XML files with precise exception reporting (line and character position)
  • Cross-Platform: Written in ANSI C++ with true platform independence
  • Easy XML Generation: Intuitive builder pattern for creating XML documents
  • Unit Tested: Comprehensive Catch2 test suite with performance benchmarks

Advantages

Feature Benefit
DOM Parser Easy tree traversal and manipulation
SAX Parser Memory-efficient for large files
Malformed XML Tolerates syntax errors gracefully
Precise Errors Reports exact line and character of errors
Header-only Use Include and link easily
No Dependencies Pure C++17, no external libraries needed

Performance

XMLCC is optimized for normal-sized XML files (~10 MB). The parser reads character-by-character, enabling precise error reporting.

Operation Typical Time
Parse small XML ~34 μs
Create 1000 DOM elements ~75 μs
Generate XML string (100x) ~246 ns

For files larger than 10 MB, consider using the SAX parser or streaming approach.


Class Architecture

                        ┌─────────────────────────────────────┐
                        │            XMLCC::DOM              │
                        │     (Document Object Model)         │
                        └─────────────────────────────────────┘
                                         │
         ┌─────────────────────────────────┼─────────────────────────────────┐
         │                                 │                                 │
         ▼                                 ▼                                 ▼
┌─────────────────┐           ┌─────────────────────┐           ┌─────────────────┐
│    Controller   │           │        Core         │           │    Parser       │
│                 │           │                     │           │                 │
│ - createRoot()  │           │ - parseFile2DomTree │           │ - parseFile()   │
│ - create()      │           │ - parseString()     │           │ - parseString() │
│ - search()      │           │                     │           │                 │
│ - genListOf()   │           └─────────────────────┘           └─────────────────┘
│ - erase()       │
└────────┬────────┘
         │
         │ creates/manages
         ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                              DOM::Node (Base Class)                         │
├─────────────────────────────────────────────────────────────────────────────┤
│  Root    │  Header  │  Element  │  Attribute  │  Value  │  Comment  │ CData │
└──────────┴─────────┴──────────┴─────────────┴─────────┴───────────┴───────┘

                        ┌─────────────────────────────────────┐
                        │            XMLCC::SAX              │
                        │     (Simple API for XML)            │
                        └─────────────────────────────────────┘
                                         │
                         ┌───────────────┴───────────────┐
                         ▼                               ▼
              ┌─────────────────┐            ┌─────────────────┐
              │     Parser      │            │    Handler      │
              │                 │            │                 │
              │ - parseFile()   │            │ - startDoc()    │
              │ - parseString()│            │ - startTag()    │
              │                 │            │ - characters()  │
              │                 │            │ - endTag()      │
              │                 │            │ - endDoc()      │
              └─────────────────┘            └─────────────────┘

                        ┌─────────────────────────────────────┐
                        │            XMLCC::SYS              │
                        │        (System Utilities)           │
                        └─────────────────────────────────────┘
                                         │
         ┌───────────────────────────────┼───────────────────────────────┐
         ▼                               ▼                               ▼
┌─────────────────┐           ┌─────────────────────┐           ┌─────────────────┐
│    StrTool      │           │      XmlTool        │           │     List<T>     │
│                 │           │                     │           │                 │
│ - trimS()       │           │ - addSpikes()      │           │ - add()         │
│ - doS2low()     │           │ - removeSpikes()   │           │ - get()         │
│ - doS2up()      │           │ - check4Tag()      │           │ - ins()         │
│ - doI2S()       │           │ - cleanTag()       │           │ - size()        │
│ - doS2I()       │           │ - format()         │           │ - arr()         │
└─────────────────┘           └─────────────────────┘           └─────────────────┘

Quick Start

Build

# Configure with CMake + Ninja
cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DXMLCC_BUILD_TESTS=ON

# Build
ninja -C build

# Run
./run/xmlcc

Code Example: Library XML

Here's how to create a library XML document with books, authors, and availability:

#include <iostream>
#include <fstream>
#include "xmlcc/xmlcc.h"

using namespace XMLCC::DOM;

int main() {
    
    // Create library XML with three books
    Root* library = new Root("library.xml", new Doctype(),
        new Element("library",
            // Book 1: Available
            new Element("book",
                new Attribute("id", "1"),
                new Element("author", new Value("George Orwell")),
                new Element("title", new Value("1984")),
                new Element("available", new Value("true"))
            ),
            // Book 2: Not available
            new Element("book",
                new Attribute("id", "2"),
                new Element("author", new Value("Jane Austen")),
                new Element("title", new Value("Pride and Prejudice")),
                new Element("available", new Value("false"))
            ),
            // Book 3: Available
            new Element("book",
                new Attribute("id", "3"),
                new Element("author", new Value("Miguel de Cervantes")),
                new Element("title", new Value("Don Quixote")),
                new Element("available", new Value("true"))
            )
        )
    );

    // Write to file
    std::fstream file;
    file.open("library.xml", std::ios::out);
    file << library;
    file.close();

    std::cout << "Created library.xml successfully!" << std::endl;

    // Parse it back
    XMLCC::DOM::Core core;
    Root* parsed = core.parseFile2DomTree("library.xml");
    
    if (parsed) {
        std::cout << "\nParsed XML:\n" << parsed << std::endl;
        
        // Find all books using Controller
        Controller ctrl;
        NodeList* books = ctrl.genListOfElements(parsed);
        
        std::cout << "\nLibrary contains " << books->size() << " books:\n";
        for (int i = 0; i < books->size(); i++) {
            Node* book = books->get(i);
            Str id = ctrl.getStrOfValueOfAttribute(book, "id");
            Str title = ctrl.getStrOfFirstElement(book);
            Str author = ctrl.getStrOfFirstElement(
                ctrl.getElement(book, "author")
            );
            Str available = ctrl.getStrOfFirstElement(
                ctrl.getElement(book, "available")
            );
            
            std::cout << "  [" << id << "] " << title 
                      << " by " << author
                      << " - " << (available == "true" ? "Available" : "Checked Out")
                      << std::endl;
        }
        
        delete books;
        delete parsed;
    }

    delete library;
    return 0;
}

Output

Generated XML (library.xml):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE library>
<library>
  <book id="1">
    <author>George Orwell</author>
    <title>1984</title>
    <available>true</available>
  </book>
  <book id="2">
    <author>Jane Austen</author>
    <title>Pride and Prejudice</title>
    <available>false</available>
  </book>
  <book id="3">
    <author>Miguel de Cervantes</author>
    <title>Don Quixote</title>
    <available>true</available>
  </book>
</library>

Console Output:

Created library.xml successfully!

Parsed XML:
[xml content]

Library contains 3 books:
  [1] 1984 by George Orwell - Available
  [2] Pride and Prejudice by Jane Austen - Checked Out
  [3] Don Quixote by Miguel de Cervantes - Available

License

XMLCC is distributed under the MIT License.

Copyright (c) 2008-2025 Christian (graetz23@gmail.com)


Version

XMLCC v1.01 - Released 2020