FDO API Reference | Feature Data Objects |
00001 #ifndef FDO_XML_WRITER_H 00002 #define FDO_XML_WRITER_H 00003 // 00004 00005 // 00006 // Copyright (C) 2004-2006 Autodesk, Inc. 00007 // 00008 // This library is free software; you can redistribute it and/or 00009 // modify it under the terms of version 2.1 of the GNU Lesser 00010 // General Public License as published by the Free Software Foundation. 00011 // 00012 // This library is distributed in the hope that it will be useful, 00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 // Lesser General Public License for more details. 00016 // 00017 // You should have received a copy of the GNU Lesser General Public 00018 // License along with this library; if not, write to the Free Software 00019 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00020 // 00021 00022 00023 #include <FdoCommon.h> 00024 00025 /// \brief 00026 /// FdoXmlWriter writes an XML document to a text or binary stream. 00027 /// \note 00028 /// The XML document is not completely written until this object 00029 /// is destroyed by releasing all references to it. Therefore, this object 00030 /// must be destroyed before reading back the document being written. 00031 class FdoXmlWriter : public FdoDisposable 00032 { 00033 public: 00034 /// \brief 00035 /// FdoXmlWriter::LineFormat specifies whether the output XML document 00036 /// has line breaks or indentation. 00037 /// 00038 /// \param LineFormat_None 00039 /// The document is written without line breaks or element indentation. 00040 /// \param LineFormat_Break 00041 /// The document is written with a line break after: 00042 /// <ul> 00043 /// <li> every end element tag 00044 /// <li> every start tag for elements with complex content (sub-elements) 00045 /// </ul> 00046 /// Elements are not indented. 00047 /// \param LineFormat_Indent 00048 /// Same as LineFormat_Break, except that each element immediately following 00049 /// a line break is indented by a certain number of spaces. The number of 00050 /// spaces is the element's nesting level within the document X 3. The root 00051 /// element has nesting level 0. 00052 /// 00053 enum LineFormat { 00054 LineFormat_None, 00055 LineFormat_Break, 00056 LineFormat_Indent 00057 }; 00058 00059 /// \brief 00060 /// Constructs an XML writer on a file 00061 /// 00062 /// \param fileName 00063 /// Input name of the file to write. 00064 /// \param defaultRoot 00065 /// true: all elements written are wrapped in a default root element, named "DataStore". 00066 /// false: the default root element is not written. In this case, the first 00067 /// element written (via WriteStartElement() ) becomes the root element. 00068 /// The caller is responsible for ensuring that only one root element is written 00069 /// (the XML standard disallows multiple root elements). 00070 /// \param lineFormat 00071 /// Input Line break and indentation options 00072 /// for the output document. 00073 /// \param lineLength 00074 /// Input maximum line length. If 0 there is 00075 /// no maximum. Otherwise, a line break is added before an XML attribute is 00076 /// written, if the attribute would have caused the current line to exceed 00077 /// this length. 00078 /// 00079 /// \return 00080 /// Returns FdoXmlWriter 00081 /// 00082 FDO_API_COMMON static FdoXmlWriter* Create( 00083 FdoString* fileName, 00084 FdoBoolean defaultRoot = true, 00085 LineFormat lineFormat = LineFormat_None, 00086 FdoSize lineLength = 0 00087 ); 00088 00089 /// \brief 00090 /// Constructs an XML writer on a stream 00091 /// 00092 /// \param stream 00093 /// Input the stream to write. 00094 /// \param defaultRoot 00095 /// true: all elements written are wrapped in a default root element, named "DataStore". 00096 /// false: the default root element is not written. In this case, the first 00097 /// element written (via WriteStartElement() ) becomes the root element. 00098 /// The caller is responsible for ensuring that only one root element is written 00099 /// (the XML standard disallows multiple root elements). 00100 /// \param lineFormat 00101 /// Input Line break and indentation options 00102 /// for the output document. 00103 /// \param lineLength 00104 /// Input maximum line length. If 0 there is 00105 /// no maximum. Otherwise, a line break is added before an XML attribute is 00106 /// written, if the attribute would have caused the current line to exceed 00107 /// this length. 00108 /// 00109 /// \return 00110 /// Returns FdoXmlWriter 00111 /// 00112 FDO_API_COMMON static FdoXmlWriter* Create( 00113 FdoIoStream* stream, 00114 FdoBoolean defaultRoot = true, 00115 LineFormat lineFormat = LineFormat_None, 00116 FdoSize lineLength = 0 00117 ); 00118 00119 /// \brief 00120 /// Constructs an XML writer on a text writer 00121 /// 00122 /// \param reader 00123 /// Input the text writer. 00124 /// \param defaultRoot 00125 /// true: all elements written are wrapped in a default root element, named "DataStore". 00126 /// false: the default root element is not written. In this case, the first 00127 /// element written (via WriteStartElement() ) becomes the root element. 00128 /// The caller is responsible for ensuring that only one root element is written 00129 /// (the XML standard disallows multiple root elements). 00130 /// \param lineFormat 00131 /// Input Line break and indentation options 00132 /// for the output document. 00133 /// \param lineLength 00134 /// Input maximum line length. If 0 there is 00135 /// no maximum. Otherwise, a line break is added before an XML attribute is 00136 /// written, if the attribute would have caused the current line to exceed 00137 /// this length. 00138 /// 00139 /// \return 00140 /// Returns FdoXmlWriter 00141 /// 00142 FDO_API_COMMON static FdoXmlWriter* Create( 00143 FdoIoTextWriter* writer, 00144 FdoBoolean defaultRoot = true, 00145 LineFormat lineFormat = LineFormat_None, 00146 FdoSize lineLength = 0 00147 ); 00148 00149 /// \brief 00150 /// Gets the underlying text writer. If a text writer was passed to this object 00151 /// then this text writeer is returned. 00152 /// Otherwise, an auto-generated text writer is returned (a text writer 00153 /// wrapped around the file name or stream that was passed to this object) 00154 /// 00155 /// \return 00156 /// Returns the underlying text writer 00157 /// 00158 FDO_API_COMMON FdoIoTextWriter* GetTextWriter(); 00159 00160 /// \brief 00161 /// Gets the underlying stream. If a text writer was passed to this object 00162 /// then the stream for this text writer is returned. 00163 /// If a stream was passed to this object then this stream is returned. 00164 /// If a file name as passed then a auto-generated stream (wrapped around 00165 /// the file) is returned. 00166 /// 00167 /// \return 00168 /// Returns the underlying stream 00169 /// 00170 FDO_API_COMMON FdoIoStream* GetStream() 00171 { 00172 return mTextWriter->GetStream(); 00173 } 00174 00175 /// \brief 00176 /// Gets the current default root state. 00177 /// 00178 /// \return 00179 /// Returns true if the default root element will be written, false otherwise. 00180 /// 00181 FDO_API_COMMON FdoBoolean GetDefaultRoot() 00182 { 00183 return mbDefaultRoot; 00184 } 00185 00186 /// \brief 00187 /// Closes this XML Writer by writing end tags for all 00188 /// elements currently open. Once this function is called, no more 00189 /// elements can be added to the output document. 00190 /// 00191 FDO_API_COMMON void Close(); 00192 00193 /// \brief 00194 /// Sets whether to write the default root element. 00195 /// Must be called before the first element is written, 00196 /// otherwise an exception is thrown 00197 /// 00198 /// \param defaultRoot 00199 /// true: use the default root element ("DataStore") as the root element. 00200 /// false: caller is responsible for writing the root element. 00201 /// 00202 FDO_API_COMMON void SetDefaultRoot( FdoBoolean defaultRoot ); 00203 00204 /// \brief 00205 /// Writes an element start tag to the document 00206 /// 00207 /// \param elementName 00208 /// Input the element name. Must be a valid 00209 /// XML 1.0 element name. 00210 /// 00211 FDO_API_COMMON void WriteStartElement( FdoString* elementName ); 00212 00213 /// \brief 00214 /// Writes the end tag for the current element to the document. 00215 /// A FdoXmlException is thrown if there is no element to end. 00216 /// 00217 FDO_API_COMMON void WriteEndElement(); 00218 00219 /// \brief 00220 /// Writes an attribute to the current element. 00221 /// A FdoXmlException is thrown if this function is called immediately after 00222 /// WriteEndElement(). 00223 /// 00224 /// \param attributeName 00225 /// Input the element name. Must be a valid 00226 /// XML 1.0 attribute name. 00227 /// \param attributeValue 00228 /// Input the element value. 00229 /// 00230 FDO_API_COMMON void WriteAttribute( FdoString* attributeName, FdoString* attributeValue ); 00231 00232 /// \brief 00233 /// Writes simple (character) content for the current element. This function 00234 /// can be called multiple times for the same element. The characters are appended 00235 /// to the element's content. A FdoXmlException is thrown if there is no current 00236 /// element. 00237 /// 00238 /// \param characters 00239 /// Input characters to append to the element content. 00240 /// 00241 FDO_API_COMMON void WriteCharacters( FdoString* characters ); 00242 00243 /// \brief 00244 /// Writes arbitrary bytes to the XML Writer. Caller is responsible 00245 /// for ensuring that the text does not introduce any errors into the 00246 /// XML document. 00247 /// 00248 /// \param characters 00249 /// Input characters to write. 00250 /// 00251 FDO_API_COMMON void WriteBytes( FdoByte* bytes, FdoSize count ); 00252 00253 /// \brief 00254 /// utility function that converts FDO element names to valid XML 00255 /// element or attribute names. Conversion is done by changing each invalid 00256 /// character to a hex pattern ( "-xnnnn-" ). 00257 /// 00258 /// \param name 00259 /// Input the name to encode (convert). 00260 /// 00261 /// \return 00262 /// Returns the encoded name. 00263 /// 00264 FDO_API_COMMON virtual FdoStringP EncodeName ( FdoStringP name ) = 0; 00265 00266 /// \brief 00267 /// Checks if a string is a valid XML 1.0 element or attribute name. 00268 /// 00269 /// \param name 00270 /// Input the string to check. 00271 /// 00272 /// \return 00273 /// Returns true if the string is a valid name, false otherwise. 00274 /// 00275 FDO_API_COMMON virtual FdoBoolean IsValidName ( FdoStringP name ) = 0; 00276 00277 /// \brief 00278 /// Given an element's or attribute's globally unique name ( uri and local name ), 00279 /// this function returns its fully qualified name as per the 00280 /// XML document being written, or the unqualified name if the uri is 00281 /// the default namespace. This is done by searching for the current 00282 /// namespace declaration that references the uri. 00283 /// 00284 /// \remarks 00285 /// If a matching default namespace declaration ( "xmlns=<uri>" ) was 00286 /// found and the name is for an element then the localName is returned. 00287 /// \note 00288 /// According to the XML 1.0 specification, default namespaces do 00289 /// not apply to attribute names, so the default namespace is ignored when the 00290 /// given name is not for an element. 00291 /// \n 00292 /// Otherwise, if a matching namespace declaration was found then 00293 /// "[namespace]:[localName]" is returned. 00294 /// \n 00295 /// Otherwise, L"" is returned (unable to determine qualified name). 00296 /// 00297 /// \param uri 00298 /// Input the URI corresponding to an element. 00299 /// \param uri 00300 /// Input the local name corresponding to an element. 00301 /// \param isElement 00302 /// Input a boolean flag indicating that the URI corresponds to an element. 00303 /// 00304 /// \return 00305 /// Returns the fully qualified name corresponding to the uri. 00306 /// 00307 FDO_API_COMMON FdoStringP UriToQName( FdoString* uri, FdoString* localName, FdoBoolean isElement = true ); 00308 00309 /// \cond DOXYGEN-IGNORE 00310 protected: 00311 FdoXmlWriter() {} 00312 FdoXmlWriter( FdoIoTextWriter* writer, FdoBoolean defaultRoot, LineFormat lineFormat, FdoSize lineLength ); 00313 00314 virtual ~FdoXmlWriter(void); 00315 00316 /// Write the prologue when needed 00317 void WritePrologue(); 00318 /// \endcond 00319 00320 private: 00321 /// XML Element stack element, representing a currently open XML element. 00322 class StackElement : public FdoDisposable 00323 { 00324 public: 00325 static StackElement* Create( FdoStringP elementName, FdoXmlWriter* writer) 00326 { 00327 return new StackElement(elementName, writer); 00328 } 00329 00330 FdoStringP GetName() 00331 { 00332 return mName; 00333 } 00334 00335 /// returns true if this element declares any namespaces. 00336 bool GetHasNsDecl(); 00337 00338 /// set an attribute value for this element. 00339 void SetAttribute( FdoString* attributeName, FdoString* attributeValue ); 00340 00341 /// Flush all the attributes to the output document 00342 void FlushAttributes( FdoIoTextWriterP pWriter ); 00343 00344 /// Generates fully qualified name for the given element from 00345 /// namespace declarations in this element. 00346 FdoStringP UriToQName( FdoString* uri, FdoString* localName, FdoBoolean isElement ); 00347 00348 static FdoStringP EncodeValue ( FdoStringP value ); 00349 00350 protected: 00351 StackElement(); 00352 StackElement( FdoStringP elementName, FdoXmlWriter* writer); 00353 virtual ~StackElement() {} 00354 00355 private: 00356 FdoStringP mName; 00357 FdoXmlAttributesP mAtts; 00358 bool mHasNsDecl; 00359 FdoXmlWriter* mWriter; 00360 00361 }; 00362 00363 typedef FdoPtr<StackElement> StackElementP; 00364 00365 /// Stack of all currently open XML elements. 00366 class ElementStack : public FdoStack<StackElement,FdoXmlException> 00367 { 00368 public: 00369 static ElementStack* Create() {return new ElementStack();} 00370 00371 /// Generates fully qualified name for the given element or attribute from 00372 /// namespace declarations in the stacked elements. 00373 FdoStringP UriToQName( FdoString* uri, FdoString* localName, FdoBoolean isElement ); 00374 00375 protected: 00376 ElementStack() {} 00377 ~ElementStack() {} 00378 virtual void Dispose() 00379 { 00380 delete this; 00381 } 00382 00383 }; 00384 00385 /// Close the currently open start element tag. 00386 void CloseStartElementTag(); 00387 00388 void WriteIndent(); 00389 00390 /// Underlying test writer 00391 FdoIoTextWriterP mTextWriter; 00392 00393 /// true if automatically writing default root element. 00394 FdoBoolean mbDefaultRoot; 00395 00396 /// Tracks whether current element start tag is still open 00397 /// (attributes can be added ) 00398 FdoBoolean mbTagOpen; 00399 00400 /// Tracks whether the document prologue has been written. 00401 FdoBoolean mbPrologueWritten; 00402 00403 /// Tracks whether an element has been written. 00404 FdoBoolean mbElementWritten; 00405 00406 FdoBoolean mbCharsWritten; 00407 00408 /// Stack containing all elements whose end tag has not yet been written. 00409 /// The current (innermost) element is at the top of the stack. 00410 FdoPtr<ElementStack> mElementStack; 00411 00412 FdoStringP mIndent; 00413 FdoInt32 mIndentLevel; 00414 LineFormat mLineFormat; 00415 FdoSize mLineLength; 00416 00417 FdoSize mCharWritten; 00418 }; 00419 00420 /// \brief 00421 /// FdoXmlWriterP is a FdoPtr on FdoXmlWriter, provided for convenience. 00422 typedef FdoPtr<FdoXmlWriter> FdoXmlWriterP; 00423 00424 #endif 00425 00426
Comments or suggestions? Send us feedback. |