{"id":41808358,"url":"https://github.com/graetz23/paxcc","last_synced_at":"2026-01-25T06:56:38.868Z","repository":{"id":275321186,"uuid":"925705408","full_name":"graetz23/paxcc","owner":"graetz23","description":"A pretty simple C++ Data Passenger  - building object trees that can write and may read from XML","archived":false,"fork":false,"pushed_at":"2025-11-22T17:01:42.000Z","size":132,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-11-22T19:04:28.928Z","etag":null,"topics":["fast","handy","object-oriented","object-oriented-programming","pointer","pointers","pretty","simple","tag","tree","tree-structure","trees","value","xml"],"latest_commit_sha":null,"homepage":"https://github.com/graetz23/paxcc","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/graetz23.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-02-01T14:44:56.000Z","updated_at":"2025-11-22T17:01:46.000Z","dependencies_parsed_at":"2025-02-01T17:41:09.476Z","dependency_job_id":null,"html_url":"https://github.com/graetz23/paxcc","commit_stats":null,"previous_names":["graetz23/paxcc"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/graetz23/paxcc","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/graetz23%2Fpaxcc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/graetz23%2Fpaxcc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/graetz23%2Fpaxcc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/graetz23%2Fpaxcc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/graetz23","download_url":"https://codeload.github.com/graetz23/paxcc/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/graetz23%2Fpaxcc/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28747306,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-25T05:12:38.112Z","status":"ssl_error","status_checked_at":"2026-01-25T05:04:50.338Z","response_time":113,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fast","handy","object-oriented","object-oriented-programming","pointer","pointers","pretty","simple","tag","tree","tree-structure","trees","value","xml"],"created_at":"2026-01-25T06:56:38.802Z","updated_at":"2026-01-25T06:56:38.859Z","avatar_url":"https://github.com/graetz23.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# paxcc\n\n_A pretty simple C++ Data Passenger_; PAX is an airborne code or peace in latin.\n\n## Introduction\n\nThe PAX class is a C++ written _double linked object tree_.\nIt is an enabler for parsing any kind of - hierarchically - structured data; e.g. _extensible markup language_ (XML).\nA simple SAX like interface is available for parsing to a PAX object tree.\n\nA _Pax_ objects can:\n\n- store a _tag_ as std::string,\n- store a _value_ as std::string,\n- add multiple _attribute_ as a pair of _tag_ and _value_,\n- add multiple _Pax_ object as _children_ of the current,\n- generate themselves recursively to XML,\n- write themselves to XML using the _Writer_,\n- parse themselves by XML to a _double linked object tree_ using the _Reader_.\n  \nPAXCC is written in C++11 currently (may switch to C++98).\nThere are not further dependencies to other libraries or framework.\nIt is ideal for standalone hierarchical structured data handling using XML.\n\n## HowTo\n\nHow to use _Pax_, build object tree, and what can go wrong.\n\n### Creating, Setting, Changing, and Deleting _Pax_ trees\n\n#### Creating a Pax Object\n\nCreating _Pax_ objects:\n\n```C++\n  Pax* pax1 = new Pax(\"Bob\", \"Dylon\");\n\n  Pax *pax2 = new Pax();\n  pax2-\u003eTag(\"Bob\");\n  pax2-\u003eVal(\"Dylon\");\n\n  Pax* pax3 = new Pax(\"Bob\");\n```\n\n#### Adding Attributes to a Pax Object\n\nAdding _Attributes_ to _Pax_ objects:\n\n```C++\n  Pax* pax1 = new Pax(\"Bob\", \"Dylon\");\n  pax1-\u003eAttrib()-\u003eadd(\"plays\", \"guitar\");\n  pax1-\u003eAttrib()-\u003eadd(\"sings\", \"songs\");\n```\n\n#### Adding Children to a Pax Object\n\nAdding _Children_ to _Pax_ objects:\n\n```C++\n  Pax* pax1 = new Pax(\"Bob\", \"Dylon\");\n  Pax* pax2 = new Pax(\"Dolly\", \"Parton\");\n  Pax* pax3 = new Pax(\"Johnny\", \"Cash\");\n\n  pax1-\u003eChild()-\u003eadd(pax2); // pax2 as child of pax1\n  pax2-\u003eChild()-\u003eadd(pax3); // pax3 as child of pax2\n```\n\n#### Deleting Pax Object\n\nDeleting any _Pax_ object by recursive destructor:\n\n```C++\n  Pax* root = new Pax(\"Bob\", \"Dylon\");\n  Pax* pax2 = new Pax(\"Dolly\", \"Parton\");\n  Pax* pax3 = new Pax(\"Johnny\", \"Cash\");\n\n  root-\u003eChild()-\u003eadd(pax2); // pax2 as child of pax1\n  pax2-\u003eChild()-\u003eadd(pax3); // pax3 as child of pax2\n\n  delete root; // runs recursively ..\n```\n\n#### Generating XML from a Pax Object\n\nGenerating XML from _Pax_ and writing to _std::out_:\n\n```C++\n  Pax* pax1 = new Pax(\"Bob\", \"Dylon\");\n  pax1-\u003eAttrib()-\u003eadd(\"plays\", \"guitar\");\n  pax1-\u003eAttrib()-\u003eadd(\"sings\", \"songs\");\n\n  Pax* pax2 = new Pax(\"Dolly\", \"Parton\");\n  pax2-\u003eAttrib()-\u003eadd(\"sings\", \"songs\");\n  pax2-\u003eAttrib()-\u003eadd(\"plays\", \"country guitar\");\n\n\n  Pax* pax3 = new Pax(\"Johnny\", \"Cash\");\n  pax3-\u003eAttrib()-\u003eadd(\"plays\", \"guitar\");\n  pax3-\u003eAttrib()-\u003eadd(\"sings\", \"country songs\");\n\n  Pax* pax4 = new Pax(\"John\", \"Denver\");\n  pax4-\u003eAttrib()-\u003eadd(\"sings\", \"country songs\");\n  pax4-\u003eAttrib()-\u003eadd(\"plays\", \"country guitar\");\n\n  pax1-\u003eChild()-\u003eadd(pax2); // pax2 as child of pax1\n  pax2-\u003eChild()-\u003eadd(pax3); // pax3 as child of pax2\n  pax2-\u003eChild()-\u003eadd(pax4); // pax3 as child of pax2\n\n  std::string xml = pax1-\u003eXML();\n  std::cout \u003c\u003c xml \u003c\u003c std::endl \u003c\u003c std::flush;\n\n  delete pax1; // runs recursively\n```\n\nThe XML of above example looks like:\n\n```XML\n  \u003cBob plays=\"guitar\" sings=\"songs\"\u003e\n    \u003cDolly sings=\"songs\" plays=\"country guitar\"\u003e\n      \u003cJohnny plays=\"guitar\" sings=\"country songs\"\u003eCash\u003c/Johnny\u003e\n      \u003cJohn sings=\"country songs\" plays=\"country guitar\"\u003eDenver\u003c/John\u003e\n    \u003c/Dolly\u003e\n  \u003c/Bob\u003e\n````\n\n#### Access Pax Child Objects\n\nRetrieving _Pax_ from above example:\n\n```C++\n  // assume we have build above Pax object tree ..\n\n  Pax* pax2_ = pax1-\u003eChild(\"Dolly\");\n\n  Pax* pax3_ = pax2-\u003eChild(\"Johnny\"); // from pax2\n\n  Pax* pax4_ = pax1-\u003eChild(\"Dolly\")-\u003eChild(\"John\"); // chained\n```\n\n#### Accessing Tag and Value\n\nRetrieving _Tag_ and _Value_:\n\n```C++\n  Pax* pax = pax1-\u003eChild(\"Dolly\")-\u003eChild(\"John\"); // chained\n  std::string tag = pax-\u003eTag();\n  std::string val = pax-\u003eVal();\n```\n\n#### Accessing Tag and Value of Attributes\n\nRetrieving _Attributes_ _Tag_ and _Value_:\n\n```C++\n  Pax* pax = pax1-\u003eChild(\"Dolly\")-\u003eChild(\"John\"); // chained\n  std::string attribTag = pax-\u003eAttrib(\"sings\")-\u003eTag();\n  std::string attribVal = pax-\u003eAttrib(\"sings\")-\u003eVal();\n```\n\n### What can go wrong\n\n#### Deleting treed _Pax_ outside the tree\n\nThe problem in pointered C++ is, that there is no garbage collector that\ncollects any memory address and holds a pointer for automatic deletion on it.\nTherefore, within _Pax_ it is possible to delete objects not recursively by\nthe tree, but outside the tree. This leads to a memory gap, where the object\ntree still holds the pointer but the object is deleted. The recursive calling\nmethods stumbles over it an crashes off course. Here is an easy example to\nproduce this error:\n\n```C++\n  Pax* root = new Pax(\"Bob\", \"Dylon\");\n  Pax* pax2 = new Pax(\"Dolly\", \"Parton\");\n  Pax* pax3 = new Pax(\"Johnny\", \"Cash\");\n\n  root-\u003eChild()-\u003eadd(pax2); // pax2 as child of pax1\n  pax2-\u003eChild()-\u003eadd(pax3); // pax3 as child of pax2\n\n  delete pax2; // the error one can make ..\n\n  delete root; // runs recursively .. and crashes!\n```\n\nThe reason is simple. The Higher _Pax_ holds in his child list still the pointer\nto the address of the delete _pax2_. As soon as this list of child is iterated,\nthe crash is there. There is no known chance to overcome this issue in ANSI C++.\n\n#### Changing _Tags_ and _Values_ of a treed _Pax_\n\nIf an _already treed Pax_ is retrieved and the _Tag_ or the _Value_ is changed,\nthe object tree is not updated. Therefore, the object tree holds in the matching\n_Pax_ of higher hierarchy still the old _Tag_ to the address of the changed _Pax_.\nThe following example details this issue:\n\n```C++\n  Pax* root = new Pax(\"Bob\", \"Dylon\");\n  Pax* pax2 = new Pax(\"Dolly\", \"Parton\");\n  Pax* pax3 = new Pax(\"Johnny\", \"Cash\");\n\n  root-\u003eChild()-\u003eadd(pax2); // pax2 as child of pax1\n  pax2-\u003eChild()-\u003eadd(pax3); // pax3 as child of pax2\n\n  Pax* pax = root-\u003eChild(\"Dolly\")-\u003eChild(\"Johnny\");\n\n  pax-\u003eTag(\"John\"); // updating Tag\n  pax-\u003eVal(\"Denver\"); // updating Value\n\n  Pax* pax2_ = root-\u003eChild(\"Dolly\"); // remeber Dolly knows Johnny\n\n  Pax* pax3_ = pax2-\u003eChild(\"Johnny\"); // exists\n  std::string tag = pax3_.Tag(); // John was stored\n  std::string val = pax3_.Val(); // Denver was stored\n\n  // and \n\n  Pax* pax3__ = pax2-\u003eChild(\"John\"); // null pointer\n\n  delete root; // runs recursively ..\n```\n\nThis leads to the fact, that if one wants to change data on treed _Pax_,\nhe has to also deal with the object tree. Therefore, retrieving the object\nabove, deleting the _Pax_ from object tree, changing it, and adding it again.\n\n### Input and Output with Pax Objects\n\n#### Writing a Pax Object to Console\n\nWriting a _Pax_ Object to Console:\n\n```C++\n  // build some Pax object named pax1\n  std::string xml = pax1-\u003eXML(); // generate XML from object tree ..\n  std::cout \u003c\u003c xml \u003c\u003c std::endl; // print out\n```\n\n#### Writing Pax Object to File\n\nWriting a _Pax_ Object to file:\n\n```C++\n  // build some Pax object named pax1\n  PaxWriter writer;\n  writer.write(\"example_output.xml\", pax1); // write to file\n  delete pax1; // working recursively well on first run ..\n```\n\n### Reading a Pax Object from File\n\nReading a _Pax_ Object from File:\n\n```C++\n  PaxReader reader;\n  Pax* pax1 = reader.read(\"example_output.xml\"); // read from file\n  delete pax1; // working recursively well on first run ..\n```\n\n#### Reading some Pax Objects from Folder\n\nReading several _Pax_ Objects from a folder:\n\n```C++\n  PaxReader reader;\n  std::vector\u003cPax*\u003e paxList = reader.readAll(\"./folderPath\"); // read all from folder\n  for(int i = 0; i \u003c paxList.size(); i++) {\n    Pax* pax1 = paxList[i];\n    delete pax1; // working recursively well on first run ..\n  } // for\n```\n\n#### Reading some Pax Objects from Folder for certain File Ending\n\nReading several _Pax_ Objects from a folder by a given file ending:\n\n```C++\n  PaxReader reader;\n  std::vector\u003cPax*\u003e paxList = reader.readAll(\"./folderPath\", \".xsd\"); // read all from folder\n  for(int i = 0; i \u003c paxList.size(); i++) {\n    Pax* pax1 = paxList[i];\n    delete pax1; // working recursively well on first run ..\n  } // for\n```\n\n## Building the PAXCC\n\nFor building PAXCC the [CMake - Software Build System](https://cmake.org/) is available.\n\n### Cmake Build Tooling\n\nFor modern CMake version install _CMake_ and [Ninja](https://ninja-build.org/).\n\n#### Build PAXCC\n\nFor generating the _ninja build files_ with _CMake_ and building binaries via _ninja_:\n\n```bash\n  ./build.sh\n```\n\nIf you want to use classical make, you can edit the _build.sh_ bash script easily.\n\n#### Clean PAXCC\n\nFor cleaning up all compiled objects:\n\n```bash\n  ./clean.sh\n```\n\nTo remove the build folder:\n\n```bash\n  rm -rf build/\n```\n\n## Closings\n\nHave fun :-)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgraetz23%2Fpaxcc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgraetz23%2Fpaxcc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgraetz23%2Fpaxcc/lists"}