3 * ====================================================================
\r
4 * Copyright (c) 2000-2006, 2008 CollabNet. All rights reserved.
\r
6 * This software is licensed as described in the file COPYING, which
\r
7 * you should have received as part of this distribution. The terms
\r
8 * are also available at http://subversion.tigris.org/license-1.html.
\r
9 * If newer versions of this license are posted there, you may use a
\r
10 * newer version instead, at your option.
\r
12 * This software consists of voluntary contributions made by many
\r
13 * individuals. For exact contribution history, see the revision
\r
14 * history and logs, available at http://subversion.tigris.org/.
\r
15 * ====================================================================
\r
19 * @brief XML code shared by various Subversion libraries.
\r
26 #include <apr_pools.h>
\r
27 #include <apr_hash.h>
\r
29 #include "svn_types.h"
\r
30 #include "svn_string.h"
\r
34 #endif /* __cplusplus */
\r
36 /** The namespace all Subversion XML uses. */
\r
37 #define SVN_XML_NAMESPACE "svn:"
\r
39 /** Used as style argument to svn_xml_make_open_tag() and friends. */
\r
40 enum svn_xml_open_tag_style {
\r
44 /** <tag ...>, no cosmetic newline */
\r
45 svn_xml_protect_pcdata,
\r
48 svn_xml_self_closing
\r
53 /** Determine if a string of character @a data of length @a len is a
\r
54 * safe bet for use with the svn_xml_escape_* functions found in this
\r
57 * Return @c TRUE if it is, @c FALSE otherwise.
\r
59 * Essentially, this function exists to determine whether or not
\r
60 * simply running a string of bytes through the Subversion XML escape
\r
61 * routines will produce legitimate XML. It should only be necessary
\r
62 * for data which might contain bytes that cannot be safely encoded
\r
63 * into XML (certain control characters, for example).
\r
66 svn_xml_is_xml_safe(const char *data,
\r
69 /** Create or append in @a *outstr an xml-escaped version of @a string,
\r
70 * suitable for output as character data.
\r
72 * If @a *outstr is @c NULL, set @a *outstr to a new stringbuf allocated
\r
73 * in @a pool, else append to the existing stringbuf there.
\r
76 svn_xml_escape_cdata_stringbuf(svn_stringbuf_t **outstr,
\r
77 const svn_stringbuf_t *string,
\r
80 /** Same as svn_xml_escape_cdata_stringbuf(), but @a string is an
\r
84 svn_xml_escape_cdata_string(svn_stringbuf_t **outstr,
\r
85 const svn_string_t *string,
\r
88 /** Same as svn_xml_escape_cdata_stringbuf(), but @a string is a
\r
89 * NULL-terminated C string.
\r
92 svn_xml_escape_cdata_cstring(svn_stringbuf_t **outstr,
\r
97 /** Create or append in @a *outstr an xml-escaped version of @a string,
\r
98 * suitable for output as an attribute value.
\r
100 * If @a *outstr is @c NULL, set @a *outstr to a new stringbuf allocated
\r
101 * in @a pool, else append to the existing stringbuf there.
\r
104 svn_xml_escape_attr_stringbuf(svn_stringbuf_t **outstr,
\r
105 const svn_stringbuf_t *string,
\r
108 /** Same as svn_xml_escape_attr_stringbuf(), but @a string is an
\r
112 svn_xml_escape_attr_string(svn_stringbuf_t **outstr,
\r
113 const svn_string_t *string,
\r
116 /** Same as svn_xml_escape_attr_stringbuf(), but @a string is a
\r
117 * NULL-terminated C string.
\r
120 svn_xml_escape_attr_cstring(svn_stringbuf_t **outstr,
\r
121 const char *string,
\r
125 * Return UTF-8 string @a string if it contains no characters that are
\r
126 * unrepresentable in XML. Else, return a copy of @a string,
\r
127 * allocated in @a pool, with each unrepresentable character replaced
\r
128 * by "?\uuu", where "uuu" is the three-digit unsigned decimal value
\r
129 * of that character.
\r
131 * Neither the input nor the output need be valid XML; however, the
\r
132 * output can always be safely XML-escaped.
\r
134 * @note The current implementation treats all Unicode characters as
\r
135 * representable, except for most ASCII control characters (the
\r
136 * exceptions being CR, LF, and TAB, which are valid in XML). There
\r
137 * may be other UTF-8 characters that are invalid in XML; see
\r
138 * http://subversion.tigris.org/servlets/ReadMsg?list=dev&msgNo=90591
\r
139 * and its thread for details.
\r
141 * @since New in 1.2.
\r
144 svn_xml_fuzzy_escape(const char *string,
\r
148 /*---------------------------------------------------------------*/
\r
150 /* Generalized Subversion XML Parsing */
\r
152 /** A generalized Subversion XML parser object */
\r
153 typedef struct svn_xml_parser_t svn_xml_parser_t;
\r
155 typedef void (*svn_xml_start_elem)(void *baton,
\r
157 const char **atts);
\r
159 typedef void (*svn_xml_end_elem)(void *baton, const char *name);
\r
161 /* data is not NULL-terminated. */
\r
162 typedef void (*svn_xml_char_data)(void *baton,
\r
167 /** Create a general Subversion XML parser */
\r
169 svn_xml_make_parser(void *baton,
\r
170 svn_xml_start_elem start_handler,
\r
171 svn_xml_end_elem end_handler,
\r
172 svn_xml_char_data data_handler,
\r
176 /** Free a general Subversion XML parser */
\r
178 svn_xml_free_parser(svn_xml_parser_t *svn_parser);
\r
181 /** Push @a len bytes of xml data in @a buf at @a svn_parser.
\r
183 * If this is the final push, @a is_final must be set.
\r
185 * An error will be returned if there was a syntax problem in the XML,
\r
186 * or if any of the callbacks set an error using
\r
187 * svn_xml_signal_bailout().
\r
189 * If an error is returned, the @c svn_xml_parser_t will have been freed
\r
190 * automatically, so the caller should not call svn_xml_free_parser().
\r
193 svn_xml_parse(svn_xml_parser_t *svn_parser,
\r
196 svn_boolean_t is_final);
\r
200 /** The way to officially bail out of xml parsing.
\r
202 * Store @a error in @a svn_parser and set all expat callbacks to @c NULL.
\r
205 svn_xml_signal_bailout(svn_error_t *error,
\r
206 svn_xml_parser_t *svn_parser);
\r
212 /*** Helpers for dealing with the data Expat gives us. ***/
\r
214 /** Return the value associated with @a name in expat attribute array @a atts,
\r
215 * else return @c NULL.
\r
217 * (There could never be a @c NULL attribute value in the XML,
\r
218 * although the empty string is possible.)
\r
220 * @a atts is an array of c-strings: even-numbered indexes are names,
\r
221 * odd-numbers hold values. If all is right, it should end on an
\r
222 * even-numbered index pointing to @c NULL.
\r
225 svn_xml_get_attr_value(const char *name,
\r
226 const char **atts);
\r
230 /* Converting between Expat attribute lists and APR hash tables. */
\r
233 /** Create an attribute hash from @c va_list @a ap.
\r
235 * The contents of @a ap are alternating <tt>char *</tt> keys and
\r
236 * <tt>char *</tt> vals, terminated by a final @c NULL falling on an
\r
237 * even index (zero-based).
\r
240 svn_xml_ap_to_hash(va_list ap,
\r
243 /** Create a hash that corresponds to Expat xml attribute list @a atts.
\r
245 * The hash's keys and values are <tt>char *</tt>'s.
\r
247 * @a atts may be NULL, in which case you just get an empty hash back
\r
248 * (this makes life more convenient for some callers).
\r
251 svn_xml_make_att_hash(const char **atts,
\r
255 /** Like svn_xml_make_att_hash(), but takes a hash and preserves any
\r
256 * key/value pairs already in it.
\r
259 svn_xml_hash_atts_preserving(const char **atts,
\r
263 /** Like svn_xml_make_att_hash(), but takes a hash and overwrites
\r
264 * key/value pairs already in it that also appear in @a atts.
\r
267 svn_xml_hash_atts_overlaying(const char **atts,
\r
275 /** Create an XML header and return it in @a *str.
\r
277 * Fully-formed XML documents should start out with a header,
\r
279 * \<?xml version="1.0" encoding="utf-8"?\>
\r
281 * This function returns such a header. @a *str must either be @c NULL, in
\r
282 * which case a new string is created, or it must point to an existing
\r
283 * string to be appended to.
\r
286 svn_xml_make_header(svn_stringbuf_t **str,
\r
290 /** Store a new xml tag @a tagname in @a *str.
\r
292 * If @a *str is @c NULL, set @a *str to a new stringbuf allocated
\r
293 * in @a pool, else append to the existing stringbuf there.
\r
295 * Take the tag's attributes from varargs, a NULL-terminated list of
\r
296 * alternating <tt>char *</tt> key and <tt>char *</tt> val. Do xml-escaping
\r
299 * @a style is one of the enumerated styles in @c svn_xml_open_tag_style.
\r
302 svn_xml_make_open_tag(svn_stringbuf_t **str,
\r
304 enum svn_xml_open_tag_style style,
\r
305 const char *tagname,
\r
309 /** Like svn_xml_make_open_tag(), but takes a @c va_list instead of being
\r
313 svn_xml_make_open_tag_v(svn_stringbuf_t **str,
\r
315 enum svn_xml_open_tag_style style,
\r
316 const char *tagname,
\r
320 /** Like svn_xml_make_open_tag(), but takes a hash table of attributes
\r
321 * (<tt>char *</tt> keys mapping to <tt>char *</tt> values).
\r
323 * You might ask, why not just provide svn_xml_make_tag_atts()?
\r
325 * The reason is that a hash table is the most natural interface to an
\r
326 * attribute list; the fact that Expat uses <tt>char **</tt> atts instead is
\r
327 * certainly a defensible implementation decision, but since we'd have
\r
328 * to have special code to support such lists throughout Subversion
\r
329 * anyway, we might as well write that code for the natural interface
\r
330 * (hashes) and then convert in the few cases where conversion is
\r
331 * needed. Someday it might even be nice to change expat-lite to work
\r
334 * See conversion functions svn_xml_make_att_hash() and
\r
335 * svn_xml_make_att_hash_overlaying(). Callers should use those to
\r
336 * convert Expat attr lists into hashes when necessary.
\r
339 svn_xml_make_open_tag_hash(svn_stringbuf_t **str,
\r
341 enum svn_xml_open_tag_style style,
\r
342 const char *tagname,
\r
343 apr_hash_t *attributes);
\r
346 /** Store an xml close tag @a tagname in @a str.
\r
348 * If @a *str is @c NULL, set @a *str to a new stringbuf allocated
\r
349 * in @a pool, else append to the existing stringbuf there.
\r
352 svn_xml_make_close_tag(svn_stringbuf_t **str,
\r
354 const char *tagname);
\r
359 #endif /* __cplusplus */
\r
361 #endif /* SVN_XML_H */
\r