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
Copyright © 2001 SL_OpenSource XML Project. All Rights Reserved