{"id":28932172,"url":"https://github.com/ndw/org-to-xml","last_synced_at":"2025-07-03T18:32:22.737Z","repository":{"id":138758344,"uuid":"171468737","full_name":"ndw/org-to-xml","owner":"ndw","description":"Library to convert Emacs org-mode files to XML","archived":false,"fork":false,"pushed_at":"2020-08-04T07:11:35.000Z","size":86,"stargazers_count":20,"open_issues_count":1,"forks_count":3,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-06-22T16:11:46.682Z","etag":null,"topics":["emacs","org-mode","xml"],"latest_commit_sha":null,"homepage":null,"language":"Emacs Lisp","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ndw.png","metadata":{"files":{"readme":"README.org","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}},"created_at":"2019-02-19T12:20:13.000Z","updated_at":"2024-12-03T06:27:30.000Z","dependencies_parsed_at":null,"dependency_job_id":"2c355631-bb44-47c0-abbf-11b9426f9aa4","html_url":"https://github.com/ndw/org-to-xml","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/ndw/org-to-xml","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ndw%2Forg-to-xml","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ndw%2Forg-to-xml/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ndw%2Forg-to-xml/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ndw%2Forg-to-xml/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ndw","download_url":"https://codeload.github.com/ndw/org-to-xml/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ndw%2Forg-to-xml/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263379296,"owners_count":23457828,"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":["emacs","org-mode","xml"],"created_at":"2025-06-22T16:09:13.090Z","updated_at":"2025-07-03T18:32:22.726Z","avatar_url":"https://github.com/ndw.png","language":"Emacs Lisp","funding_links":[],"categories":[],"sub_categories":[],"readme":"#+TITLE: org-to-xml\n#+STARTUP: showeverything\n\nThis project contains a library to convert Emacs org-mode files to\nXML: [[*om-to-xml][om-to-xml]].\n\nThe goal is a complete and accurate translation of the internal\n~org-mode~ data structures to XML. This produces XML that isn’t\nespecially pretty, but the assumption is that downstream XML\nprocessing tools can be used to transform it.\n\n* What’s new?\n\n** 04 August 2020\n   + Renamed default branch to ~main~.\n   + Updated dependency (the ~om.el~ package was renamed ~org-ml~)\n\n* om-to-xml\n\nThis projects started began with [[*org-to-xml (obsolete)][org-to-xml]], but development stalled\nwhen I realized that I didn’t really have a solid understanding of the\nunderlying Org data structures and what I really needed to write first\nwas a library that provided a consistent API that I could use in the\nconversion. (This is not a criticism of the Org developers; there are\nstill corners of Emacs lisp that I don’t understand very well.)\n\nLo and behold! Nate Dwarshuis has written [[https://github.com/ndwarshuis/om.el][just such a library]]! The\n~om-to-xml~ library is a rewrite of my XML conversion on top of that\nlibrary.\n\nIt does a more complete and accurate job and has a few extensibility\nmechanisms that ~org-to-xml~ did not:\n\n+ Whitespace handling\n+ Attribute handling\n+ Custom element processing\n\n** How to use it\n\nInstall the library somewhere. I use [[https://github.com/raxod502/straight.el][straight.el]], but you can just\ndownload the library and put it on your load path any way you like.\n\nRun ~m-x om-to-xml~ in a buffer where you’re viewing an Org mode file.\nAn XML representation will be constructed and saved. If the Org mode\nfile is ~notes.org~, the XML file will be saved in ~notes.xml~.\n\n** How it works\n\nFor the curious, here’s how it works.\n\nConsider, [[file:tests/simple.org][an org file]]:\n\n   #+BEGIN_SRC org\n   #+TITLE: Some Title\n   #+AUTHOR: Norman Walsh\n   #+DATE: 2019-02-19\n   \n   A paragraph with \u003cmarkup\u003e in it. This isn’t intended to be meaningful\n   or useful.\n   \n   * First level heading\n     :PROPERTIES:\n     :CUSTOM_ID: first\n     :END:\n   \n   ** TODO This is an example TODO item.\n      DEADLINE: \u003c2019-02-26 Tue +1w\u003e\n      :PROPERTIES:\n      :CREATED:  [2019-02-19 Tue 06:39]\n      :SRC:      [[file:/projects/emacs/org-to-xml/README.md::For%20the%20curious,%20here%E2%80%99s%20how%20it%20works.]]\n      :END:\n   \n   See [[https://orgmode.org/][org-mode]] for more information about ~org-mode~.\n   #+END_SRC\n\n1. First, it’s parsed by ~om~, swaths of which I’ve elided:\n    #+BEGIN_SRC elisp\n((keyword (:key \"TITLE\" :value \"Some Title\"))\n (keyword (:key \"AUTHOR\" :value \"Norman Walsh\"))\n (keyword (:key \"DATE\" :value \"2019-02-19\"))\n (paragraph\n  (:parent (section (:post-affiliated 64) #1))\n  #(\"A paragraph with \u003cmarkup\u003e in it. This isn’t intended to be meaningful\nor useful.\n\" 0 81 (:parent #1)))\n (headline\n  (:raw-value \"First level heading\" :level 1 :CUSTOM_ID \"first\"\n   :title (#(\"First level heading\" 0 19 (:parent #1))))\n (section\n  (:parent #1)\n  (property-drawer\n   (:parent #2)\n   (node-property (:key \"CUSTOM_ID\" :value \"first\" :parent #3))))\n (headline\n  (:raw-value \"This is an example TODO item.\" :level 2\n   :todo-keyword #(\"TODO\" 0 4 (fontified t face org-todo))\n   :todo-type todo\n   :deadline (timestamp\n              (:type active :raw-value \"\u003c2019-02-26 Tue +1w\u003e\"\n               :year-start 2019 :month-start 2 :day-start 26\n               :year-end 2019 :month-end 2 :day-end 26\n               :repeater-type cumulate :repeater-value 1\n               :repeater-unit week))\n   :SRC \"[[file:/projects/emacs/org-to-xml/README.md::For%20the%20curious,%20here%E2%80%99s%20how%20it%20works.]]\"\n   :CREATED \"[2019-02-19 Tue 06:39]\"\n   :title (#(\"This is an example TODO item.\" 0 29 (:parent #2)))\n   :parent #1)\n  (section\n   (:parent #2)\n   (planning\n    (:closed nil\n     :deadline (timestamp\n                (:type active :raw-value \"\u003c2019-02-26 Tue +1w\u003e\"\n                       :year-start 2019 :month-start 2 :day-start 26\n                       :year-end 2019 :month-end 2 :day-end 26\n                       :repeater-type cumulate :repeater-value 1\n                       :repeater-unit week)) :parent #3))\n   (property-drawer\n    (:parent #3)\n    (node-property (:key \"CREATED\" :value \"[2019-02-19 Tue 06:39]\" :parent #4))\n    (node-property (:key \"SRC\" :value \"[[file:/projects/emacs/org-to-xml/README.md::For%20the%20curious,%20here%E2%80%99s%20how%20it%20works.]]\" :parent #4)))\n   (paragraph\n    (:parent #3)\n    #(\"See \" 0 4 (:parent #4))\n    (link (:type \"https\" :path \"//orgmode.org/\" :format bracket\n           :raw-link \"https://orgmode.org/\" :parent #4)\n          #(\"org-mode\" 0 8 (:parent #5)))\n    #(\"for more information about \" 0 27 (:parent #4))\n    (code (:value \"org-mode\" :parent #4)) #(\".\n\" 0 2 (:parent #4)))))))\n    #+END_SRC\n2. A buffer is created to store the XML, and the om data is traversed\n   emiting XML elements for each node. The node properties become\n   attributes, except for ignored properties and properties that come\n   from a [[https://orgmode.org/manual/Properties-and-Columns.html#Properties-and-Columns][properties drawer]] which are always ignored.\n3. If a post-processing function has been provided, it is run.\n4. Save the file.\n   #+BEGIN_SRC xml\n\u003c?xml version=\"1.0\"?\u003e\n\u003c!-- Converted from org-mode to XML by om-to-xml version 0.0.1 --\u003e\n\u003c!-- See https://github.com/ndw/org-to-xml --\u003e\n\u003cdocument xmlns=\"https://nwalsh.com/ns/org-to-xml\"\u003e\n\u003ckeyword key=\"TITLE\" value=\"Some Title\"/\u003e\n\u003ckeyword key=\"AUTHOR\" value=\"Norman Walsh\"/\u003e\n\u003ckeyword key=\"DATE\" value=\"2019-02-19\"/\u003e\n\n\u003cparagraph\u003eA paragraph with \u0026lt;markup\u0026gt; in it. This isn’t intended to be meaningful\nor useful.\n\u003c/paragraph\u003e\n\u003cheadline raw-value=\"First level heading\" level=\"1\"\u003e\u003ctitle\u003eFirst level heading\u003c/title\u003e\n\u003csection\u003e\n\u003cproperty-drawer\u003e\n\u003cnode-property key=\"CUSTOM_ID\" value=\"first\"/\u003e\n\u003c/property-drawer\u003e\n\u003c/section\u003e\n\n\u003cheadline raw-value=\"This is an example TODO item.\" level=\"2\" todo-keyword=\"TODO\" todo-type=\"todo\" SRC=\"[[file:/projects/emacs/org-to-xml/README.md::For%20the%20curious,%20here%E2%80%99s%20how%20it%20works.]]\" CREATED=\"[2019-02-19 Tue 06:39]\"\u003e\u003cdeadline\u003e\u003ctimestamp type=\"active\" raw-value=\"\u0026lt;2019-02-26 Tue +1w\u0026gt;\" year-start=\"2019\" month-start=\"2\" day-start=\"26\" year-end=\"2019\" month-end=\"2\" day-end=\"26\" repeater-type=\"cumulate\" repeater-value=\"1\" repeater-unit=\"week\"/\u003e\u003c/deadline\u003e\u003ctitle\u003eThis is an example TODO item.\u003c/title\u003e\n\u003csection\u003e\u003cplanning/\u003e\n\u003cproperty-drawer\u003e\n\u003cnode-property key=\"CREATED\" value=\"[2019-02-19 Tue 06:39]\"/\u003e\n\u003cnode-property key=\"SRC\" value=\"[[file:/projects/emacs/org-to-xml/README.md::For%20the%20curious,%20here%E2%80%99s%20how%20it%20works.]]\"/\u003e\n\u003c/property-drawer\u003e\n\n\u003cparagraph\u003eSee \u003clink type=\"https\" path=\"//orgmode.org/\" format=\"bracket\" raw-link=\"https://orgmode.org/\"\u003eorg-mode\u003c/link\u003e\nfor more information about \u003ccode value=\"org-mode\"/\u003e.\n\u003c/paragraph\u003e\n\u003c/section\u003e\n\u003c/headline\u003e\n\u003c/headline\u003e\u003c/document\u003e\n   #+END_SRC\n\nIt’s been twenty years since I tried to do anything much more interesting than\na keybinding in [[https://en.wikipedia.org/wiki/Emacs_Lisp][elisp]]. I expect the code, especially the tree walking, is embarrassingly\ncrude. Suggestions for improvement, or simply pointers to the bits of the\n[[https://www.gnu.org/software/emacs/manual/elisp.html][elisp manual]] I should read again, most humbly solicited.\n\nI also confess, I’m completely winging it on current function\nnaming/namspacing conventions.\n\n\n* Pros and Cons\n\nThere are two obvious ways to approach the problem of converting .org files to .xml.\n\n1. Use the [[https://orgmode.org/worg/exporters/ox-overview.html][ox framework]].\n2. Do it the hard way.\n\nMy goal in this project is to have a complete dump of the org\nstructures in XML. That rules out the =ox= framework. The =ox=\nframework is definitely the place to start if you want to convert from\nan unknown org file and extract the information that you know about.\nBut it flattens structures like the property drawer so that it’s\nimpossible to extract /everything/ with fidelity, even the things you\n/don’t/ know about.\n\nSo this code attempts to do it the hard way. But I’m also lying when I\nsay I want a /complete/ dump of the org structures. I want a dump of\nthe /meaningful/ structures. One person’s meaning is another person’s\npointless cruft, however.\n\nExamples of structures I don’t consider meaningful:\n\n+ The =pre-blank= and =post-blank= properties that the org data\n  structures use to encode spaces in some circumstances.\n+ Leading blanks in code blocks.\n+ Leading spaces in paragraphs.\n\nIt’s likely that this list will grow as I learn more about the Org\ndata strutures. Unless I give up on this project altogether, of\ncourse.\n\n* org-to-xml (obsolete)\n\nYou can still find ~org-to-xml.el~ in this repository’s history (at tag\n[[https://github.com/ndw/org-to-xml/tree/0.0.5][0.0.5]], for example). I’ve removed it from the master branch because I\nreally think it’s a dead end and it caused confusion for at least some\nusers.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fndw%2Forg-to-xml","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fndw%2Forg-to-xml","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fndw%2Forg-to-xml/lists"}