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