Org to XML (redux)
I still want XML out. I still always want XML out.
(This is a revisit of Org to XML from a few years ago. It’s remotely within the bounds of possibility that you might want to look at that for some context before you read what follows.)
I went to publish a weblog post recently and it didn’t work. I got a
weird elisp error about comparing nil
to -1
. My normal weblog
posting workflow starts with an Org mode file and winds its way
through XML on its way to a database (in Docker
containers for local preview) and deeper still into the abyss.
Nevermind all that right now.
Trouble was, a couple of weeks earlier, I’d upgraded to Emacs 30 which probably upgraded me to Org mode 9.7.x and may have upgraded the om.el library that I depend on. A quick “I’ll rewind to Emacs 29 and see if that fixes it to get the post published” didn’t fix it. Luckily I could do it by hand.
On Sunday, I set out to fix org-to-xml
.
The first thing I discovered was a change to the Org data structures.
There’s a new :standard-properties
array. The nil
was caused by
the fact that the :end
property had moved into that array. Fixed
that. Back in business!
Yeah. Not so much. For very simple documents, that was fine, but for more complex documents, the parsed data structures included “deferred properties” a new feature of Org mode 9.7 that improves performance. (The deferred properties are lazily evaluated.)
Attempting to do string operations on a deferred property is an error.
I could not figure out how to get Org to evaluate deferred
properties. It’s possible that I overlooked something in the
documentation somewhere, but I tried a good long while. The closest I
got was a comment in org-element-ast.el
that says:
;; Note that `org-element-copy' unconditionally resolves deferred
;; properties. This is useful to generate pure (in functional sense)
;; AST.
Except as far as I can tell, it doesn’t. At least, my attempts to copy
the objects with org-element-copy
did not evaluate their deferred descendants.
Luckily, somewhat randomly and in desperation, I discovered that
(org-element-parse-buffer)
returns the whole tree with no deferred
properties. So I switched to using that. (It’s not entirely clear why
I was doing something else in the first place.)
With a few more tweaks, I got it working again. The resulting XML is a little different, but it’s the same in all the fine detail. In fact, my weblog publishing XSLT consumed it without a hitch.
So I can easily make weblog posts again. Which you might consider a good thing or a bad thing, depending.
P.S. I moved the project to Codeberg so in the very unlikely event that
you’re also using this package, you’ll want to download the most
recent version from there or update your straight.el
recipe:
(use-package om-to-xml :straight
(om-to-xml :type git :host codeberg
:repo "ndw/org-to-xml" :branch "main"))
Share and enjoy.