Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

XMLSerializer.cpp

Go to the documentation of this file.
00001 /* -*- C++ -*- */
00002 
00003 /*
00004  * The Apache Software License, Version 1.1
00005  *
00006  *
00007  * Copyright (c) 2002 The Apache Software Foundation.  All rights
00008  * reserved.
00009  *
00010  * Redistribution and use in source and binary forms, with or without
00011  * modification, are permitted provided that the following conditions
00012  * are met:
00013  *
00014  * 1. Redistributions of source code must retain the above copyright
00015  *    notice, this list of conditions and the following disclaimer.
00016  *
00017  * 2. Redistributions in binary form must reproduce the above copyright
00018  *    notice, this list of conditions and the following disclaimer in
00019  *    the documentation and/or other materials provided with the
00020  *    distribution.
00021  *
00022  * 3. The end-user documentation included with the redistribution,
00023  *    if any, must include the following acknowledgment:
00024  *       "This product includes software developed by the
00025  *        Apache Software Foundation (http://www.apache.org/)."
00026  *    Alternately, this acknowledgment may appear in the software itself,
00027  *    if and wherever such third-party acknowledgments normally appear.
00028  *
00029  * 4. The names "SOAP" and "Apache Software Foundation" must
00030  *    not be used to endorse or promote products derived from this
00031  *    software without prior written permission. For written
00032  *    permission, please contact apache@apache.org.
00033  *
00034  * 5. Products derived from this software may not be called "Apache",
00035  *    nor may "Apache" appear in their name, without prior written
00036  *    permission of the Apache Software Foundation.
00037  *
00038  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
00039  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00040  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00041  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
00042  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00043  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00044  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
00045  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00046  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00047  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
00048  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00049  * SUCH DAMAGE.
00050  * ====================================================================
00051  *
00052  * This software consists of voluntary contributions made by many
00053  * individuals on behalf of the Apache Software Foundation.  For more
00054  * information on the Apache Software Foundation, please see
00055  * <http://www.apache.org/>.
00056  */
00057 
00058 /*
00059  *
00060  *
00061  * @author Lilantha Darshana (lilantha@erunway.com)
00062  *
00063  */
00064 
00065 #include "Platform.hpp"
00066 #include "XMLSerializer.hpp"
00067 #include "AttList.hpp"
00068 #include "XercescConst.hpp"
00069 #include "AxisConst.hpp"
00070 #include "TypeMappingRegistry.hpp"
00071 #include <cstdio>
00072 
00073 
00074 
00075 std::ostream& operator<<(std::ostream& p_OutStr, const DOMString& p_dmNode);
00076 std::ostream& operator<<(std::ostream& p_OutStr, DOM_Node& p_dmNode);
00077 XMLFormatter& operator<< (XMLFormatter& p_xmlFmt, const DOMString& p_dmStr);
00078 
00079 XMLFormatter* Xml_Formatter=NULL;
00080 XMLCh* Encoding_Name=NULL;
00081 static int m_nIndent=-1;
00082 
00083 
00084 
00085 
00086 XMLSerializer::XMLSerializer(XmlWriter& str)
00087     : m_bStartDoc(true), m_nIndent(0), m_PrefixIndx(1), 
00088       m_xmlBuffer(&str), m_pTypeMapper(0)
00089 {
00090     try
00091     {
00092         XMLPlatformUtils::Initialize();
00093     }
00094     catch(const XMLException& ex)
00095     {
00096         char *pchMsg = XMLString::transcode(ex.getMessage());
00097         std::cerr << "Error during Xerces-c Initialization.\n"
00098                   << "  Exception message:"
00099                   << pchMsg;
00100         delete pchMsg;
00101     }
00102 }
00103 
00104 XMLSerializer::~XMLSerializer()
00105 {
00106 //  XMLPlatformUtils::Terminate();
00107 }
00108 
00109 
00110 void XMLSerializer::StartElem(ax::QName& p_qName, AttList& p_attList)
00111 {
00112     // Start writing XML document
00113     if(m_bStartDoc)
00114     {
00115         m_Doc = DOM_Document::createDocument(); 
00116         m_Doc.appendChild(m_Doc.createXMLDecl ("1.0",  "UTF-8", ""));
00117         m_CurNode = m_Doc;
00118         Append(p_qName, p_attList);
00119         m_CurNode = m_Doc.getDocumentElement();
00120         m_bStartDoc = false;
00121         return;
00122     }
00123 
00124     m_CurNode = Append(p_qName, p_attList);
00125 }
00126 
00127 
00128 DOM_Element& XMLSerializer::Append(ax::QName& p_qName, AttList& p_attList)
00129 {
00130     std::string qName = QNameToStr(p_qName);
00131     m_ChildElm = m_Doc.createElement(qName.c_str());
00132 
00133     for (int i = 0; i < p_attList.getLength(); i++) 
00134     {
00135         m_ChildElm.setAttribute(p_attList.getName(i).c_str(), 
00136                                 p_attList.getValue(i).c_str());
00137     }
00138     
00139     NsMap *CurMap = m_nsStk.Peek();
00140     if(CurMap)
00141     {
00142         NsMap::iterator mpIter;
00143         for (mpIter = CurMap->begin(); mpIter != CurMap->end(); ++mpIter) 
00144         {
00145             if(mpIter->first.empty()) continue;
00146             std::string  strQName = std::string("xmlns") + ":" + mpIter->second;
00147             m_ChildElm.setAttributeNS(ax::NS_URI_XMLNS.c_str(), strQName.c_str(),
00148                                         mpIter->first.c_str());
00149                                         
00150         }
00151         m_nsStk.Push();
00152     }
00153     
00154     m_CurNode.appendChild(m_ChildElm);
00155     return m_ChildElm;
00156 }
00157 
00158 
00159 void XMLSerializer::WriteStr(const std::string& str)
00160 {
00161     m_CurTxtElm = m_Doc.createTextNode(str.c_str());
00162     m_ChildElm.appendChild(m_CurTxtElm);
00163 }
00164 
00165 void XMLSerializer::EndElem()
00166 {
00167     m_nsStk.Pop();
00168     return;
00169 }
00170 
00171 void XMLSerializer::Serialize(ax::QName p_qName, AttList& p_attList, const char* value)
00172 {
00173     m_ChildElm = Append(p_qName, p_attList);
00174     WriteStr(std::string(value));
00175 }
00176 
00177 void XMLSerializer::RegisterPrefixForURI(const std::string& prefix, const std::string& uri)
00178 {
00179     m_nsStk.Add(uri, prefix);
00180 }
00181 
00182 std::string XMLSerializer::GetPrefixForURI(const std::string& uri)
00183 {
00184     char buf[10];
00185     sprintf(buf, "%d", m_PrefixIndx++);
00186     return GetPrefixForURI(uri, "ns" + std::string(buf));
00187 }
00188 
00189 std::string XMLSerializer::GetPrefixForURI(const std::string& uri, std::string defaultPrefix)
00190 {
00191     if (uri.empty()) 
00192         return std::string("");
00193 
00194     std::string prefix = m_nsStk.GetPrefix(uri);
00195 
00196     if (prefix.empty() && uri == ax::URI_SOAP_ENC)
00197     {
00198         prefix = ax::NSPREFIX_SOAP_ENC;
00199         RegisterPrefixForURI(prefix, uri);
00200     }
00201 
00202     if (prefix.empty()) 
00203     {
00204         prefix = defaultPrefix;
00205         RegisterPrefixForURI(prefix, uri);
00206     }
00207 
00208     return prefix; 
00209 }
00210 
00211 std::string XMLSerializer::QNameToStr(ax::QName& qName)
00212 {
00213     std::string prefix = GetPrefixForURI(qName.GetNsURI());
00214     return ((!prefix.empty())?(prefix + ":"): std::string("")) + qName.GetLocalPart();
00215 }
00216 
00217 
00218 void XMLSerializer::flush()
00219 {
00220     std::ostream p_OutStr(m_xmlBuffer->rdbuf());
00221     SOAPEnvelopFormatter* fmtTarget = new SOAPEnvelopFormatter(p_OutStr);
00222 
00223     DOMString xmlEncCharset("UTF-8");
00224     DOM_Node dmNode = m_Doc.getFirstChild();
00225 
00226     // Check whether this is a declaration Node 
00227     if (dmNode.getNodeType() == DOM_Node::XML_DECL_NODE)
00228     {
00229         DOMString strTmp = ((DOM_XMLDecl &)dmNode).getEncoding();
00230         if (strTmp != "")
00231         {
00232             xmlEncCharset = strTmp;
00233         }
00234     }
00235 
00236     unsigned int lent = xmlEncCharset.length();
00237     Encoding_Name     = new XMLCh[lent + 1];
00238 
00239     XMLString::copyNString(Encoding_Name, xmlEncCharset.rawBuffer(), lent);
00240     Encoding_Name[lent] = 0;
00241 
00242     try
00243     {
00244         Xml_Formatter = new XMLFormatter(Encoding_Name, fmtTarget, XMLFormatter::NoEscapes, 
00245                                          XMLFormatter::UnRep_CharRef);
00246         p_OutStr << m_Doc;
00247         *Xml_Formatter << chLF; // add linefeed in requested output encoding
00248     }
00249     catch (XMLException& e)
00250     {
00251         std::cerr << "An error occurred during creation of output transcoder. Msg is:"
00252                   << DOMString(e.getMessage()) << std::endl;
00253     }
00254 
00255     delete fmtTarget;
00256     delete Xml_Formatter;
00257 }
00258 
00259 
00260 
00261 std::ostream& operator<<(std::ostream& p_OutStr, DOM_Node& p_dmNode)
00262 {
00263     // Get the name and value out for convenience
00264     DOMString   nodeName  = p_dmNode.getNodeName();
00265     DOMString   nodeValue = p_dmNode.getNodeValue();
00266     unsigned long lent = nodeValue.length();
00267 
00268     switch (p_dmNode.getNodeType())
00269     {
00270         case DOM_Node::TEXT_NODE:
00271         {
00272             Xml_Formatter->formatBuf(nodeValue.rawBuffer(), lent, XMLFormatter::CharEscapes);
00273             break;
00274         }
00275 
00276         case DOM_Node::PROCESSING_INSTRUCTION_NODE :
00277         {
00278             *Xml_Formatter << XMLFormatter::NoEscapes << gStartPI  << nodeName;
00279 
00280             if (lent > 0) 
00281                 *Xml_Formatter << chSpace << nodeValue;
00282 
00283             *Xml_Formatter << XMLFormatter::NoEscapes << gEndPI;
00284             break;
00285         }
00286 
00287         case DOM_Node::DOCUMENT_NODE :
00288         {
00289             DOM_Node childNode = p_dmNode.getFirstChild();
00290 
00291             while( childNode != 0)
00292             {
00293                 p_OutStr << childNode;
00294                 *Xml_Formatter << chLF; // add linefeed in requested output encoding
00295                 p_OutStr << std::flush;
00296                 childNode = childNode.getNextSibling();
00297             }
00298             break;
00299         }
00300 
00301         case DOM_Node::ELEMENT_NODE :
00302         {
00303             // The name has to be representable without any escapes
00304             m_nIndent++;    // make pretty
00305             std::string strTmp;
00306 
00307             if(m_nIndent > 0)
00308                 strTmp = std::string(m_nIndent, ' ');
00309         
00310             // Output the element start tag.
00311             *Xml_Formatter  << XMLFormatter::NoEscapes
00312                          << strTmp.c_str() << chOpenAngle << nodeName;
00313 
00314             // Output any attributes on this element
00315             DOM_NamedNodeMap mapAttribs = p_dmNode.getAttributes();
00316             int nAttCnt = mapAttribs.getLength();
00317 
00318             for (int i = 0; i < nAttCnt; i++)
00319             {
00320                 DOM_Node  dnAttr = mapAttribs.item(i);
00321 
00322                 //  Again the name has to be completely representable. But the
00323                 //  dnAttr can have refs and requires the dnAttr style
00324                 //  escaping.
00325                 *Xml_Formatter   << XMLFormatter::NoEscapes
00326                                  << chSpace << dnAttr.getNodeName()
00327                                  << chEqual << chDoubleQuote
00328                                  << XMLFormatter::AttrEscapes
00329                                  << dnAttr.getNodeValue()
00330                                  << XMLFormatter::NoEscapes
00331                                  << chDoubleQuote;
00332             }
00333 
00334             //  Test for the presence of children, which includes both
00335             //  text content and nested elements.
00336             DOM_Node childNode = p_dmNode.getFirstChild();
00337 
00338             if (childNode != 0)
00339             {
00340                 // There are children. Close start-tag, and output children.
00341                 // No escapes are legal here
00342                 bool bTxtChild=false;
00343 
00344                 *Xml_Formatter << XMLFormatter::NoEscapes << chCloseAngle;
00345 
00346                 //make pretty
00347                 if(childNode.getNodeType() != DOM_Node::TEXT_NODE)
00348                     *Xml_Formatter << "\n";
00349 
00350                 while( childNode != 0)
00351                 {
00352                     if(childNode.getNodeType() == DOM_Node::TEXT_NODE)
00353                         bTxtChild = true;
00354 
00355                     p_OutStr << childNode;
00356                     childNode = childNode.getNextSibling();
00357                 }
00358 
00359                 // Done with children.  Output the end tag.
00360                 if(!bTxtChild && (m_nIndent > 0))
00361                     strTmp = std::string(m_nIndent, ' ');       //make pretty
00362                 else
00363                     strTmp = "";
00364             
00365                 *Xml_Formatter << strTmp.c_str() << XMLFormatter::NoEscapes << gEndElement
00366                             << nodeName << chCloseAngle << "\n";
00367                 m_nIndent--;
00368             }
00369             else
00370             {
00371                 //  There were no children. Output the short form close of
00372                 //  the element start tag, making it an empty-element tag.
00373                 *Xml_Formatter << XMLFormatter::NoEscapes << chForwardSlash << chCloseAngle << "\n";
00374             }
00375             break;
00376         }
00377 
00378 
00379         case DOM_Node::ENTITY_REFERENCE_NODE:
00380         {
00381             DOM_Node childNode;
00382 
00383                *Xml_Formatter << XMLFormatter::NoEscapes << chAmpersand
00384                     << nodeName << chSemiColon;
00385             break;
00386         }
00387 
00388 
00389         case DOM_Node::CDATA_SECTION_NODE:
00390         {
00391             *Xml_Formatter << XMLFormatter::NoEscapes << gStartCDATA
00392                         << nodeValue << gEndCDATA;
00393             break;
00394         }
00395 
00396         case DOM_Node::XML_DECL_NODE:
00397         {
00398             DOMString  str;
00399 
00400             *Xml_Formatter << gXMLDecl1 << ((DOM_XMLDecl &)p_dmNode).getVersion();
00401 
00402             *Xml_Formatter << gXMLDecl2 << Encoding_Name;
00403 
00404             str = ((DOM_XMLDecl &)p_dmNode).getStandalone();
00405             if (str != 0)
00406                 *Xml_Formatter << gXMLDecl3 << str;
00407 
00408             *Xml_Formatter << gXMLDecl4;
00409 
00410             break;
00411         }
00412 
00413         default:
00414             std::cerr << "Unrecognized node type for SOAP envelop = "
00415                 << (long)p_dmNode.getNodeType() << std::endl;
00416     }
00417     return p_OutStr;
00418 }
00419 
00420 std::ostream& operator<< (std::ostream& p_OutStr, const DOMString& p_dmStr)
00421 {
00422     char *p = p_dmStr.transcode();
00423     p_OutStr << p;
00424     delete [] p;
00425     return p_OutStr;
00426 }
00427 
00428 
00429 XMLFormatter& operator<< (XMLFormatter& p_xmlFmt, const DOMString& p_dmStr)
00430 {
00431     unsigned int lent = p_dmStr.length();
00432 
00433     if (lent <= 0)
00434         return p_xmlFmt;
00435 
00436     XMLCh*  buf = new XMLCh[lent + 1];
00437     XMLString::copyNString(buf, p_dmStr.rawBuffer(), lent);
00438     buf[lent] = 0;
00439     p_xmlFmt << buf;
00440     delete [] buf;
00441     return p_xmlFmt;
00442 }
00443 
00444 
00445 
00446 
00447 
00448 
00449 
00450         
Axis C++ Client Lib - User's Guide

Copyright © 2001 SL_OpenSource XML Project. All Rights Reserved