{"id":17062131,"url":"https://github.com/recp/xml","last_synced_at":"2025-06-11T19:06:01.293Z","repository":{"id":53541932,"uuid":"224018474","full_name":"recp/xml","owner":"recp","description":"🔋 In-place lightweight XML parser","archived":false,"fork":false,"pushed_at":"2024-05-08T11:39:06.000Z","size":63,"stargazers_count":13,"open_issues_count":1,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-04T08:51:16.635Z","etag":null,"topics":["c-xml","fast-xml","header-only","in-place-parser","lightweight-xml","optimized-xml","parser","tokenizer","tokenizer-parser","xml","xml-loader","xml-parser"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/recp.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}},"created_at":"2019-11-25T18:49:23.000Z","updated_at":"2025-01-10T22:17:14.000Z","dependencies_parsed_at":"2024-10-28T14:18:35.635Z","dependency_job_id":null,"html_url":"https://github.com/recp/xml","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/recp/xml","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/recp%2Fxml","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/recp%2Fxml/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/recp%2Fxml/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/recp%2Fxml/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/recp","download_url":"https://codeload.github.com/recp/xml/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/recp%2Fxml/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259319669,"owners_count":22839818,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["c-xml","fast-xml","header-only","in-place-parser","lightweight-xml","optimized-xml","parser","tokenizer","tokenizer-parser","xml","xml-loader","xml-parser"],"created_at":"2024-10-14T10:49:17.767Z","updated_at":"2025-06-11T19:06:01.273Z","avatar_url":"https://github.com/recp.png","language":"C","readme":"# 🔋 XML parser for `C`\n\n[![Build Status](https://travis-ci.org/recp/xml.svg?branch=master)](https://travis-ci.org/recp/xml)\n[![Build status](https://ci.appveyor.com/api/projects/status/ugk4im145es00v3g/branch/master?svg=true)](https://ci.appveyor.com/project/recp/xml/branch/master)\n[![Codacy Badge](https://api.codacy.com/project/badge/Grade/c3439f84b19f40d2a5da3b748b3fe6b4)](https://www.codacy.com/manual/recp/xml?utm_source=github.com\u0026amp;utm_medium=referral\u0026amp;utm_content=recp/xml\u0026amp;utm_campaign=Badge_Grade)\n\nThis is very simple and very powerful XML parser. It creates DOM-like data structure and allows to iterate and process XML objects very simple way.\nIt does not alloc any memory for XML itself, it only allocs memory for tokens. It also does not use recursive way to build data structure which makes it very fast to build DOM-like tree structure.\n\n#### Documentation\n\nAlmost all functions (inline versions) and parameters are documented inside related headers. \u003cbr /\u003e\nComplete documentation: TODO.\n\n## Features\n\n- header-only or optional compiled library\n- option to store members and arrays as reverse order or normal\n- option to separate xml tag prefix \n- doesn't alloc memory for keys and values only for tokens\n- creates DOM-like data structure to make it easy to iterate though\n- simple api\n- provides some util functions to print xml, get int32, int64, float, double...\n- very small library\n- unique way to parse XML (check the object map section)\n- helper to get string nodes, primitive values (int, float, bool) for both attribs and values\n\n## TODOs\n\n- [x] provide header only library and optionally compile version\n- [x] provide option to preserve array order (currently array order is reversed, because it is easy to parse it in this way; this may be changed. Please follow new commits or releases)\n- [x] provide option to separate tag prefixes\n- [x] windows build\n- [ ] documentation\n- [x] handle or ignore comments? (ignored)\n- [x] handle or ignore CDATA? (ignored)\n- [x] cmake\n- [ ] tests\n- [ ] extra optimizations\n- [ ] usage in detail\n\n## Build\n\n### Unix (Autotools)\n\n```bash\nsh autogen.sh\n./configure\nmake\n[sudo] make install\n```\n\nyou can grap library in .libs folder after build finished\n\n### Windows (MSBuild)\n\nWindows related build files, project files are located in `win` folder,\nmake sure you are inside `tm/win` folder.\nCode Analysis are enabled, it may take awhile to build\n\n```Powershell\ncd win\n.\\build.bat\n```\n\n##### Cmake options with Defaults:\n\n```CMake\noption(XML_SHARED \"Shared build\" ON)\noption(XML_STATIC \"Static build\" OFF)\noption(XML_USE_C99 \"\" OFF) # C11 \noption(XML_USE_TEST \"Enable Tests\" OFF) # for make check - make test\n```\n\n```bash\nmkdir build \u0026\u0026 cd build\ncmake ..\nmake\n[sudo] make install\n```\n\n### Header-only or Compiled Library\n\nThe functions has the `xmlc_` prefix are compiled version which is called from library. To use this feature you must include `xml/call/xml.h` header.\n\nTo use header-only library you must include `xml/xml.h` header. The functions has the `xml_` prefix are forced to be inlined. When you use this, you don't have to compile the library.\n\ntodo.\n\n#### Example usage\n\nYou can inspect `xml_print()` to view usage in more detail. The example will be updated later to give more detail.\n\n```C\n#include \u003cxml/xml.h\u003e\n#include \u003cxml/print.h\u003e\n\nint main(int argc, const char * argv[]) {\n  xml_doc_t *doc;\n  xml_t     *root;\n  \n  doc  = xml_parse(/* XML string */, XML_DEFAULTS);\n  root = doc-\u003eroot;\n\n  xml_print_human(stderr, root);\n\n  xml_free(doc);\n\n  return 0;\n}\n\n```\n\n```C\n\nconst xml_doc_t *xmlDoc;\nconst xml_t     *xml;\n\nxmlDoc = xml_parse(/* XML string */, XML_DEFAULTS);\nxml    = xmlDoc-\u003eroot-\u003evalue;\n\n/* already defined in util.h */\nXML_INLINE\nbool\nxml_tag_eq(const xml_t * __restrict obj, const char * __restrict str);\n\nwhile (xml) {\n    if (xml_key_eq(xml, \"tag 1\")) {\n      int aNumber;\n\n     aNumber = xml_int32(xml, 0);\n\n     /* ... */\n    } else if (xml_tag_eq(xml, \"tag 2\")) {\n      const char *nonNullTerminatedString;\n      const char *nullTerminatedString;\n\n      /* just pointer */\n      nonNullTerminatedString = xml_string(xml);\n\n       /* null-terminated string (strdup), needs to be freed */\n      nullTerminatedString    = xml_string_dup(xml);\n\n     /* ... */\n    } else if (xml_key_eq(xml, \"tag 3\")) {\n      xml_t *aChild;\n      \n      aChild = xml-\u003evalue;\n      while (aChild) {\n          /* handle child node */\n          aChild = aChild-\u003enext;\n      }\n    }\n\n    xml = xml-\u003enext;\n}\n```\n\n#### Using Object Map\n\n```C\nvoid\ncallback_1(xml_t * __restrict xml, void * __restrict obj) {\n  printf(\"entered callback_1\\n\");\n}\n\nxml = xml_parse(/* XML string */, XML_DEFAULTS);\n\nxml_objmap_t objmap[] = {\n    {\n      .key = \"key1\",\n      .foundFunc = {\n        .func = callback_1\n      }\n    },\n    {\n      .key = \"key2\",\n      .foundFunc = {\n        .func = callback_1\n      }\n    }\n};\n\n/* or you can use macro helpers which is more readable if you don't need more details: */\nxml_objmap_t objmap[] = {\n    XML_OBJMAP_FN(\"key 1\", func1, param1),\n    XML_OBJMAP_FN(\"key 2\", func2, param2),\n    XML_OBJMAP_FN(\"key 3\", func3, param3),\n    /* ... */\n};\n\nxml_objmap_call(xml, objmap, ARRAY_LEN(objmap), NULL);\n```\n\nIn this way you don't have to compare keys in a loop, just map the keys with a function or with userdata. You don't have to use function in this way, you may use to map xml object to userdata which may be a GOTO LABEL (to use compound gotos) or something else. \n\n## License\n\nMIT. check the LICENSE file\n","funding_links":[],"categories":["Structured File Processing","结构化文件处理"],"sub_categories":["XML"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frecp%2Fxml","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frecp%2Fxml","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frecp%2Fxml/lists"}