svn_xml.h

Go to the documentation of this file.
00001 /**
00002  * @copyright
00003  * ====================================================================
00004  * Copyright (c) 2000-2006 CollabNet.  All rights reserved.
00005  *
00006  * This software is licensed as described in the file COPYING, which
00007  * you should have received as part of this distribution.  The terms
00008  * are also available at http://subversion.tigris.org/license-1.html.
00009  * If newer versions of this license are posted there, you may use a
00010  * newer version instead, at your option.
00011  *
00012  * This software consists of voluntary contributions made by many
00013  * individuals.  For exact contribution history, see the revision
00014  * history and logs, available at http://subversion.tigris.org/.
00015  * ====================================================================
00016  * @endcopyright
00017  *
00018  * @file svn_xml.h
00019  * @brief XML code shared by various Subversion libraries.
00020  */
00021 
00022 
00023 
00024 #ifndef SVN_XML_H
00025 #define SVN_XML_H
00026 
00027 #include <apr.h>
00028 #include <apr_pools.h>
00029 #include <apr_hash.h>
00030 
00031 #include "svn_error.h"
00032 #include "svn_string.h"
00033 
00034 #ifdef __cplusplus
00035 extern "C" {
00036 #endif /* __cplusplus */
00037   
00038 /** The namespace all Subversion XML uses. */
00039 #define SVN_XML_NAMESPACE "svn:"
00040 
00041 /** Used as style argument to svn_xml_make_open_tag() and friends. */
00042 enum svn_xml_open_tag_style {
00043   /** <tag ...> */
00044   svn_xml_normal = 1,
00045 
00046   /** <tag ...>, no cosmetic newline */
00047   svn_xml_protect_pcdata,
00048 
00049   /** <tag .../>  */
00050   svn_xml_self_closing
00051 };
00052   
00053 
00054 
00055 /** Determine if a string of character @a data of length @a len is a
00056  * safe bet for use with the svn_xml_escape_* functions found in this
00057  * header. 
00058  * 
00059  * Return @c TRUE if it is, @c FALSE otherwise.
00060  *
00061  * Essentially, this function exists to determine whether or not
00062  * simply running a string of bytes through the Subversion XML escape
00063  * routines will produce legitimate XML.  It should only be necessary
00064  * for data which might contain bytes that cannot be safely encoded
00065  * into XML (certain control characters, for example).
00066  */
00067 svn_boolean_t svn_xml_is_xml_safe(const char *data, 
00068                                   apr_size_t len);
00069 
00070 /** Create or append in @a *outstr an xml-escaped version of @a string,
00071  * suitable for output as character data.
00072  *
00073  * If @a *outstr is @c NULL, store a new stringbuf, else append to the
00074  * existing stringbuf there.
00075  */
00076 void svn_xml_escape_cdata_stringbuf(svn_stringbuf_t **outstr,
00077                                     const svn_stringbuf_t *string,
00078                                     apr_pool_t *pool);
00079 
00080 /** Same as svn_xml_escape_cdata_stringbuf(), but @a string is an
00081  * @c svn_string_t.
00082  */
00083 void svn_xml_escape_cdata_string(svn_stringbuf_t **outstr,
00084                                  const svn_string_t *string,
00085                                  apr_pool_t *pool);
00086 
00087 /** Same as svn_xml_escape_cdata_stringbuf(), but @a string is a
00088  * null-terminated C string.
00089  */
00090 void svn_xml_escape_cdata_cstring(svn_stringbuf_t **outstr,
00091                                   const char *string,
00092                                   apr_pool_t *pool);
00093 
00094 
00095 /** Create or append in @a *outstr an xml-escaped version of @a string,
00096  * suitable for output as an attribute value.
00097  *
00098  * If @a *outstr is @c NULL, store a new stringbuf, else append to the
00099  * existing stringbuf there.
00100  */
00101 void svn_xml_escape_attr_stringbuf(svn_stringbuf_t **outstr,
00102                                    const svn_stringbuf_t *string,
00103                                    apr_pool_t *pool);
00104 
00105 /** Same as svn_xml_escape_attr_stringbuf(), but @a string is an
00106  * @c svn_string_t.
00107  */
00108 void svn_xml_escape_attr_string(svn_stringbuf_t **outstr,
00109                                 const svn_string_t *string,
00110                                 apr_pool_t *pool);
00111 
00112 /** Same as svn_xml_escape_attr_stringbuf(), but @a string is a
00113  * null-terminated C string.
00114  */
00115 void svn_xml_escape_attr_cstring(svn_stringbuf_t **outstr,
00116                                  const char *string,
00117                                  apr_pool_t *pool);
00118 
00119 /**
00120  * Return UTF-8 string @a string if it contains no characters that are
00121  * unrepresentable in XML.  Else, return a copy of @a string,
00122  * allocated in @a pool, with each unrepresentable character replaced
00123  * by "?\uuu", where "uuu" is the three-digit unsigned decimal value
00124  * of that character.
00125  *
00126  * Neither the input nor the output need be valid XML; however, the
00127  * output can always be safely XML-escaped.
00128  *
00129  * @note The current implementation treats all Unicode characters as
00130  * representable, except for most ASCII control characters (the
00131  * exceptions being CR, LF, and TAB, which are valid in XML).  There
00132  * may be other UTF-8 characters that are invalid in XML; see
00133  * http://subversion.tigris.org/servlets/ReadMsg?list=dev&msgNo=90591
00134  * and its thread for details.
00135  *
00136  * @since New in 1.2.
00137  */
00138 const char *svn_xml_fuzzy_escape(const char *string,
00139                                  apr_pool_t *pool);
00140 
00141 
00142 /*---------------------------------------------------------------*/
00143 
00144 /* Generalized Subversion XML Parsing */
00145 
00146 /** A generalized Subversion XML parser object */
00147 typedef struct svn_xml_parser_t svn_xml_parser_t;
00148 
00149 typedef void (*svn_xml_start_elem)(void *baton,
00150                                    const char *name,
00151                                    const char **atts);
00152 
00153 typedef void (*svn_xml_end_elem)(void *baton, const char *name);
00154 
00155 /* data is not NULL-terminated. */
00156 typedef void (*svn_xml_char_data)(void *baton,
00157                                   const char *data,
00158                                   apr_size_t len);
00159 
00160 
00161 /** Create a general Subversion XML parser */
00162 svn_xml_parser_t *svn_xml_make_parser(void *baton,
00163                                       svn_xml_start_elem start_handler,
00164                                       svn_xml_end_elem end_handler,
00165                                       svn_xml_char_data data_handler,
00166                                       apr_pool_t *pool);
00167 
00168 
00169 /** Free a general Subversion XML parser */
00170 void svn_xml_free_parser(svn_xml_parser_t *svn_parser);
00171 
00172 
00173 /** Push @a len bytes of xml data in @a buf at @a svn_parser.  
00174  *
00175  * If this is the final push, @a is_final must be set.  
00176  *
00177  * An error will be returned if there was a syntax problem in the XML,
00178  * or if any of the callbacks set an error using
00179  * svn_xml_signal_bailout().  
00180  *
00181  * If an error is returned, the @c svn_xml_parser_t will have been freed
00182  * automatically, so the caller should not call svn_xml_free_parser().
00183  */ 
00184 svn_error_t *svn_xml_parse(svn_xml_parser_t *parser,
00185                            const char *buf,
00186                            apr_size_t len,
00187                            svn_boolean_t is_final);
00188 
00189 
00190 
00191 /** The way to officially bail out of xml parsing.
00192  *
00193  * Store @a error in @a svn_parser and set all expat callbacks to @c NULL.
00194  */
00195 void svn_xml_signal_bailout(svn_error_t *error,
00196                             svn_xml_parser_t *svn_parser);
00197 
00198 
00199 
00200 
00201 
00202 /*** Helpers for dealing with the data Expat gives us. ***/
00203 
00204 /** Return the value associated with @a name in expat attribute array @a atts,
00205  * else return @c NULL.
00206  *
00207  * (There could never be a @c NULL attribute value in the XML,
00208  * although the empty string is possible.)
00209  * 
00210  * @a atts is an array of c-strings: even-numbered indexes are names,
00211  * odd-numbers hold values.  If all is right, it should end on an
00212  * even-numbered index pointing to @c NULL. 
00213  */
00214 const char *svn_xml_get_attr_value(const char *name, const char **atts);
00215 
00216 
00217 
00218 /* Converting between Expat attribute lists and APR hash tables. */
00219 
00220 
00221 /** Create an attribute hash from @c va_list @a ap. 
00222  *
00223  * The contents of @a ap are alternating <tt>char *</tt> keys and 
00224  * <tt>char *</tt> vals, terminated by a final @c NULL falling on an 
00225  * even index (zero-based).
00226  */
00227 apr_hash_t *svn_xml_ap_to_hash(va_list ap, apr_pool_t *pool);
00228 
00229 /** Create a hash that corresponds to Expat xml attribute list @a atts.
00230  *
00231  * The hash's keys and values are <tt>char *</tt>'s.
00232  *
00233  * @a atts may be null, in which case you just get an empty hash back
00234  * (this makes life more convenient for some callers).
00235  */
00236 apr_hash_t *svn_xml_make_att_hash(const char **atts, apr_pool_t *pool);
00237 
00238 
00239 /** Like svn_xml_make_att_hash(), but takes a hash and preserves any
00240  * key/value pairs already in it.
00241  */
00242 void svn_xml_hash_atts_preserving(const char **atts,
00243                                   apr_hash_t *ht,
00244                                   apr_pool_t *pool);
00245 
00246 /** Like svn_xml_make_att_hash(), but takes a hash and overwrites
00247  * key/value pairs already in it that also appear in @a atts.
00248  */
00249 void svn_xml_hash_atts_overlaying(const char **atts,
00250                                   apr_hash_t *ht,
00251                                   apr_pool_t *pool);
00252 
00253 
00254 
00255 /* Printing XML */
00256 
00257 /** Create an XML header and return it in @a *str.
00258  *
00259  * Fully-formed XML documents should start out with a header,
00260  * something like 
00261  *         <?xml version="1.0" encoding="utf-8"?>
00262  * 
00263  * This function returns such a header.  @a *str must either be @c NULL, in
00264  * which case a new string is created, or it must point to an existing
00265  * string to be appended to.
00266  */
00267 void svn_xml_make_header(svn_stringbuf_t **str, apr_pool_t *pool);
00268 
00269 
00270 /** Store a new xml tag @a tagname in @a *str.
00271  *
00272  * If @a str is @c NULL, allocate @a *str in @a pool; else append the new 
00273  * tag to @a *str, allocating in @a str's pool
00274  *
00275  * Take the tag's attributes from varargs, a null-terminated list of
00276  * alternating <tt>char *</tt> key and <tt>char *</tt> val.  Do xml-escaping 
00277  * on each val.
00278  *
00279  * @a style is one of the enumerated styles in @c svn_xml_open_tag_style.
00280  */
00281 void svn_xml_make_open_tag(svn_stringbuf_t **str,
00282                            apr_pool_t *pool,
00283                            enum svn_xml_open_tag_style style,
00284                            const char *tagname,
00285                            ...);
00286 
00287 
00288 /** Like svn_xml_make_open_tag(), but takes a @c va_list instead of being
00289  * variadic.
00290  */
00291 void svn_xml_make_open_tag_v(svn_stringbuf_t **str,
00292                              apr_pool_t *pool,
00293                              enum svn_xml_open_tag_style style,
00294                              const char *tagname,
00295                              va_list ap);
00296 
00297 
00298 /** Like svn_xml_make_open_tag(), but takes a hash table of attributes
00299  * (<tt>char *</tt> keys mapping to <tt>char *</tt> values).
00300  *
00301  * You might ask, why not just provide svn_xml_make_tag_atts()?
00302  *
00303  * The reason is that a hash table is the most natural interface to an
00304  * attribute list; the fact that Expat uses <tt>char **</tt> atts instead is
00305  * certainly a defensible implementation decision, but since we'd have
00306  * to have special code to support such lists throughout Subversion
00307  * anyway, we might as well write that code for the natural interface
00308  * (hashes) and then convert in the few cases where conversion is
00309  * needed.  Someday it might even be nice to change expat-lite to work
00310  * with apr hashes.
00311  *
00312  * See conversion functions svn_xml_make_att_hash() and
00313  * svn_xml_make_att_hash_overlaying().  Callers should use those to
00314  * convert Expat attr lists into hashes when necessary.
00315  */
00316 void svn_xml_make_open_tag_hash(svn_stringbuf_t **str,
00317                                 apr_pool_t *pool,
00318                                 enum svn_xml_open_tag_style style,
00319                                 const char *tagname,
00320                                 apr_hash_t *attributes);
00321 
00322 
00323 /** Makes a close tag. */
00324 void svn_xml_make_close_tag(svn_stringbuf_t **str,
00325                             apr_pool_t *pool,
00326                             const char *tagname);
00327 
00328 
00329 
00330 #ifdef __cplusplus
00331 }
00332 #endif /* __cplusplus */
00333 
00334 #endif /* SVN_XML_H */

Generated on Tue Oct 30 01:59:52 2007 for Subversion by  doxygen 1.5.2