xmlreader.h

Go to the documentation of this file.
00001 /*
00002  * The information in this file is
00003  * Copyright(c) 2007 Ball Aerospace & Technologies Corporation
00004  * and is subject to the terms and conditions of the
00005  * GNU Lesser General Public License Version 2.1
00006  * The license text is available from   
00007  * http://www.gnu.org/licenses/lgpl.html
00008  */
00009 
00010 #ifndef XMLREADER_H
00011 #define XMLREADER_H
00012 
00013 #include <iterator>
00014 #include <stdio.h>
00015 
00016 #include "Filename.h"
00017 #include "LocationType.h"
00018 #include "MessageLogMgr.h"
00019 #include "MessageLog.h"
00020 #include "XercesIncludes.h"
00021 #include "xmlbase.h"
00022 
00023 class Font;
00024 
00025 /** @file xmlreader.h
00026  *  @brief XML utilities and functionality for reading and parsing
00027  */
00028 
00029 /**
00030  * This class reads and parses XML.
00031  * @ingroup app_xml
00032  *
00033  * @par requirements
00034  * Apache Xerces-C++ version 3.1.1
00035  */
00036 class XmlReader : public XmlBase
00037 {
00038 public:
00039    /**
00040     * Create an %XmlReader.
00041     *
00042     * @param pLog
00043     *        Optional MessageLog to be passed to XmlBase.
00044     *
00045     * @param bValidate
00046     *        Should the %XmlReader perform validation? It is strongly
00047     *        suggested that you always perform validation except when
00048     *        this is not possible. (such as during development, before
00049     *        XSD entries are made)
00050     */
00051    XmlReader(MessageLog* pLog = NULL, bool bValidate = true);
00052 
00053    /**
00054     * Destroy and cleanup the %XmlReader object.
00055     */
00056    ~XmlReader();
00057 
00058    /**
00059     * Parse a file.
00060     *
00061     * @param pFn
00062     *        The file to parse, as a Filename. Should not be \c NULL.
00063     *
00064     * @param endTag
00065     *        If not empty, the parse will halt when this end tag is reached.
00066     *
00067     * @return The root element. Returns \c NULL for failure.
00068     */
00069    XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument* parse(const Filename* pFn, std::string endTag = "");
00070 
00071    /**
00072     * Parse a file.
00073     *
00074     * @param fn
00075     *        The file to parse, as a string.
00076     *
00077     * @param endTag
00078     *        If not empty, the parse will halt when this end tag is reached.
00079     *
00080     * @return The root element. Returns \c NULL for failure.
00081     */
00082    XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument* parse(std::string fn, std::string endTag = "");
00083 
00084    /**
00085     * Parse a string.  This method should not be used if validation has been
00086     * enabled for this XmlReader.
00087     *
00088     * @param str
00089     *        The string to parse.
00090     *
00091     * @return The root element. Returns \c NULL for failure.
00092     */
00093    XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument* parseString(const std::string& str);
00094 
00095    /**
00096     * Perform an XPath query on the parsed document.
00097     *
00098     *
00099     * @param expression
00100     *        A valid XPath 2.0 expression.
00101     *
00102     * @param type
00103     *        The type of result requested. Allowed values: DOMXPathResult::FIRST_RESULT_TYPE,
00104     *        DOMXPathResult::ITERATOR_RESULT_TYPE, or DOMXPathResult::SNAPSHOT_RESULT_TYPE.
00105     *
00106     * @param reuse
00107     *        If this is true, the DOMXPathResult will be reused for each query. If this
00108     *        is false, a new result will be generated. If true, the XmlReader retains
00109     *        ownership of the result. If false, the caller takes ownership of the result.
00110     *
00111     * @return The result of the XPath query. \c NULL if the query failed or no document is loaded.
00112     */
00113    XERCES_CPP_NAMESPACE_QUALIFIER DOMXPathResult* query(const std::string& expression,
00114       XERCES_CPP_NAMESPACE_QUALIFIER DOMXPathResult::ResultType type, bool reuse = true);
00115 
00116 public: // struct and static utility functions
00117    /**
00118     * Convert a string to another type.
00119     *
00120     * This templated class converts a string
00121     * to a template specified type using
00122     * a std::stringstream.
00123     *
00124     * @see std::stringstream
00125     */
00126    template<typename T>
00127    class StringStreamAssigner
00128    {
00129    public:
00130       /**
00131        * Convert a string to another type.
00132        *
00133        * @param pVal
00134        *        The string representation of a \b T
00135        *
00136        * @return The converted \b T. If \e arg does not
00137        *         contain a valid string representation
00138        *         of a \b T, the return value is the default
00139        *         value of \b T.
00140        */
00141       T operator()(const char* pVal)
00142       {
00143          std::stringstream s(pVal);
00144          T tmp;
00145          s >> tmp;
00146          return tmp;
00147       }
00148    };
00149 
00150    /**
00151     * Convert a const char * to another type.
00152     *
00153     * This templated class converts a const char *
00154     * to a template specified type by first converting
00155     * it to a std::string. \b T must have a std::string
00156     * conversion operator or a constructor which takes
00157     * a std::string.
00158     */
00159    template<typename T>
00160    class StringAssigner
00161    {
00162    public:
00163       /**
00164        * Convert a const char * to another type.
00165        *
00166        * @param pVal
00167        *        The const char * representation of a \b T
00168        *
00169        * @return The converted \b T.
00170        */
00171       T operator()(const char* pVal)
00172       {
00173          return std::string(pVal);
00174       }
00175    };
00176 
00177    /**
00178     * Convert a const char * to another type.
00179     *
00180     * This templated class converts a const char *
00181     * to a template specified type.
00182     * \b T must have a constructor which takes a const char *.
00183     */
00184    template<typename T>
00185    class ParseStringAssigner
00186    {
00187    public:
00188       /**
00189        * Convert a const char * to another type.
00190        *
00191        * @param pVal
00192        *        The const char * representation of a \b T
00193        *
00194        * @return The converted \b T. The caller takes ownership.
00195        */
00196       T* operator()(const char* pVal)
00197       {
00198          return new T(pVal);
00199       }
00200    };
00201 
00202    /**
00203     * Convert a Unicode string to a vector of objects.
00204     *
00205     * The Unicode string is tokenized using XML list tokenization
00206     * and passed into a vector. The individual values are converted
00207     * from the tokenized strings to \b T using the functor \b B.
00208     *
00209     * Example:
00210     *  @code
00211     *    vector<int> *pIntVec(NULL);
00212     *    pIntVec = reinterpret_cast<vector<int>* >(StrToVector<int, StringStreamAssigner<int> >(X("1 2 3 4")));
00213     *  @endcode
00214     *
00215     * @param pStr
00216     *        The Unicode string to parse.
00217     *
00218     * @return A pointer to a \b vector<T> which has
00219     *         been created with \e new. The caller
00220     *         takes ownership of this vector.
00221     */
00222    template<typename T, class B>
00223    static void* StrToVector(const XMLCh* pStr)
00224    {
00225       std::vector<T>* v(new std::vector<T>);
00226       XERCES_CPP_NAMESPACE_QUALIFIER XMLStringTokenizer t(pStr);
00227       B bb;
00228       while (t.hasMoreTokens())
00229       {
00230          v->push_back(bb(A(t.nextToken())));
00231       }
00232 
00233       return reinterpret_cast<void*>(v);
00234    }
00235 
00236    /**
00237     * Convert a Unicode string to a vector of objects.
00238     *
00239     * The Unicode string is tokenized using XML list tokenization
00240     * and passed into a vector. The individual values are converted
00241     * from the tokenized strings to \b T using the functor \b B.
00242     *
00243     * Example:
00244     *  @code
00245     *    vector<int> intVec;
00246     *    StrToVector<int,StringStreamAssigner<int> >(intVec, X("1 2 3 4")));
00247     *  @endcode
00248     *
00249     * @param vec
00250     *        The vector to place the values in.
00251     *
00252     * @param pStr
00253     *        The Unicode string to parse.
00254     */
00255    template<typename T, class B>
00256    static void StrToVector(typename std::vector<T>& vec, const XMLCh* pStr)
00257    {
00258       XERCES_CPP_NAMESPACE_QUALIFIER XMLStringTokenizer t(pStr);
00259       B bb;
00260       while (t.hasMoreTokens())
00261       {
00262          vec.push_back(bb(A(t.nextToken())));
00263       }
00264    }
00265 
00266    /**
00267     * Convert a Unicode string to a LocationType.
00268     *
00269     * The Unicode string is tokenized using XML list tokenization.
00270     *
00271     * @param pStr
00272     *        The Unicode string to parse.
00273     *
00274     * @param loc
00275     *        Output argument. The LocationType in which to store the result.
00276     */
00277    static bool StrToLocation(const XMLCh* pStr, LocationType& loc)
00278    {
00279       XERCES_CPP_NAMESPACE_QUALIFIER XMLStringTokenizer t(pStr);
00280       if (t.hasMoreTokens())
00281       {
00282          loc.mX = atof(A(t.nextToken()));
00283          if (t.hasMoreTokens())
00284          {
00285             loc.mY = atof(A(t.nextToken()));
00286             return true;
00287          }
00288       }
00289 
00290       return false;
00291    }
00292 
00293    /**
00294     * Convert a Unicode string to a quad coordinate.
00295     *
00296     * The Unicode string is tokenized using XML list tokenization.
00297     * The coordinate is represented by the four arguments \e a, \e b, \e c, and \e d.
00298     * If fewer than four tokens are available, the remaining coordinate values
00299     * are set to 0.0. This means, it is possible to parse 1, 2, 3 or 4, coordinate
00300     * lists with the function.
00301     *
00302     * Example:
00303     *  @code
00304     *     // Parse a quad coord
00305     *     {
00306     *       double a,b,c,d;
00307     *       StrToQuadCoord(X("1.2 3.4 5.6 7.8"), a, b, c, d);
00308     *     }
00309     *
00310     *     // Now parse a tri coord
00311     *     {
00312     *       double r, g, b, dummy;
00313     *       StrToQuadCoord(X("12.4 44.0 16.85"), r, g, b, dummy);
00314     *     }
00315     *
00316     *     // Finally, an example of parsing a double coord
00317     *     {
00318     *       double x, y, dummy;
00319     *       StrToQuadCoord(X("42.43 15.0"), x, y, dummy, dummy);
00320     *     }
00321     *
00322     *  @endcode
00323     *
00324     * @param pStr
00325     *        The Unicode string to parse.
00326     *
00327     * @param a
00328     *        Output argument. The first part of the quad-coord.
00329     * @param b
00330     *        Output argument. The second part of the quad-coord.
00331     * @param c
00332     *        Output argument. The third part of the quad-coord.
00333     * @param d
00334     *        Output argument. The fourth part of the quad-coord.
00335     */
00336    static void StrToQuadCoord(const XMLCh* pStr, double& a, double& b, double& c, double& d)
00337    {
00338       a = 0.0;
00339       b = 0.0;
00340       c = 0.0;
00341       d = 0.0;
00342 
00343       XERCES_CPP_NAMESPACE_QUALIFIER XMLStringTokenizer t(pStr);
00344       if (t.hasMoreTokens())
00345       {
00346          a = atof(A(t.nextToken()));
00347       }
00348 
00349       if (t.hasMoreTokens())
00350       {
00351          b = atof(A(t.nextToken()));
00352       }
00353 
00354       if (t.hasMoreTokens())
00355       {
00356          c = atof(A(t.nextToken()));
00357       }
00358 
00359       if (t.hasMoreTokens())
00360       {
00361          d = atof(A(t.nextToken()));
00362       }
00363    }
00364 
00365    /**
00366     * An exception class representing an error or warning while reading and parsing.
00367     */
00368    class XmlReaderException : public XmlException
00369    {
00370    public:
00371       /**
00372        * Create a new %XmlReaderException.
00373        *
00374        * @param msg
00375        *        The message associated with this exception.
00376        *
00377        * @param binary
00378        *        The file (or string) being parsed is likely a binary file.
00379        *        It is easy for the parser to determine when the parse string
00380        *        is likely a binary (or non-XML) file. Since the application supports
00381        *        loading of some older binary files, this is useful information
00382        *        for the caller as they can attempt to load the file using the old
00383        *        deserialization methods.
00384        */
00385       XmlReaderException(std::string msg, bool binary) :
00386          XmlBase::XmlException(msg),
00387          mBin(binary) {}
00388 
00389       virtual ~XmlReaderException() {}
00390 
00391       /**
00392        * Returns the state of the \e binary flag.
00393        *
00394        * @return Is this possibly a binary file?
00395        */
00396       bool isBinary()
00397       {
00398          return mBin;
00399       }
00400 
00401       using XmlException::str;
00402       /**
00403        * This override appends an additional notice when the
00404        * file may be binary.
00405        *
00406        * @return The message associated with this exception.
00407        */
00408       virtual std::string str()
00409       {
00410          std::string msg(XmlBase::XmlException::str());
00411          if (isBinary())
00412          {
00413             msg += " :: file may be binary";
00414          }
00415 
00416          return msg;
00417       }
00418 
00419    private:
00420       bool mBin;
00421    };
00422 
00423    /**
00424     * An exception class representing an error or warning while parsing the DOM
00425     */
00426    class DomParseException : public XmlException
00427    {
00428    public:
00429       /**
00430        * Create a new %DomParseException.
00431        *
00432        * @param msg
00433        *        The message associated with this exception.
00434        *
00435        * @param pNode
00436        *        The DOM node that caused the exception.
00437        */
00438       DomParseException(std::string msg, XERCES_CPP_NAMESPACE_QUALIFIER DOMNode* pNode) :
00439          XmlBase::XmlException(msg),
00440          mpNode(pNode) {}
00441 
00442       /**
00443        * Destroy and cleanup this exception.
00444        */
00445       virtual ~DomParseException() {}
00446 
00447       /**
00448        * Find out what DOM node caused the exception.
00449        *
00450        * @return The DOMNode that caused the exception.
00451        */
00452       XERCES_CPP_NAMESPACE_QUALIFIER DOMNode* where()
00453       {
00454          return mpNode;
00455       }
00456 
00457       using XmlException::str;
00458       /**
00459        * Get the message associated with this exception.
00460        *
00461        * This will append information about which DOM node
00462        * caused the exception.
00463        *
00464        * @return The message associated with this exception.
00465        */
00466       virtual std::string str()
00467       {
00468          std::string msg(XmlBase::XmlException::str());
00469          if (where() != NULL)
00470          {
00471             msg += " :: nodename=";
00472             msg += A(where()->getNodeName());
00473          }
00474          return msg;
00475       }
00476 
00477    private:
00478       XERCES_CPP_NAMESPACE_QUALIFIER DOMNode* mpNode;
00479    };
00480 
00481 private:
00482    XERCES_CPP_NAMESPACE_QUALIFIER DOMImplementationLS* mpImpl;
00483    XERCES_CPP_NAMESPACE_QUALIFIER DOMLSParser* mpParser;
00484    std::string mXmlSchemaLocation;
00485    XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument* mpDoc;
00486    XERCES_CPP_NAMESPACE_QUALIFIER DOMXPathResult* mpResult;
00487 };
00488 
00489 /**
00490  * Convert a null-terminated char array to a std::string.
00491  *
00492  * This is an explicit specialization of the StringStreamAssigner template.
00493  */
00494 template<>
00495 class XmlReader::StringStreamAssigner<std::string>
00496 {
00497 public:
00498    /**
00499     * Convert a null-terminated char array to a std::string.
00500     *
00501     * @param pVal
00502     *        The null-terminated char array.
00503     *
00504     * @return The char array converted to a std::string.
00505     */
00506    std::string operator()(const char* pVal)
00507    {
00508       return std::string(pVal);
00509    }
00510 };
00511 
00512 
00513 /**
00514  * Class required by Xerces for parsing.
00515  */
00516 class BinFILEInputStream : public XERCES_CPP_NAMESPACE_QUALIFIER BinInputStream
00517 {
00518 public:
00519    BinFILEInputStream(FILE* pFp, XERCES_CPP_NAMESPACE_QUALIFIER MemoryManager* const pManager =
00520                       XERCES_CPP_NAMESPACE_QUALIFIER XMLPlatformUtils::fgMemoryManager) :
00521       mpFp(pFp),
00522       mpManager(pManager) {}
00523 
00524    ~BinFILEInputStream() {}
00525 
00526    virtual XMLFilePos curPos() const
00527    {
00528       return static_cast<XMLFilePos>(ftell(mpFp));
00529    }
00530 
00531    virtual XMLSize_t readBytes(XMLByte* const pToFill, const XMLSize_t maxToRead)
00532    {
00533       return static_cast<XMLSize_t>(fread(pToFill, sizeof(XMLByte), maxToRead, mpFp));
00534    }
00535 
00536    virtual const XMLCh* getContentType() const
00537    {
00538       return 0;
00539    }
00540 
00541 private:
00542    BinFILEInputStream(const BinFILEInputStream& rhs);
00543    BinFILEInputStream& operator=(const BinFILEInputStream& rhs);
00544    FILE* mpFp;
00545    XERCES_CPP_NAMESPACE_QUALIFIER MemoryManager* mpManager;
00546 };
00547 
00548 /**
00549  * Class required by Xerces for parsing.
00550  */
00551 class FILEInputSource : public XERCES_CPP_NAMESPACE_QUALIFIER InputSource
00552 {
00553 public:
00554    FILEInputSource(FILE* pFp, XERCES_CPP_NAMESPACE_QUALIFIER MemoryManager* const pManager =
00555                    XERCES_CPP_NAMESPACE_QUALIFIER XMLPlatformUtils::fgMemoryManager) :
00556       mpFp(pFp),
00557       mpManager(pManager) {}
00558 
00559    ~FILEInputSource() {}
00560 
00561    virtual const XMLCh* getEncoding() const
00562    {
00563       return 0;
00564    }
00565 
00566    virtual const XMLCh* getPublicId() const
00567    {
00568       return 0;
00569    }
00570 
00571    virtual const XMLCh* getSystemId() const
00572    {
00573       return 0;
00574    }
00575 
00576    virtual const XMLCh* getBaseURI() const
00577    {
00578       return 0;
00579    }
00580 
00581    virtual void setEncoding(const XMLCh* const encodingStr) {}
00582    virtual void setPublicId(const XMLCh* const publicId) {}
00583    virtual void setSystemId(const XMLCh* const systemId) {}
00584    virtual void setBaseURI(const XMLCh* const baseURI) {}
00585 
00586    virtual XERCES_CPP_NAMESPACE_QUALIFIER BinInputStream* makeStream() const
00587    {
00588       return new(mpManager) BinFILEInputStream(mpFp, mpManager);
00589    }
00590 
00591    virtual void setIssueFatalErrorIfNotFound(const bool flag) {}
00592 
00593    virtual bool getIssueFatalErrorIfNotFound() const
00594    {
00595       return false;
00596    }
00597 
00598    virtual void release() {}
00599 
00600 private:
00601    FILEInputSource(const FILEInputSource& rhs);
00602    FILEInputSource& operator=(const FILEInputSource& rhs);
00603    FILE* mpFp;
00604    XERCES_CPP_NAMESPACE_QUALIFIER MemoryManager* mpManager;
00605 };
00606 
00607 /**
00608  *  This macro creates a for-loop that iterates over the child nodes of a 
00609  *  specified parent node.
00610  *
00611  *  @param pParent
00612  *        A non-\c NULL node over whose children to iterate
00613  *  @param pChild
00614  *        The variable name that will be given to each child node.
00615  */
00616 #define FOR_EACH_DOMNODE(pParent, pChild) \
00617    for (XERCES_CPP_NAMESPACE_QUALIFIER DOMNode* pChild = pParent->getFirstChild(); \
00618       pChild != NULL; \
00619       pChild = pChild->getNextSibling())
00620 
00621 /**
00622  *  This is a convenience method that returns a decendent of a DOMElement in 
00623  *  an XML hierarchy.
00624  *
00625  *  @note This can be inefficient if called multiple times in a method. In this
00626  *        case, it is usually best to manually loop through the child nodes and
00627  *        process each as it is traversed.
00628  *
00629  *  @param pParent
00630  *            The DOMElement to start the search from.
00631  *
00632  *  @param pName
00633  *            The full path of the decendent node from the specified parent, with 
00634  *            element parentage specified with '/'. For example, the following
00635  *            code will return the node called "baz" from the element
00636  *            called "bar", which is a child of the element called "foo" which
00637  *            is a child of pParent.
00638  *  @code
00639  *  DOMNode *pNode = findChildNode(pParent, "foo/bar/baz");
00640  *  @endcode
00641  *
00642  *  @return The found node or \c NULL if the node is not found.
00643  */
00644 XERCES_CPP_NAMESPACE_QUALIFIER DOMNode* findChildNode(XERCES_CPP_NAMESPACE_QUALIFIER DOMNode* pParent,
00645    const char* pName);
00646 
00647 /**
00648  *  This is a convenience method that returns an attribute of a DOMElement in 
00649  *  an XML hierarchy.
00650  *
00651  *  @param pParent
00652  *            The DOMElement to start the search from.
00653  *
00654  *  @param pName
00655  *            The full path of the attribute from the specified parent, with 
00656  *            element parentage specified with '/'. For example, the following
00657  *            code will extract the attribute called "baz" from the element
00658  *            called "bar", which is a child of the element called "foo" which
00659  *            is a child of pParent.
00660  *  @code
00661  *  string s = findAttribute(pParent, "foo/bar/baz");
00662  *  @endcode
00663  *
00664  *  @return The found attribute, or an empty string if the attribute is not
00665  *             found.
00666  */
00667 std::string findAttribute(XERCES_CPP_NAMESPACE_QUALIFIER DOMNode* pParent, const char* pName);
00668 
00669 /**
00670  *  This method reads a font that was written using XMLWriter::addFontElement.
00671  *
00672  *  @param pName
00673  *            The name the font was written out with.
00674  *
00675  *  @param pParent
00676  *            The DOMElement the data was written to.
00677  *
00678  *  @param font
00679  *            A font to read the data into.
00680  *
00681  *  @return The DOMElement the data was read from or \c NULL if the element was
00682  *            not found.
00683  */
00684 XERCES_CPP_NAMESPACE_QUALIFIER DOMElement* readFontElement(const char* pName,
00685    XERCES_CPP_NAMESPACE_QUALIFIER DOMElement* pParent, Font& font);
00686 
00687 /**
00688  * \cond INTERNAL
00689  *  This method is used by readContainerElements and is not intended to be used
00690  *  by developer code.
00691  */
00692 template <class T>
00693 void extractContainerElementValue(std::stringstream& str, T& iter)
00694 {
00695    str >> *iter;
00696 }
00697 
00698 /**
00699  *  This method is used by readContainerElements and is not intended to be used
00700  *  by developer code.
00701  */
00702 template <class Container>
00703 void extractContainerElementValue(std::stringstream& str, std::back_insert_iterator<Container>& iter)
00704 {
00705    typename Container::value_type value;
00706    str >> value;
00707    *iter = value;
00708 }
00709 
00710 /**
00711  *  This method reads data from an XML data stream into a container.
00712  *
00713  *  This method reads data that was written using XML_ADD_CONTAINER. The data
00714  *  can be read into a fixed-size array, a pre-allocated STL container of the
00715  *  desired size, or appended onto an existing STL container via push_backs.
00716  *
00717  *  @param pParent
00718  *            The DOMElement the data was written to.
00719  *
00720  *  @param pName
00721  *            The name of each node to write. This will be the name provided to
00722  *            XML_ADD_CONTAINER.
00723  *
00724  *  @param startIter
00725  *            The location to begin placing data.
00726  *  @code
00727  *  vector<int> v(12, 65); // creates a vector<int> with 12 65's in it
00728  *  XMLWriter writer("MyRootNode");
00729  *  XML_ADD_CONTAINER(writer, int, v.begin(), v.end());
00730  *  ...
00731  *  XmlReader reader(NULL, false);
00732  *  DOMDocument* pDoc = reader.parse(file);
00733  *  DOMElement* pRoot = pDoc->getDocumentElement();
00734  *  int intArray[12];
00735  *  vector<int> v(12, 0);
00736  *  list<int> l;
00737  *  readContainerElements(pRoot, "int", &intArray[0], 12); // reads 12 values into the array
00738  *  readContainerElements(pRoot, "int", v.begin(), 12); // reads 12 values into the vector
00739  *  readContainerElements(pRoot, "int", back_inserter(l), 0); // pushes 12 values onto the list
00740  *  @endcode
00741  *
00742  *  @param countLimit
00743  *             The maximum number of values to read. If this is 0, all of the
00744  *             values will be read.
00745  *
00746  *  @return The number of values read into the container.
00747  */
00748 template <class T>
00749 int readContainerElements(DOMNode* pParent, const char* pName, T startIter, int countLimit = 0)
00750 {
00751    int numRead = 0;
00752    XERCES_CPP_NAMESPACE_QUALIFIER DOMNode* pChild = findChildNode(pParent, pName);
00753    if (pChild != NULL)
00754    {
00755       int i = 0;
00756       FOR_EACH_DOMNODE (pChild, pGchild)
00757       {
00758          if (XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(pGchild->getNodeName(), X("element")))
00759          {
00760             if (countLimit > 0 && i++ >= countLimit)
00761             {
00762                break;
00763             }
00764 
00765             XERCES_CPP_NAMESPACE_QUALIFIER DOMElement* pElement = 
00766                dynamic_cast<XERCES_CPP_NAMESPACE_QUALIFIER DOMElement*>(pGchild);
00767             if (pElement)
00768             {
00769                std::stringstream str(A(pElement->getAttribute(X("value"))));
00770                extractContainerElementValue(str, startIter);
00771                ++startIter;
00772                ++numRead;
00773             }
00774          }
00775       }
00776    }
00777    return numRead;
00778 }
00779 /// \endcond
00780 
00781 #endif

Software Development Kit - Opticks 4.9.0 Build 16218