- Main Page
- Related Pages
- Modules
- Classes
- Files

# Writer.h

Go to the documentation of this file.

    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

Please send us your comment about this page