1 | [[tags:eggs]] |
---|
2 | |
---|
3 | This is version 0.3 of the '''sxml-modifications''' extension library for Chicken Scheme. |
---|
4 | |
---|
5 | [[toc:]] |
---|
6 | |
---|
7 | == Sxml-modifications |
---|
8 | |
---|
9 | The {{modif}} parts of the [[http://cvs.sourceforge.net/viewcvs.py/ssax/sxml-tools/|sxml-tools]] from the [[http://ssax.sf.net|SSAX project]] at Sourceforge. |
---|
10 | |
---|
11 | == Requirements |
---|
12 | |
---|
13 | * [[srfi-1]] |
---|
14 | * [[sxpath]] |
---|
15 | |
---|
16 | == Documentation |
---|
17 | |
---|
18 | This egg provides procedures for making modifications to SXML |
---|
19 | documents, functional-style. |
---|
20 | |
---|
21 | Some documentation is available in |
---|
22 | [[https://web.archive.org/web/20170608200039/http://modis.ispras.ru/Lizorkin/sxml-tutorial.html#hevea:modif|Dmitry |
---|
23 | Lizorkin's tutorial]] and the [[http://ssax.sf.net|SSAX homepage]]. |
---|
24 | Note that the SSAX documentation uses the more awkward and arbitrary |
---|
25 | {{sxml:}} or {{modif:}} prefixes. |
---|
26 | |
---|
27 | The initial documentation on this wiki page came straight from the |
---|
28 | comments in the extremely well-documented source code. It's |
---|
29 | recommended you read the code if you want to learn more. |
---|
30 | |
---|
31 | Modifications are done to all nodes that match an xpath expression. |
---|
32 | These can be either textual "standard" XPath or [[sxpath]] |
---|
33 | expressions. |
---|
34 | |
---|
35 | <procedure>(sxml-modify [update-specifier ...])</procedure> |
---|
36 | |
---|
37 | Returns a procedure which accepts a document and returns a modified |
---|
38 | copy of this document. How it will be modified depends on the |
---|
39 | {{update-specifier}}s passed to it. Each update-specifier is a list |
---|
40 | of two or three elements: |
---|
41 | |
---|
42 | update-specifier ::= (xpath-location-path action [action-parameter ...]) |
---|
43 | |
---|
44 | {{xpath-location-path}} addresses the node(s) to be transformed, in |
---|
45 | the form of an XPath location path. If the location path is absolute, |
---|
46 | it addresses the node(s) with respect to the root of the document |
---|
47 | being transformed. If the location path is relative, it addresses the |
---|
48 | node(s) with respect to the node selected by the previous |
---|
49 | update-specifier. The location path in the first update-specifier |
---|
50 | always addresses the node(s) with respect to the root of the |
---|
51 | document. We'll further refer to the node with respect of which the |
---|
52 | location path is evaluated as to the base-node for this location path. |
---|
53 | |
---|
54 | {{action}} specifies the modification to be made over each of the |
---|
55 | node(s) addressed by the location path. Possible actions are described |
---|
56 | below. |
---|
57 | |
---|
58 | {{action-parameter}}s are additional parameters supplied for the |
---|
59 | action. The number of parameters and their semantics depend on the |
---|
60 | definite action. |
---|
61 | |
---|
62 | Each {{action}} is either a symbol that describes what to do, or a |
---|
63 | handler lambda which performs the action itself. The allowed symbols |
---|
64 | are as follows: |
---|
65 | |
---|
66 | ; {{delete}} : deletes the node. Expects no action-parameters |
---|
67 | ; {{delete-undeep}} : deletes the node, but keeps all its content (which thus moves to one level upwards in the document tree). Expects no action-parameters. |
---|
68 | ; {{insert-into}} : inserts the new node(s) as the last children of the given node. The new node(s) are specified in SXML as action-parameters. |
---|
69 | ; {{insert-following}}, {{insert-preceding}} : inserts the new node(s) after (before) the given node. Action-parameters are the same as for {{insert-into}}. |
---|
70 | ; {{replace}} : replaces the given node with the new node(s). Action-parameters are the same as for {{insert-into}}. |
---|
71 | ; {{rename}} : renames the given node. The node to be renamed must be a pair (i.e. not a text node). A single action-parameter is expected, which is to be a Scheme symbol to specify the new name of the given node. |
---|
72 | ; {{move-into}} : moves the given node to a new location. The single action-parameter is the location path, which addresses the new location with respect to the given node as the base node. The given node becomes the last child of the node selected by the parameter location path. |
---|
73 | ; {{move-following}}, {{move-preceding}} : the given node is moved to the location respectively after (before) the node selected by the parameter location path. |
---|
74 | |
---|
75 | If a handler is passed, it should look like {{(lambda (node context base-node) ...)}}. |
---|
76 | The {{node}} is the current target of the {{xpath-location-path}} in the current |
---|
77 | update specifier. {{context}} is a list that consists of the symbol {{*CONTEXT*}}, followed by |
---|
78 | the current node and all its ancestors that were looked at during the XPath matching process |
---|
79 | (as per [[sxpath]]'s {{context-sxpath}} module). {{base-node}} is the node that was used |
---|
80 | as the starting point for the current {{xpath-location-path}} (useful if it's a relative |
---|
81 | path; you can "see" the previous update specifier's node this way). |
---|
82 | |
---|
83 | The handler can return either an SXML node, which will then replace |
---|
84 | the source document's node, or a nodeset (list of nodes), in which |
---|
85 | case it will splice this set into the place occupied by the source |
---|
86 | node. If an empty nodeset -- ie, {{'()}} -- is returned, this has the |
---|
87 | effect of deleting the source node. |
---|
88 | |
---|
89 | Example: |
---|
90 | |
---|
91 | <enscript highlight="scheme"> |
---|
92 | (define doc |
---|
93 | '(*TOP* |
---|
94 | (*PI* xml "version='1.0'") |
---|
95 | (purchaseOrder (@ (orderDate "07.23.2001")) |
---|
96 | (recipient |
---|
97 | (name "Dennis Scannell") |
---|
98 | (street "175 Perry Lea Side Road")) |
---|
99 | (order |
---|
100 | (cd (@ (title "Little Lion") (artist "Brooks Williams"))))))) |
---|
101 | |
---|
102 | (define delete-recipient (sxml-modify '("purchaseOrder/recipient" delete))) |
---|
103 | (delete-recipient doc) |
---|
104 | => |
---|
105 | (*TOP* |
---|
106 | (*PI* xml "version='1.0'") |
---|
107 | (purchaseOrder (@ (orderDate "07.23.2001")) |
---|
108 | ;; (recipient ...) is gone |
---|
109 | (order |
---|
110 | (cd (@ (title "Little Lion") (artist "Brooks Williams")))))) |
---|
111 | |
---|
112 | ;; insert-into accepts any number of action-parameters, being the node(s) to insert at the end |
---|
113 | ((sxml-modify '("purchaseOrder/recipient" insert-into (postalCode "05676") (city "Footown"))) doc) |
---|
114 | => |
---|
115 | (*TOP* |
---|
116 | (*PI* xml "version='1.0'") |
---|
117 | (purchaseOrder (@ (orderDate "07.23.2001")) |
---|
118 | (recipient |
---|
119 | (name "Dennis Scannell") |
---|
120 | (street "175 Perry Lea Side Road") |
---|
121 | (postalCode "05676") ; New |
---|
122 | (city "Footown")) ; New |
---|
123 | (order |
---|
124 | (cd (@ (title "Little Lion") (artist "Brooks Williams")))))) |
---|
125 | </enscript> |
---|
126 | |
---|
127 | <procedure>(sxml-modify! [update-specifier ...])</procedure> |
---|
128 | |
---|
129 | Destructively updating version of {{sxml-modify}}. Like the |
---|
130 | linear-updating variants of SRFI-1, you should use the return value of |
---|
131 | this procedure rather than assuming the original document was mutated |
---|
132 | in-place. |
---|
133 | |
---|
134 | <procedure>(sxml-insert-following node-specifier)</procedure> |
---|
135 | <procedure>(sxml-insert-preceding node-specifier)</procedure> |
---|
136 | <procedure>(sxml-insert-into node-specifier)</procedure> |
---|
137 | <procedure>(sxml-rename new-name)</procedure> |
---|
138 | <procedure>sxml-delete</procedure> |
---|
139 | <procedure>sxml-delete-undeep</procedure> |
---|
140 | |
---|
141 | These procedures all correspond to the action symbols accepted by |
---|
142 | {{sxml-modify}}. There are no procedures corresponding to |
---|
143 | {{move-into}}, {{move-preceding}}, {{move-following}} or {{replace}}. |
---|
144 | |
---|
145 | The {{sxml-delete}} and {{sxml-delete-undeep}} procedures can only be |
---|
146 | put directly into the action-parameters list as-is, which means this |
---|
147 | adds zero expressiveness over the corresponding symbols. |
---|
148 | |
---|
149 | The {{insert-following}}, {{insert-preceding}} and {{insert-into}} |
---|
150 | procedures all accept a {{node-specifier}} procedure of two arguments |
---|
151 | which must return a node or node-set which shall be inserted. The |
---|
152 | first argument of the procedure is the context, the second is the base |
---|
153 | node. |
---|
154 | |
---|
155 | The {{sxml-rename}} procedure accepts a symbol which indicates the new |
---|
156 | element name to use for the matched nodes. |
---|
157 | |
---|
158 | Here's the example from {{sxml-modify}} using these procedures instead |
---|
159 | of action symbols: |
---|
160 | |
---|
161 | <enscript highlight="scheme"> |
---|
162 | (define doc |
---|
163 | '(*TOP* |
---|
164 | (*PI* xml "version='1.0'") |
---|
165 | (purchaseOrder (@ (orderDate "07.23.2001")) |
---|
166 | (recipient |
---|
167 | (name "Dennis Scannell") |
---|
168 | (street "175 Perry Lea Side Road")) |
---|
169 | (order |
---|
170 | (cd (@ (title "Little Lion") (artist "Brooks Williams"))))))) |
---|
171 | |
---|
172 | (define delete-recipient (sxml-modify `("purchaseOrder/recipient" ,sxml-delete))) |
---|
173 | (delete-recipient doc) |
---|
174 | => |
---|
175 | (*TOP* |
---|
176 | (*PI* xml "version='1.0'") |
---|
177 | (purchaseOrder (@ (orderDate "07.23.2001")) |
---|
178 | ;; (recipient ...) is gone |
---|
179 | (order |
---|
180 | (cd (@ (title "Little Lion") (artist "Brooks Williams")))))) |
---|
181 | |
---|
182 | ;; insert-into accepts any number of action-parameters, being the node(s) to insert at the end |
---|
183 | ((sxml-modify `("purchaseOrder/recipient" |
---|
184 | ,(sxml-insert-into |
---|
185 | (lambda (context base-node) |
---|
186 | (list '(postalCode "05676") '(city "Footown")))))) |
---|
187 | doc) |
---|
188 | => |
---|
189 | (*TOP* |
---|
190 | (*PI* xml "version='1.0'") |
---|
191 | (purchaseOrder (@ (orderDate "07.23.2001")) |
---|
192 | (recipient |
---|
193 | (name "Dennis Scannell") |
---|
194 | (street "175 Perry Lea Side Road") |
---|
195 | (postalCode "05676") ; New |
---|
196 | (city "Footown")) ; New |
---|
197 | (order |
---|
198 | (cd (@ (title "Little Lion") (artist "Brooks Williams")))))) |
---|
199 | </enscript> |
---|
200 | |
---|
201 | == About this egg |
---|
202 | |
---|
203 | === Author |
---|
204 | |
---|
205 | [[http://okmij.org/ftp/|Oleg Kiselyov]], [[http://metapaper.net/|Kirill Lisovsky]], [[https://web.archive.org/web/20171030192758/http://modis.ispras.ru/Lizorkin/|Dmitry Lizorkin]]. |
---|
206 | |
---|
207 | === Version history |
---|
208 | |
---|
209 | ; 0.3 : Add sxml- prefix to all exported functions |
---|
210 | ; 0.2 : Ported to Chicken 5 |
---|
211 | ; 0.1 : First Chicken 4 release |
---|
212 | |
---|
213 | === License |
---|
214 | |
---|
215 | The sxml-tools are in the public domain. |
---|