← Blog of oldlisper

Парсим ODS

· 23.10.2015 00:00
· original author: archimag

Парсим ODS

Внезапно потребовалось из программы на CL прочитать ODS файл. Подходящего решения не нашёл, правда особо не искал, потому что это довольно просто сделать самому:

  1. (ql:quickload "zip")
  2. (ql:quickload "cl-libxml2")
  3. (ql:quickload "parse-number")
  4. (defpackage #:my.tools.ods
  5.   (:use #:cl #:iter)
  6.   (:export #:parse-ods-file))
  7. (in-package #:my.tools.ods)
  8. (defun ods-xpath-map ()
  9.   (list* (list "office" "urn:oasis:names:tc:opendocument:xmlns:office:1.0")
  10.          (list "table" "urn:oasis:names:tc:opendocument:xmlns:table:1.0")
  11.          xpath:*default-ns-map*))
  12. (defun parse-ods-content (content)
  13.   (xtree:with-parse-document (doc content)
  14.     (let ((xpath:*default-ns-map* (ods-xpath-map)))
  15.       (iter (for sheet in (xpath:find-list doc "//table:table"))
  16.             (collect (parse-sheet sheet))))))
  17. (defun parse-sheet (sheet)
  18.   (list* (xpath:find-string sheet "@table:name")
  19.          (iter (for row in (xpath:find-list sheet "table:table-row"))
  20.                (collect (parse-row row)))))
  21. (defun parse-row (row)
  22.   (iter (for cell in (xpath:find-list row "table:table-cell"))
  23.         (let ((repeat-number (xpath:find-string cell "@table:number-columns-repeated")))
  24.           (dotimes (i (if repeat-number (parse-integer repeat-number) 1))
  25.             (collect (parse-cell cell))))))
  26. (defun parse-cell (cell)
  27.   (let ((value (xtree:text-content cell))
  28.         (value-type (xpath:find-string cell "@office:value-type")))
  29.     (cond
  30.       ((string= value-type "float")
  31.        (parse-number:parse-number value))
  32.       (t
  33.        value))))
  34. (defun parse-ods-file (pathname)
  35.   (zip:with-zipfile (zipfile pathname)
  36.     (parse-ods-content
  37.      (zip:zipfile-entry-contents
  38.       (zip:get-zipfile-entry "content.xml" zipfile)))))

Мне этого пока хватает.