NOTICE.xml.gz から file-nameの値とcontentIdを取り出す Gauche編
NOTICE.xml.gz から file-nameの値とcontentIdを取り出す
NOTICE.xml.gz から file-nameの値とcontentIdを取り出す by gauche
gzip 圧縮された XMLファイル、NOTICE.xml.gz があったとします。それで XML ファイルのトップレベル licenses タグ内に file-name タグがあって、そのプロパティ contentId の値と その file-name の値を抽出してみるとします。
<licenses> <file-name contentId="1234567890abcdef">value</file-name> <file-name contentId="1234567890abcdef">value</file-name> <file-name contentId="1234567890abcdef">value</file-name> <file-content contentId="1234567890abcdef"><![CDATA[ここにライセンスファイルの中身]]></file-content> </licenses> <!-- contentId はライセンス文の md5ハッシュ値 -->
この NOTICE.xml.gz は AOSP の中で使われているライセンス情報を管理するファイルです。多分検索したら手にはいる。 これをパースしてみよう。
gauche way
gauche だと標準で含まれる rfc.zlib と sxml で gzip 解凍 と xml をサポートしているらしい。
(use rfc.zlib)
(use sxml.ssax)
(use sxml.sxpath)
(use sxml.tools)
(define (gz->raw gz-file raw-file)
(call-with-input-file gz-file
(lambda (in-port)
(call-with-output-file raw-file
(lambda (out-port)
(copy-port
(open-inflating-port in-port :window-bits 47)
out-port))))))
(define (read-xml-file filename)
(call-with-input-file filename
(lambda (port)
(ssax:xml->sxml port '()))))
(define (extract-file-names sxml-data)
((sxpath '(licenses file-name)) sxml-data))
(define (extract-name-contentId record)
(let ((content-id-value
(cadar (filter (lambda (ll) (eq? 'contentId (car ll)))
(cdadr record))))
(file-name-value (caddr record)))
(cons file-name-value content-id-value)))
;;;;
; gzip -d
(gz->raw "NOTICE.xml.gz" "NOTICE.xml")
; S式風xml に変換して file-name 部分を抽出
(define fns
(extract-file-names (read-xml-file "NOTICE.xml")))
; あとはS式なのでごにょごにょ
(map extract-name-contentId fns)