-
Notifications
You must be signed in to change notification settings - Fork 2
/
xml-filter.lisp
66 lines (51 loc) · 2.43 KB
/
xml-filter.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
;;; -*- Mode:Lisp; Syntax:ANSI-Common-Lisp; Coding:utf-8 -*-
;;; This file is part of MusicXML-PWGL.
;;; Copyright (c) 2010 - 2011, Kilian Sprotte. All rights reserved.
;;; This program is free software: you can redistribute it and/or modify
;;; it under the terms of the GNU General Public License as published by
;;; the Free Software Foundation, either version 3 of the License, or
;;; (at your option) any later version.
;;; This program is distributed in the hope that it will be useful,
;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;; You should have received a copy of the GNU General Public License
;;; along with this program. If not, see <http://www.gnu.org/licenses/>.
(defpackage #:musicxml-pwgl.xml-filter
(:use #:cl)
(:export
#:filter-string
#:filter-file))
(in-package #:musicxml-pwgl.xml-filter)
(defclass filter (cxml:sax-proxy)
((names :accessor names :initarg :names
:initform '("b"))
(gate-open :accessor gate-open :initform t)))
(defmethod sax:start-element
((handler filter) namespace-uri local-name qname attributes)
(if (not (member local-name (names handler) :test #'string=))
(when (gate-open handler) (call-next-method))
(setf (gate-open handler) nil)))
(defmethod sax:end-element
((handler filter) namespace-uri local-name qname)
(if (not (member local-name (names handler) :test #'string=))
(when (gate-open handler) (call-next-method))
(setf (gate-open handler) t)))
(defmethod sax:characters ((handler filter) data)
(when (gate-open handler) (call-next-method)))
(defun filter-string (string element-names)
(let* ((octets (sb-ext:string-to-octets string))
(dom (cxml:parse-octets octets (cxml-dom:make-dom-builder))))
(dom:map-document
(make-instance 'filter
:names element-names
:chained-handler (cxml:make-string-sink :canonical t))
dom)))
(defun filter-file (path out-path element-names)
(let ((dom (cxml:parse-file path (cxml-dom:make-dom-builder))))
(with-open-file (out out-path :direction :output :if-exists :supersede)
(dom:map-document (make-instance
'filter
:names element-names
:chained-handler
(cxml:make-character-stream-sink out)) dom))))