Парсим ODS
Внезапно потребовалось из программы на CL прочитать ODS файл. Подходящего решения не нашёл, правда особо не искал, потому что это довольно просто сделать самому:
- (ql:quickload "zip")
- (ql:quickload "cl-libxml2")
- (ql:quickload "parse-number")
- (defpackage #:my.tools.ods
- (:use #:cl #:iter)
- (:export #:parse-ods-file))
- (in-package #:my.tools.ods)
- (defun ods-xpath-map ()
- (list* (list "office" "urn:oasis:names:tc:opendocument:xmlns:office:1.0")
- (list "table" "urn:oasis:names:tc:opendocument:xmlns:table:1.0")
- xpath:*default-ns-map*))
- (defun parse-ods-content (content)
- (xtree:with-parse-document (doc content)
- (let ((xpath:*default-ns-map* (ods-xpath-map)))
- (iter (for sheet in (xpath:find-list doc "//table:table"))
- (collect (parse-sheet sheet))))))
- (defun parse-sheet (sheet)
- (list* (xpath:find-string sheet "@table:name")
- (iter (for row in (xpath:find-list sheet "table:table-row"))
- (collect (parse-row row)))))
- (defun parse-row (row)
- (iter (for cell in (xpath:find-list row "table:table-cell"))
- (let ((repeat-number (xpath:find-string cell "@table:number-columns-repeated")))
- (dotimes (i (if repeat-number (parse-integer repeat-number) 1))
- (collect (parse-cell cell))))))
- (defun parse-cell (cell)
- (let ((value (xtree:text-content cell))
- (value-type (xpath:find-string cell "@office:value-type")))
- (cond
- ((string= value-type "float")
- (parse-number:parse-number value))
- (t
- value))))
- (defun parse-ods-file (pathname)
- (zip:with-zipfile (zipfile pathname)
- (parse-ods-content
- (zip:zipfile-entry-contents
- (zip:get-zipfile-entry "content.xml" zipfile)))))
Мне этого пока хватает.