00001 // -*- C++ -*- 00002 00003 //============================================================================= 00004 /** 00005 * @file NamespaceSupport.h 00006 * 00007 * NamespaceSupport.h,v 1.10 2006/02/09 22:53:20 kitty Exp 00008 * NamespaceSupport.h,v 1.10 2006/02/09 22:53:20 kitty Exp 00009 * 00010 * @author Nanbor Wang <nanbor@cs.wustl.edu> 00011 */ 00012 //============================================================================= 00013 00014 #ifndef ACEXML_NAMESPACESUPPORT_H 00015 #define ACEXML_NAMESPACESUPPORT_H 00016 00017 #include /**/ "ace/pre.h" 00018 #include "ACEXML/common/ACEXML_Export.h" 00019 00020 #if !defined (ACE_LACKS_PRAGMA_ONCE) 00021 #pragma once 00022 #endif /* ACE_LACKS_PRAGMA_ONCE */ 00023 00024 #include "ACEXML/common/XML_Types.h" 00025 #include "ace/Functor.h" 00026 #include "ace/Hash_Map_Manager.h" 00027 #include "ace/Containers_T.h" 00028 #include "ace/Null_Mutex.h" 00029 00030 00031 typedef ACE_Hash_Map_Entry<ACEXML_String, 00032 ACEXML_String> ACEXML_NS_CONTEXT_ENTRY; 00033 00034 typedef ACE_Hash_Map_Manager_Ex<ACEXML_String, 00035 ACEXML_String, 00036 ACE_Hash<ACEXML_String>, 00037 ACE_Equal_To<ACEXML_String>, 00038 ACE_Null_Mutex> ACEXML_NS_CONTEXT; 00039 00040 typedef ACE_Hash_Map_Iterator_Ex<ACEXML_String, 00041 ACEXML_String, 00042 ACE_Hash<ACEXML_String>, 00043 ACE_Equal_To<ACEXML_String>, 00044 ACE_Null_Mutex> ACEXML_NS_CONTEXT_ITER; 00045 00046 typedef ACE_Hash_Map_Reverse_Iterator_Ex<ACEXML_String, 00047 ACEXML_String, 00048 ACE_Hash<ACEXML_String>, 00049 ACE_Equal_To<ACEXML_String>, 00050 ACE_Null_Mutex> ACEXML_NS_CONTEXT_REVERSE_ITER; 00051 00052 typedef ACE_Unbounded_Queue<const ACEXML_Char *> ACEXML_STR_LIST; 00053 00054 /** 00055 * @class ACEXML_Namespace_Context_Stack NamespaceSupport.h "ACEXML/common/NamespaceSupport.h" 00056 * 00057 * @brief ACEXML_Namespace_Context_Stack implements a simple stack 00058 * that ACEXML_NamespaceSupport uses to keep track of namespace scopes. 00059 * 00060 * @sa ACEXML_NamespaceSupport 00061 */ 00062 class ACEXML_Export ACEXML_Namespace_Context_Stack 00063 { 00064 public: 00065 /// Default constructor. 00066 ACEXML_Namespace_Context_Stack (void); 00067 00068 /// Destructor. 00069 ~ACEXML_Namespace_Context_Stack (void); 00070 00071 /// Push the old namespace before entering into a new namespace scope. 00072 int push (ACEXML_NS_CONTEXT * old); 00073 00074 /// Pop the old namespace when exiting a namespace scope. 00075 ACEXML_NS_CONTEXT *pop (void); 00076 00077 private: 00078 /// Internal stack structure to hold namespace context. 00079 ACE_Unbounded_Stack<ACEXML_NS_CONTEXT*> stack_; 00080 }; 00081 00082 /** 00083 * @class ACEXML_NamespaceSupport NamespaceSupport.h "ACEXML/common/NamespaceSupport.h" 00084 * 00085 * @brief ACEXML_NamespaceSupport provides namespace management 00086 * operation for an XML parser. 00087 * 00088 * This class encapsulates the logic of Namespace processing: it 00089 * tracks the declarations currently in force for each context and 00090 * automatically processes qualified XML 1.0 names into their 00091 * Namespace parts; it can also be used in reverse for generating XML 00092 * 1.0 from Namespaces. 00093 * 00094 * Namespace support objects are reusable, but the reset method must 00095 * be invoked between each session. 00096 * 00097 * Here is a simple session (in Java :-p): 00098 * @code 00099 * String parts[] = new String[3]; 00100 * NamespaceSupport support = new NamespaceSupport(); 00101 * 00102 * support.pushContext(); 00103 * support.declarePrefix("", "http://www.w3.org/1999/xhtml"); 00104 * support.declarePrefix("dc", "http://www.purl.org/dc#"); 00105 * 00106 * String parts[] = support.processName("p", parts, false); 00107 * System.out.println("Namespace URI: " + parts[0]); 00108 * System.out.println("Local name: " + parts[1]); 00109 * System.out.println("Raw name: " + parts[2]); 00110 * 00111 * String parts[] = support.processName("dc:title", parts, false); 00112 * System.out.println("Namespace URI: " + parts[0]); 00113 * System.out.println("Local name: " + parts[1]); 00114 * System.out.println("Raw name: " + parts[2]); 00115 * 00116 * support.popContext(); 00117 * @endcode 00118 * 00119 * Note that this class is optimized for the use case where most 00120 * elements do not contain Namespace declarations: if the same 00121 * prefix/URI mapping is repeated for each context (for example), this 00122 * class will be somewhat less efficient. 00123 * 00124 * @sa ACEXML_Exception 00125 */ 00126 class ACEXML_Export ACEXML_NamespaceSupport 00127 { 00128 public: 00129 /** 00130 * Default constructor. 00131 */ 00132 ACEXML_NamespaceSupport (void); 00133 00134 /** 00135 * Default destructor. 00136 */ 00137 ~ACEXML_NamespaceSupport (void); 00138 00139 /** 00140 * Initialize the namespace support object 00141 */ 00142 int init(void); 00143 00144 /** 00145 * XMLNS default prefix and URI strings. 00146 */ 00147 static const ACEXML_Char *XMLNS_PREFIX; 00148 static const ACEXML_Char *XMLNS; 00149 00150 /** 00151 * Declare a Namespace prefix. Return -1 if the prefix was illegal 00152 * or an internal error occured. Return 0 if the prefix gets declared 00153 * successfully, 1 if the prefix replaces an existing prefix definition. 00154 */ 00155 int declarePrefix (const ACEXML_Char *prefix, 00156 const ACEXML_Char *uri); 00157 00158 /** 00159 * Return all prefixes declared in current context in 00160 * the user-supplied list @a prefixes. It is user's reponsibility 00161 * to ensure the list was empty originally. 00162 */ 00163 int getDeclaredPrefixes (ACEXML_STR_LIST &prefixes) const; 00164 00165 /** 00166 * Return one of the prefixes mapped to a Namespace URI. 00167 */ 00168 const ACEXML_Char *getPrefix (const ACEXML_Char *uri) const; 00169 00170 /** 00171 * Return all prefixes currently declared in the user-supplied list. 00172 * @@ Known bug: This function should only return user-defined prefixes. 00173 */ 00174 int getPrefixes (ACEXML_STR_LIST &prefixes) const; 00175 00176 /** 00177 * Return all prefixes currently declared for a URI in the 00178 * user-supplied list. 00179 */ 00180 int getPrefixes (const ACEXML_Char *uri, 00181 ACEXML_STR_LIST &prefixes) const; 00182 00183 /** 00184 * Look up a prefix and get the currently-mapped Namespace URI. 00185 */ 00186 const ACEXML_Char *getURI (const ACEXML_Char *prefix) const; 00187 00188 /** 00189 * Revert to the previous namespace context. 00190 */ 00191 int popContext (void); 00192 00193 /** 00194 * Process a raw XML 1.0 name. 00195 * @a qName is the raw XML name we want to parse, 00196 * @a uri contains the URI string of the raw name. It points to a null 00197 * string if the namespace is not valid or there's no namespace defined. 00198 * @a name contains the original name without the prefix. 00199 * @a is_attribute specifies whether the name is an attribute or not. 00200 * Attributes have different scoping rules from elements. 00201 */ 00202 int processName (const ACEXML_Char *qName, 00203 const ACEXML_Char *&uri, 00204 const ACEXML_Char *&name, 00205 int is_attribute) const; 00206 00207 /** 00208 * Start a new Namespace context. Prefixes defined in previous 00209 * context are copied over to the new context. 00210 */ 00211 int pushContext (void); 00212 00213 /** 00214 * Reset this Namespace support object for reuse. 00215 * 00216 */ 00217 int reset (void); 00218 00219 private: 00220 /** 00221 * Namespace Context stack. When we entering a new namespace 00222 * context, the old context is duplicated and pushed into 00223 * this stack. 00224 */ 00225 ACEXML_Namespace_Context_Stack ns_stack_; 00226 00227 /** 00228 * The effective namespace context. 00229 */ 00230 ACEXML_NS_CONTEXT *effective_context_; 00231 }; 00232 00233 #include /**/ "ace/post.h" 00234 00235 #endif /* ACEXML_NAMESPACESUPPORT_H */