1 ;;; -*- show-trailing-whitespace: t; indent-tabs: nil -*-
3 ;;; Copyright (c) 2007 Ivan Shvedunov. All rights reserved.
4 ;;; Copyright (c) 2007 David Lichteblau. All rights reserved.
6 ;;; Redistribution and use in source and binary forms, with or without
7 ;;; modification, are permitted provided that the following conditions
10 ;;; * Redistributions of source code must retain the above copyright
11 ;;; notice, this list of conditions and the following disclaimer.
13 ;;; * Redistributions in binary form must reproduce the above
14 ;;; copyright notice, this list of conditions and the following
15 ;;; disclaimer in the documentation and/or other materials
16 ;;; provided with the distribution.
18 ;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED
19 ;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 ;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 ;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
22 ;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 ;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
24 ;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 ;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 ;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 ;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 ;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 (in-package :cxml-stp-impl
)
33 (defun vector->pipe
(vector &optional
(start 0))
34 (if (>= start
(length vector
))
36 (xpath::make-pipe
(elt vector start
)
37 (vector->pipe vector
(1+ start
)))))
40 ;;;; XPath protocol implementation for STP
42 ;;;; FIXME: xpath-protocol:child-pipe destructively normalizes the STP tree!
44 (defmethod xpath-protocol:local-name
((node stp
:node
))
47 (defmethod xpath-protocol:namespace-prefix
((node stp
:node
))
48 (namespace-prefix node
))
50 (defmethod xpath-protocol:parent-node
((node stp
:node
))
53 (defmethod xpath-protocol:namespace-uri
((node stp
:node
))
56 (defmethod xpath-protocol:qualified-name
((node stp
:node
))
57 (qualified-name node
))
59 (defmethod xpath-protocol:child-pipe
((node stp
:node
))
62 (defmethod xpath-protocol:child-pipe
((node stp
:parent-node
))
63 (normalize-text-nodes! node
)
64 (vector->pipe
(%children node
)))
66 (defmethod xpath-protocol:attribute-pipe
((node stp
:node
))
69 (defmethod xpath-protocol:attribute-pipe
((node stp
:element
))
70 (list-attributes node
))
72 (defmethod xpath-protocol:namespace-pipe
((node stp
:node
))
73 (when (stp:parent node
)
74 (xpath-protocol:namespace-pipe
(stp:parent node
))))
76 (defstruct (stp-namespace
77 (:constructor make-stp-namespace
(parent prefix uri
)))
82 (defmethod xpath-protocol:child-pipe
((node stp-namespace
)) nil
)
83 (defmethod xpath-protocol:attribute-pipe
((node stp-namespace
)) nil
)
84 (defmethod xpath-protocol:namespace-pipe
((node stp-namespace
)) nil
)
86 (defmethod xpath-protocol:parent-node
((node stp-namespace
))
87 (stp-namespace-parent node
))
88 (defmethod xpath-protocol:local-name
((node stp-namespace
))
89 (stp-namespace-prefix node
))
90 (defmethod xpath-protocol:qualified-name
((node stp-namespace
))
91 (stp-namespace-prefix node
))
92 (defmethod xpath-protocol:namespace-uri
((node stp-namespace
))
93 (stp-namespace-uri node
))
95 (defmethod xpath-protocol:namespace-pipe
((node stp
:element
))
97 (table (make-hash-table :test
'equal
))
99 (labels ((yield (prefix uri
)
100 (unless (gethash prefix table
)
101 (let ((nsnode (make-stp-namespace node prefix uri
)))
102 (setf (gethash prefix table
) nsnode
)
103 (push nsnode current
))))
106 (cons (pop current
) #'iterate
)
112 (map-extra-namespaces #'yield node
)
113 (yield (%namespace-prefix node
)
114 (%namespace-uri node
))
115 (dolist (a (%attributes node
))
116 (when (plusp (length (namespace-prefix a
)))
117 (yield (namespace-prefix a
) (namespace-uri a
))))
118 (setf node
(stp:parent node
))
121 (yield "xml" "http://www.w3.org/XML/1998/namespace")
122 (yield "xmlns" "http://www.w3.org/2000/xmlns/")
127 (defmethod xpath-protocol:string-value
((node node
))
130 (defmethod xpath-protocol:node-type-p
((node node
) type
)
131 (declare (ignore type
))
134 (defmethod xpath-protocol:node-type-p
((node stp-namespace
) type
)
135 (declare (ignore type
))
138 (macrolet ((deftypemapping (class keyword
)
139 `(defmethod xpath-protocol:node-type-p
140 ((node ,class
) (type (eql ,keyword
)))
142 (deftypemapping comment
:comment
)
143 (deftypemapping processing-instruction
:processing-instruction
)
144 (deftypemapping text
:text
)
145 (deftypemapping attribute
:attribute
)
146 (deftypemapping element
:element
)
147 (deftypemapping stp-namespace
:namespace
))
149 (defun normalize-text-nodes! (node)
150 (when (typep node
'stp
:parent-node
)
151 (let ((children (%children node
)))
153 for child across children
155 for b
= (typep child
'text
)
156 thereis
(and b
(or a
(zerop (length (stp:data child
))))))
159 (stp:do-children
(child node
)
161 ((not (typep child
'stp
:text
))
164 (apply #'concatenate
'string
(nreverse previous
)))
166 (setf (%parent
(car results
)) node
)
168 (push child results
))
170 (push (stp:data child
) previous
))
171 ((zerop (length (stp:data child
))))
173 (setf previous
(list (stp:data child
))))))
176 (apply #'concatenate
'string
(nreverse previous
)))
178 (setf (%parent
(car results
)) node
))
179 (setf (cxml-stp-impl::%children node
)
180 (let ((n (length results
)))
183 :initial-contents
(nreverse results
)))))))))