In the epp_eppXMLbase.cc in function createDOMDocument it calls
parseString function from domtools::XercesParser. In the dom_wrapper.c I
print the string before it is passed to the xerces-c parser in
domtools::XercesParser::parseMemory function and my value in utf-8 looks
fine. When it gets back from xerces-c a DOM_document, it uses XercesNode
object(defined in dom_wrapper.h) to store the DOM_document and break it
into nodes. Then in epp_eppXMLbase.cc, in function
eppobject::epp::addExtensionElements(EPP_output & outputobject, const
epp_extension_ref_seq_ref & extensions)

it calls
DomPrint dp(outputobject);
dp.putDOMTree(extensionDoc);

from dom_print.cc where I actually print the value in putDOMTree
function. Here the value looks truncated.
The entire source code of domtools is available on
http://sourceforge.net/project/showfiles.php?group_id=26675

Thank you very much for your help.

On Wed, 2008-09-17 at 08:19 +0200, Alberto Massari wrote:
> Anna Simbirtsev wrote:
> > I pass just plain xml string to the DOMParser, so I don't use the
> > transcode function.
> >
> > [...]
> > I just copy utf-8 strings from wikipedia.org and paste it right
> > into the code to test. After I compiled the parser with ICU, it returns
> > the string, but shorter. My xml has UTF-8 encoding set: <?xml
> > version='1.0' encoding='UTF-8'?>.
> >   
> 
> If you just used cut & paste from your browser to your C++ code editor, 
> I can bet you are not pasting UTF-8 codepoints, but something in your 
> local code page. Can you attach your source code to this e-mail 
> (attached, not copied)?
> 
> Alberto
/************************************************************************
 * EPP RTK C++
 * Copyright (C) 2001, 2002 The Global Name Registry, Limited 
 * 
 * This library is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Contact information:  [EMAIL PROTECTED]
 *
 *                       EPP RTK
 *                       The Global Name Registry, Limited
 *                       125 High Holborn
 *                       London WC1V 6QA
 *                       United Kingdom
 ************************************************************************/

/* $Header: /cvsroot/epp-rtk/epp-rtk/c++/src/data/epp_eppXMLbase.cc,v 1.29 2005/09/21 13:32:55 jamesfgould Exp $ */

/** @file epp_eppXMLbase.cc
 *  @brief Definition of XML helper-functions for general use
 *  @author Asbjorn Steira Mikkelsen
 *  @see epp_eppXMLbase.h
 */

#include <map>
#include <domtools/dom_print.h>
#include "epp_eppXMLbase.h"
#include "../epp_Session.h"
#include "epp_XMLException.h"
#include "epp_Exception.h"
#include <xercesc/util/PlatformUtils.hpp> // <FIXME>Depencency on Xerces...</fixme>

using namespace std;
using namespace eppobject::epp;
using namespace domtools;


void eppobject::epp::createStandardXMLHeader(EPP_output & outputobject)
{
   outputobject.beginTag("epp");
   outputobject.putAttribute("xmlns","urn:ietf:params:xml:ns:epp-1.0");
   outputobject.putAttribute("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance";);
   outputobject.putAttribute("xsi:schemaLocation","urn:ietf:params:xml:ns:epp-1.0 epp-1.0.xsd");
}


void eppobject::epp::createStandardXMLFooter(EPP_output & outputobject)
{
   outputobject.endTag("epp");
}


void eppobject::epp::addExtensionElement(EPP_output & outputobject, const epp_Extension_ref & extension)
{ 
   if(extension == NULL) {
      return;
   }
   
   epp_string extensionXML = extension->toXML();
   
   if(extensionXML.empty()) {
      outputobject.putTag("extension", "");
   }
   else if(extensionXML.find("<") == string::npos) {
      outputobject.putTag("extension", extensionXML);
   }
   else {
      dom_ptr extensionDoc = createDOMDocument("<parseme xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\";><extension>"
					       + extensionXML +
					       "</extension></parseme>");
      
      if(!extensionDoc->isNull()) {
	 extensionDoc = dom_ptr(extensionDoc->getFirstChildElement());
	 
	 if(extensionDoc->getNodeName() == "parseme") {
	    extensionDoc = dom_ptr(extensionDoc->getFirstChildElement());
	 }
	 else {
	    return;
	 }
      }
      else {
	 return;
      }
      
      DomPrint dp(outputobject);
      dp.putDOMTree(extensionDoc);
   }
}

void eppobject::epp::addExtensionElements(EPP_output & outputobject, const epp_extension_ref_seq_ref & extensions)
{ 
#ifdef RTK_DEBUG
   cout << "Entered epp_eppXMLBase::addExtensionElements()"<<endl;
#endif

   if( extensions == NULL || extensions->empty() ) {
#ifdef RTK_DEBUG
      cout << "addExtensionElements(): No extensions to add!"<<endl;
#endif
      return;
   }
#ifdef RTK_DEBUG
   else {
      cout << "addExtensionElements(): The extensions reference vector reference is not null"<<endl;
   }
#endif   

   outputobject.beginTag("extension");
   
   for(epp_extension_ref_seq::iterator extension = extensions->begin();
       extension != extensions->end(); extension++)
     {

        if ( *extension == NULL ) {
#ifdef RTK_DEBUG
            cout << "addExtensionElements(): a null extension"<<endl;
#endif
            break;
        }      
        epp_string extensionXML = (*extension)->toXML();
#ifdef RTK_DEBUG
        cout << "addExtensionElements(): extension returned us this xml ["<<extensionXML<<"]"<<endl;
#endif

        dom_ptr extensionDoc = createDOMDocument("<parseme xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\";>"
					         + extensionXML +
					         "</parseme>");

        if(!extensionDoc->isNull()) {
	   extensionDoc = dom_ptr(extensionDoc->getFirstChildElement());

	   if(extensionDoc->getNodeName() == "parseme") {
	      extensionDoc = dom_ptr(extensionDoc->getFirstChildElement());
	   }
	   else {
#ifdef RTK_DEBUG
              cout << "addExtensionElements(): no parseme element???"<<endl;
#endif
	      break;
	   }
        }
        else {
#ifdef RTK_DEBUG
           cout << "addExtensionElements(): couldn't transform xml string back to dom element tree"<<endl;
#endif
	   break;
        }

        DomPrint dp(outputobject);
        dp.putDOMTree(extensionDoc);
     }

   outputobject.endTag("extension");

}

/*
void eppobject::epp::addCredsElement(EPP_output & outputobject, const epp_Credentials_ref & credspart)
{
   if(credspart == NULL) {
      return;
   }
   
   outputobject.beginTag("creds");
   
   if(credspart->m_client_id != NULL) {
      outputobject.putTag("clID", *credspart->m_client_id);
   } // if "m_client_id"
   
   if(credspart->m_password != NULL) {
      outputobject.putTag("pw", *credspart->m_password);
   } // if "m_password"
   
   if(credspart->m_new_password != NULL) {
      outputobject.putTag("newPW", *credspart->m_new_password);
   } // if "m_new_password"
   
   if(credspart->m_options != NULL) {
      outputobject.beginTag("options");
      
      if(credspart->m_options->m_version != NULL) {
	 outputobject.putTag("version", *credspart->m_options->m_version);
      }
      if(credspart->m_options->m_lang != NULL) {
	 outputobject.putTag("lang", *credspart->m_options->m_lang);
      }
      outputobject.endTag("options");
   } // if "m_options"
   
   outputobject.endTag("creds");
}
*/

void eppobject::epp::addAuthInfoElement(EPP_output & outputobject, const epp_AuthInfo_ref & element, const epp_string & tag)
{
   if(element == NULL) {
      return;
   }
   
   outputobject.beginTag(tag);
   
   if(element->m_roid != NULL) {
      outputobject.putAttribute("roid", *element->m_roid);
   }
   
   if(element->m_value != NULL) {
      
      if(element->m_type != NULL) {
         map<epp_AuthInfoType, string> authInfoMap;
         authInfoMap[PW] = "pw";
         authInfoMap[EXT] = "ext";

         // FIXME -- ugly hack to get the namespace from the wrapping tag
         unsigned int namespace_location = tag.find(":");
         string namespace_str = tag.substr(0, namespace_location+1); // include the ":"
         outputobject.putTag(namespace_str + authInfoMap[*element->m_type],*element->m_value);
      }

   }
   
   outputobject.endTag(tag);
}


epp_AuthInfo_ref eppobject::epp::createAuthInfoObject(const domtools::dom_ptr & authNode)
{
   epp_AuthInfo_ref authObj(new epp_AuthInfo());
   
   if(!authNode->isNull()) {

      dom_ptr authChild = dom_ptr(authNode->getFirstChildElement());

      string roid = authNode->getAttribute("roid");
      if(!roid.empty()) {
	 authObj->m_roid.ref(new epp_roid(roid));
      }
      
      if ( ! authChild->isNull() ) {

         string authChildName = authChild->getNodeName();

         unsigned int colonLocation = authChildName.find(":");
         string type = authChildName;
         if ( colonLocation != string::npos ) {
            type = authChildName.substr(colonLocation+1);
         }
         if(!type.empty()) {
            authObj->m_type.ref(new epp_AuthInfoType(returnAuthInfoType(type)));
         }

         string value = authChild->getNodeData();
         if(!value.empty()) {
	    authObj->m_value.ref(new epp_string(value));
         }
      }
      
//      cout << "authinfo: " << type << ", " << roid << ", " << value <<  endl;
   }
   
   return authObj;   
}


epp_string eppobject::epp::returnTransferType(const epp_TransferOpType & statusType)
{
   map<epp_TransferOpType, epp_string> transferTypeMap;
   
   transferTypeMap[APPROVE] = "approve";
   transferTypeMap[CANCEL] = "cancel";
   transferTypeMap[QUERY] = "query";
   transferTypeMap[REJECT] = "reject";
   transferTypeMap[REQUEST] = "request";
   
   if(transferTypeMap.find(statusType) == transferTypeMap.end()) {
      throw epp_XMLException(__FILE__, __LINE__, "Unknown TransferOpType");
   }
   
   return transferTypeMap[statusType];
}

epp_TransferOpType eppobject::epp::returnTransferType(const epp_string & statusType)
{
   map<epp_string, epp_TransferOpType> transferTypeMap;
   
   transferTypeMap["approve"] = APPROVE;
   transferTypeMap["cancel"] = CANCEL;
   transferTypeMap["query"] = QUERY;
   transferTypeMap["reject"] = REJECT;
   transferTypeMap["request"] = REQUEST;
   
   if(transferTypeMap.find(statusType) == transferTypeMap.end()) {
      throw epp_XMLException(__FILE__, __LINE__, "Unknown TransferOpType");
   }
   
   return transferTypeMap[statusType];
}

epp_string eppobject::epp::returnTransferStatusType(const epp_TransferStatusType & statusType)
{
   map<epp_TransferStatusType, epp_string> transferTypeMap;
   
   transferTypeMap[CLIENT_APPROVED] = "clientApproved";
   transferTypeMap[CLIENT_CANCELLED] = "clientCancelled";
   transferTypeMap[CLIENT_REJECTED] = "clientRejected";
   transferTypeMap[PENDING] = "pending";
   transferTypeMap[SERVER_APPROVED] = "serverApproved";
   transferTypeMap[SERVER_CANCELLED] = "serverCancelled";
   
   if(transferTypeMap.find(statusType) == transferTypeMap.end()) {
      throw epp_XMLException(__FILE__, __LINE__, "Unknown TransferStatusType");
   }
   
   return transferTypeMap[statusType];
   
}

epp_TransferStatusType eppobject::epp::returnTransferStatusType(const epp_string & statusType)
{
   map<epp_string, epp_TransferStatusType> transferTypeMap;
   
   transferTypeMap["clientApproved"] = CLIENT_APPROVED;
   transferTypeMap["clientCancelled"] = CLIENT_CANCELLED;
   transferTypeMap["clientRejected"] = CLIENT_REJECTED;
   transferTypeMap["pending"] = PENDING;
   transferTypeMap["serverApproved"] = SERVER_APPROVED;
   transferTypeMap["serverCancelled"] = SERVER_CANCELLED;

   if(transferTypeMap.find(statusType) == transferTypeMap.end()) {
      throw epp_XMLException(__FILE__, __LINE__, "Unknown TransferStatusType");
   }
   
   return transferTypeMap[statusType];
}


epp_AuthInfoType eppobject::epp::returnAuthInfoType(const epp_string & infoType)
{
   map<epp_string, epp_AuthInfoType> authInfoMap;
   
   authInfoMap["pw"] = PW;
   authInfoMap["ext"] = EXT;
   
   if(authInfoMap.find(infoType) == authInfoMap.end()) {
      throw epp_XMLException(__FILE__, __LINE__, "Unknown AuthInfoType");
   }
   
   return authInfoMap[infoType];
}


domtools::dom_ptr eppobject::epp::createDOMDocument(const epp_string & xml)
{
#ifdef RTK_DEBUG
   cout << "<Returned_XML>\n";
   cout << xml << endl;
   cout << "\n</Returned_XML>\n";
#endif

   //<FIXME>This try/catch statement is Xerces-specific...</fixme>  
   // Initialize parser:
   try {
      XMLPlatformUtils::Initialize();
   } catch(...) {
      throw epp_XMLException(__FILE__, __LINE__, "Unable to initialise XML-parser");
   }
   
   domtools::xml_string_output out;
   domtools::XercesParser p;  // <FIXME>Xerces-specific</fixme>

   dom_ptr treeNode;
   try {
      treeNode = dom_ptr(p.parseString(xml));
   }
   catch (...) {
      throw epp_XMLException(__FILE__, __LINE__, "Unable to parse string");
   }
   
//   XMLPlatformUtils::Terminate(); //<FIXME>Why crash with this line?</fixme>
   return treeNode;
}


epp_Response_ref eppobject::epp::createGenericResponse(const domtools::dom_ptr & node)
{
   epp_Response_ref res(new epp_Response);
   
   dom_ptr resChildNode = dom_ptr(node->getFirstChildElement());

   while(!resChildNode->isNull()) {
      string nodeName = resChildNode->getNodeName();
      
      if(nodeName == "extension") {
	 
         // a single extension tag is permitted, but
         // it can contain multiple children.
         res->m_ext_strings.ref(new epp_xml_string_seq());
         
         dom_ptr extensionNode = dom_ptr(resChildNode->getFirstChild());
	 
	 while(!extensionNode->isNull()) {
	    EPP_output outObject;
	    DomPrint dp(outObject);
	    dp.putDOMTree(extensionNode);
	    extensionNode = dom_ptr(extensionNode->getNextSibling());

            epp_xml_string xml_string(outObject.getString());

	    res->m_ext_strings->push_back(xml_string);
	 }

//	 cout << "extension: " << *res->m_ext_strings << endl;
      } // if "extension"
      
      else if(nodeName == "trID") {
	 res->m_trans_id.ref(new epp_TransID());
	 
	 dom_ptr trIDChildNode = dom_ptr(resChildNode->getFirstChildElement());
	 
	 while(!trIDChildNode->isNull()) {
	    string trIDNodeName = trIDChildNode->getNodeName();
	    
	    if(trIDNodeName == "svTRID") {
	       res->m_trans_id->m_server_trid.ref(new epp_trid(trIDChildNode->getNodeData()));
//	       cout << "svTRID: " << *res->m_trans_id->m_server_trid << endl;
	    }
	    else if(trIDNodeName == "clTRID") {
	       res->m_trans_id->m_client_trid.ref(new epp_trid(trIDChildNode->getNodeData()));
//	       cout << "clTRID: " << *res->m_trans_id->m_client_trid << endl;
	    }
	    
	    trIDChildNode = dom_ptr(trIDChildNode->getNextSiblingElement());
	 } // while "trIDChildNode"
      } // if "trID"
      
      else if(nodeName == "msgQ") {
	 res->m_message_queue.ref(new epp_MessageQueue());
	 
	 string count = resChildNode->getAttribute("count");
	 res->m_message_queue->m_count.ref(new epp_long(atol(count.c_str())));
//	 cout << "msgQ, count: " << count << endl;
	 
	 string id = resChildNode->getAttribute("id");
	 if(!id.empty()) {
	    res->m_message_queue->m_id.ref(new epp_string(id));
//	    cout << "id: " << *res->m_message_queue->m_id << endl;
	 }

	 dom_ptr msgqChildNode = dom_ptr(resChildNode->getFirstChildElement());

	 while( ! msgqChildNode->isNull() ) {
	    string msgqNodeName = msgqChildNode->getNodeName();

	    if ( msgqNodeName == "msg" ) {
	       res->m_message_queue->m_msg.ref(new epp_ExtMessage());
//	       cout << "msg: " << *result.m_msg << endl;
	       
               res->m_message_queue->m_msg->m_value.ref(new epp_string(msgqChildNode->getNodeData()));
               
	       string lang = msgqChildNode->getAttribute("lang");
	       if ( ! lang.empty() ) {
	          res->m_message_queue->m_msg->m_lang.ref(new epp_string(lang));
//	          cout << "lang: " << *result.m_lang << endl;
	       }
            }
	       
	    if( msgqNodeName == "qDate" ) {
	       res->m_message_queue->m_queue_date.ref(new epp_datetime(msgqChildNode->getNodeData()));
//	       cout << "msgQ, qDate: " << qDate << endl;
	    }

	    msgqChildNode = dom_ptr(msgqChildNode->getNextSiblingElement());
         }

      } // if "msqQ"
      
      else if(nodeName == "result") {
	 
	 if(res->m_results == NULL) {
	    res->m_results.ref(new epp_result_seq);
	 }
	 
	 epp_Result result;
	 
	 string code = resChildNode->getAttribute("code");
	 
	 if(code.empty()) {
	    throw epp_XMLException(__FILE__, __LINE__, "Missing code-attribute in result-element");
	 }
	 
	 result.m_code.ref(new epp_short(atol(code.c_str())));
//	 cout << "code: " << *result.m_code << endl;
	 
	 dom_ptr resultChildNode = dom_ptr(resChildNode->getFirstChildElement());
	 
	 while(!resultChildNode->isNull()) {
	    string resNodeName = resultChildNode->getNodeName();
	    
	    if(resNodeName == "msg") {
	       result.m_msg.ref(new epp_string(resultChildNode->getNodeData()));
//	       cout << "msg: " << *result.m_msg << endl;
	       
	       string lang = resultChildNode->getAttribute("lang");
	       if(!lang.empty()) {
		  result.m_lang.ref(new epp_string(lang));
//		  cout << "lang: " << *result.m_lang << endl;
	       }
	       
	    } // if "msg"
	    
	    else if(resNodeName == "value") {
	       if(result.m_values == NULL) {
		  result.m_values.ref(new epp_resultvalue_seq);
	       }
	       
               epp_ResultValue resvalue;
               EPP_output value_xml;
               DomPrint dp(value_xml);
               dp.putDOMTree(dom_ptr(resultChildNode->getFirstChildElement()));
               string xml_string = value_xml.getString();
               string::size_type lastNotWhite = xml_string.find_last_not_of(" \t\r\n");
               if(lastNotWhite != (xml_string.length()-1) && lastNotWhite != 0) {
                  xml_string.erase(lastNotWhite+1, xml_string.length());
               }
               resvalue.m_xml_string.ref(new epp_string(xml_string));
               dom_ptr value_child = dom_ptr(resultChildNode->getFirstChildElement());
               if ( ! value_child->isNull() ) {
                  resvalue.m_namespace.ref(new epp_string(value_child->getNamespaceURI()));
                  resvalue.m_element_name.ref(new epp_string(value_child->getNodeName()));
                  resvalue.m_element_value.ref(new epp_string(value_child->getNodeData()));
               }
               
	       result.m_values->push_back(resvalue);
	    } // if "value"
	    
            // DANDAN
            // FIXME -- have to parse the extValue elements
            
	    resultChildNode = dom_ptr(resultChildNode->getNextSiblingElement());
	 } // while "resultChildNode"

	 res->m_results->push_back(result);
	 
      } // if "result"
      
      resChildNode = dom_ptr(resChildNode->getNextSiblingElement());
   } // while "resChildNode"
   
   
   // Throw exception if there is an error-condition...
   if(res->m_results != NULL && *((res->m_results->front()).m_code) >= epp_Session::EPP_UNKNOWN_COMMAND) {
      epp_Exception throwMe = epp_Exception(res->m_results, res->m_trans_id, res->m_ext_strings);
      throw throwMe;
   }
   
   return res;
}


epp_Greeting_ref eppobject::epp::createGreetingResponse(const domtools::dom_ptr & node)
{
   epp_Greeting_ref gr(new epp_Greeting());
   
   if(node->isNull()) {
      throw epp_XMLException(__FILE__, __LINE__, "Empty Greeting-element");
   }
   
   dom_ptr mainChildNode = dom_ptr(node->getFirstChildElement());
   
   while(!mainChildNode->isNull()) {
      string nodeName = mainChildNode->getNodeName();
      
      if(nodeName == "svID") {
	 gr->m_server_id.ref(new epp_string(mainChildNode->getNodeData()));
//	 cout << "svID: " << *gr->m_server_id << endl;
      } // if "svID"
      
      else if(nodeName == "svDate") {
	 gr->m_server_date.ref(new epp_datetime(mainChildNode->getNodeData()));
//	 cout << "svDate: " << *gr->m_server_date << endl;
      } // if "svDate"
      
      else if(nodeName == "svcMenu") {
	 gr->m_svc_menu.ref(new epp_ServiceMenu());
	 
	 dom_ptr elNode = dom_ptr(mainChildNode->getFirstChildElement());
	 
	 while(!elNode->isNull()) {
	    string serNodeName = elNode->getNodeName();
	    
	    if(serNodeName == "version") {
	       if(gr->m_svc_menu->m_versions == NULL) {
		  gr->m_svc_menu->m_versions.ref(new epp_string_seq);
	       }
	       
	       gr->m_svc_menu->m_versions->push_back(epp_string(elNode->getNodeData()));
//	       cout << "version: " << elNode->getNodeData() << endl;
	    } // if "version"
	    
	    else if(serNodeName == "lang") {
	       if(gr->m_svc_menu->m_langs == NULL) {
		  gr->m_svc_menu->m_langs.ref(new epp_string_seq);
	       }
	       
	       gr->m_svc_menu->m_langs->push_back(epp_string(elNode->getNodeData()));
//	       cout << "lang: " << elNode->getNodeData() << endl;
	    } // if "lang"
	    
	    else if(serNodeName == "objURI") {
	       if(gr->m_svc_menu->m_services == NULL) {
		  gr->m_svc_menu->m_services.ref(new epp_objuri_seq);
	       }
	       
	       gr->m_svc_menu->m_services->push_back(epp_string(elNode->getNodeData()));
//	       cout << "service:" << elNode->getNodeData() << "\n";		
	    } // if "objURI"
	    
	    else if(serNodeName == "svcExtension") {
	       gr->m_svc_menu->m_extensions.ref(new epp_exturi_seq);
	       
	       dom_ptr serviceNode = dom_ptr(elNode->getFirstChildElement());
	       
	       while(!serviceNode->isNull()) {
		  if(serviceNode->getNodeName() == "extURI") {
		     gr->m_svc_menu->m_extensions->push_back(epp_string(serviceNode->getNodeData()));
//		     cout << "extension:" <<  serviceNode->getNodeData()<< "\n";
		  }
		  serviceNode = dom_ptr(serviceNode->getNextSiblingElement());
	       } // while "serviceNode"
	       
	    }  // if "svcExtension"
	    
	    elNode = dom_ptr(elNode->getNextSiblingElement());
	 } // while "elNode"
	 
      } // if "svcMenu"
      
      else if(nodeName == "dcp") {
	 gr->m_dcp = createDCPObject(mainChildNode);
      } // if "dcp"
      
      mainChildNode = dom_ptr(mainChildNode->getNextSiblingElement());
   } // while "mainChildNode"
   
   return gr;
}


domtools::dom_ptr eppobject::epp::getresDataInfo(const domtools::dom_ptr & responseNode, const string & tag)
{
   if(responseNode->isNull()) {
      throw epp_XMLException(__FILE__, __LINE__, "Unable to find response-element");
   }
   
   dom_ptr resDataNode = dom_ptr(responseNode->getTag("resData"));
   
   if(resDataNode->isNull()) {
      throw epp_XMLException(__FILE__, __LINE__, "Unable to find resData-element");
   }
   
   dom_ptr resChildNode = dom_ptr(resDataNode->getFirstChildElement());
   
   if(resChildNode->isNull()) {
      throw epp_XMLException(__FILE__, __LINE__, "Empty resData-element");
   }
   
   while(!resChildNode->isNull()) {
      if(resChildNode->getNodeName().find(":" + tag) != string::npos) {
	 return resChildNode;
      }
      
      resChildNode = dom_ptr(resChildNode->getNextSiblingElement());
   } // while "resChildNode"
   
   // Return empty element if it does not find the tag
   return dom_ptr();
}


epp_Service_ref eppobject::epp::createServiceObject(const domtools::dom_ptr & node)
{
   epp_Service_ref eService(new epp_Service());
   
   eService->m_name.ref(new epp_string(node->getPrefix()));
   eService->m_xmlns.ref(new epp_string(node->getNamespaceURI()));
   string sLocation = node->getAttribute("xsi:schemaLocation");
   eService->m_schema_location.ref(new epp_string(sLocation));
   
   return eService;
}


epp_DataCollectionPolicy_ref eppobject::epp::createDCPObject(const domtools::dom_ptr & node)
{
   epp_DataCollectionPolicy_ref dcp(new epp_DataCollectionPolicy);
   
   if(node->isNull()) {
      throw epp_XMLException(__FILE__, __LINE__, "Emtpy dcp-elment in greeting");
   }
   
   dom_ptr DCPChildNode = dom_ptr(node->getFirstChildElement());
   
   while(!DCPChildNode->isNull()) {
      string nodeName = DCPChildNode->getNodeName();
      
      if(nodeName == "access") {
	 dom_ptr accessChildNode = dom_ptr(DCPChildNode->getFirstChildElement());
	 if(accessChildNode->isNull()) {
	    throw epp_XMLException(__FILE__, __LINE__, "Emtpy access-elment in greeting");
	 }
	 
	 string access = accessChildNode->getNodeName();
	 
	 if(access == "all") dcp->m_access.ref(new epp_dcpAccessType(ALL));
	 else if(access == "none") dcp->m_access.ref(new epp_dcpAccessType(NONE_ACCESS));
	 else if(access == "null") dcp->m_access.ref(new epp_dcpAccessType(NULL_ACCESS));
	 else if(access == "other") dcp->m_access.ref(new epp_dcpAccessType(OTHER));
	 else if(access == "personal") dcp->m_access.ref(new epp_dcpAccessType(PERSONAL));
	 else if(access == "personalAndOther") dcp->m_access.ref(new epp_dcpAccessType(PERSONAL_AND_OTHER));
	 else throw epp_XMLException(__FILE__, __LINE__, "Unknown access-type in greeting");
      } // if "access"
      
      else if(nodeName == "statement") {
	 if(dcp->m_statements == NULL) {
	    dcp->m_statements.ref(new epp_dcpStatement_seq());
	 }
	 
	 dom_ptr statementNode = dom_ptr(DCPChildNode->getFirstChildElement());
	 
	 epp_dcpStatement dcpS;
	 
	 while(!statementNode->isNull()) {
	    string statementName = statementNode->getNodeName();
	    
	    if(statementName == "purpose") {
	       if(dcpS.m_purposes == NULL) {
		  dcpS.m_purposes.ref(new epp_dcpPurpose_seq);
	       }
	       
	       dom_ptr purposeNode = dom_ptr(statementNode->getFirstChildElement());
	       
	       while(!purposeNode->isNull()) {
		  string purpose = purposeNode->getNodeName();
		  
		  if(purpose == "admin") dcpS.m_purposes->push_back(ADMIN_PURPOSE);
		  else if(purpose =="contact") dcpS.m_purposes->push_back(CONTACT);
		  else if(purpose =="other") dcpS.m_purposes->push_back(OTHER_PURPOSE);
		  else if(purpose =="prov") dcpS.m_purposes->push_back(PROV);
		  else throw epp_XMLException(__FILE__, __LINE__, "Unknown purpose-type in greeting");
		  
		  purposeNode = dom_ptr(purposeNode->getNextSiblingElement());
	       } // while "purposeNode"
	    } // if "purpose"
	    
	    else if(statementName == "recipient") {
	       if(dcpS.m_recipients == NULL) {
		  dcpS.m_recipients.ref(new epp_dcpRecipient_seq);
	       }
	       
	       dom_ptr recipientNode = dom_ptr(statementNode->getFirstChildElement());
	       
	       while(!recipientNode->isNull()) {
		  string recipient = recipientNode->getNodeName();
		  
                  epp_dcpRecipient dcprecip;
                  
		  if(recipient == "other") dcprecip.m_type.ref(new epp_dcpRecipientType(OTHER_RECIPIENT));
		  else if(recipient =="ours") {
                     dcprecip.m_type.ref(new epp_dcpRecipientType(OURS));
                     if ( ! recipientNode->getFirstChildElement()->isNull() ) {
                        string ours_rec_desc = recipientNode->getFirstChildElement()->getNodeData();
                        if ( ! ours_rec_desc.empty() ) dcprecip.m_rec_desc.ref(new epp_string(ours_rec_desc));
                     }
                  } else if(recipient =="public") dcprecip.m_type.ref(new epp_dcpRecipientType(PUBLIK));
		  else if(recipient =="same") dcprecip.m_type.ref(new epp_dcpRecipientType(SAME));
		  else if(recipient =="unrelated") dcprecip.m_type.ref(new epp_dcpRecipientType(UNRELATED));
		  else throw epp_XMLException(__FILE__, __LINE__, "Unknown recipient-type in greeting");
                  
                  dcpS.m_recipients->push_back(dcprecip);
                  
		  recipientNode = dom_ptr(recipientNode->getNextSiblingElement());
	       } // while "recipientNode"
	    } // if "recipient"
	    
	    else if(statementName == "retention") {

	       dom_ptr retentionNode = dom_ptr(statementNode->getFirstChildElement());
	       
	       if(!retentionNode->isNull()) {
		  
		  string retention = retentionNode->getNodeName();
		  
		  if(retention == "business") dcpS.m_retention.ref(new epp_dcpRetentionType(BUSINESS));
		  else if(retention == "indefinite") dcpS.m_retention.ref(new epp_dcpRetentionType(INDEFINITE));
		  else if(retention == "legal") dcpS.m_retention.ref(new epp_dcpRetentionType(LEGAL));
		  else if(retention == "none") dcpS.m_retention.ref(new epp_dcpRetentionType(NONE));
		  else if(retention == "stated") dcpS.m_retention.ref(new epp_dcpRetentionType(STATED));
		  else throw epp_XMLException(__FILE__, __LINE__, "Unknown retention-type in greeting");
		  
	       } // if "retentionNode"

	    } // if "retention"

	    statementNode = dom_ptr(statementNode->getNextSiblingElement());
	 } // while "statementNode"
	 
	 dcp->m_statements->push_back(dcpS);
      } // if "statement"

      else if(nodeName == "expiry") {

	 dom_ptr expiryNode = dom_ptr(DCPChildNode->getFirstChildElement());

	 if( expiryNode->isNull() ) {
	    throw epp_XMLException(__FILE__, __LINE__, "Emtpy expiry-elment in data collection policy");
	 }

	 string expiry_type = expiryNode->getNodeName();

         dcp->m_expiry.ref(new epp_dcpExpiry());
	 if(expiry_type == "absolute") dcp->m_expiry->m_type.ref(new epp_dcpExpiryType(ABSOLUTE));
	 else if(expiry_type == "relative") dcp->m_expiry->m_type.ref(new epp_dcpExpiryType(RELATIVE));
	 else throw epp_XMLException(__FILE__, __LINE__, "Unknown expiry-type in data collection policy");

         dcp->m_expiry->m_value.ref(new epp_string(expiryNode->getNodeData()));

      } // if "expiry"


      DCPChildNode = dom_ptr(DCPChildNode->getNextSiblingElement());
   } // while "DCPChildNode"
   
   return dcp;
}


   /*********************************23**********************************
    *                                                                   *
    *           Only deprecated functions below this, please...         *
    *                                                                   *
    *********************************23**********************************/

//lint -e1773
// "Info 1773: Attempt to cast away const (or volatile)"
//lint -e1746
// "Info 1746: parameter <x> in function <y> could be made const reference"
//lint -e1764
// "Info 1764: Reference parameter <x> (line <y>) could be declared const ref"

// As the functions below are deprecated, we are not concerned about
// the above lint-warnings.


// Warning: This function is deprecated, use the dom_ptr version instead!
epp_AuthInfo_ref eppobject::epp::createAuthInfoObject(DOM_Node authNode)
{
   epp_AuthInfo_ref authObj(new epp_AuthInfo());
   
   string type, roid, value;
   getAttribute(authNode, "type", type);
   getAttribute(authNode, "roid", roid);
   getNodeData(authNode, value);
   
   if(!type.empty())
     authObj->m_type.ref(new epp_AuthInfoType(returnAuthInfoType(type)));
   if(!roid.empty())
     authObj->m_roid.ref(new epp_roid(roid));
   if(!value.empty())
     authObj->m_value.ref(new epp_string(value));
//   cout << "authinfo: " << type << ", " << roid << ", " << value <<  endl;
   
   return authObj;
}



// Warning: This function is deprecated, use the dom_ptr version instead!
DOM_Document eppobject::epp::createDOM_Document(const epp_string & xml)
{
#ifdef RTK_DEBUG
   cout << "<Returned_XML>\n";
   cout << xml << endl;
   cout << "\n</Returned_XML>\n";
#endif
   
   // Initialize Xerces
   try {
      XMLPlatformUtils::Initialize();
   } catch(...) {
      throw epp_XMLException(__FILE__, __LINE__, "Unable to initialise Xerces-c");
   }
   
   domtools::xml_string_output out;
   
   DOMParser parser;
   
   MemBufInputSource * myXML = new MemBufInputSource
     (
      (const XMLByte*)xml.c_str()
      , strlen(xml.c_str())
      , "nothing"
      , false
      );
   
   parser.setDoNamespaces(true);
   parser.setToCreateXMLDeclTypeNode(true);
   
   try {
      parser.parse(*myXML);
   }
   catch (...) {
      delete myXML;
      throw epp_XMLException(__FILE__, __LINE__, "Unable to parse string");
   }
   
   DOM_Document ret = parser.getDocument();
   
   delete myXML;
   
   return ret;
}


// Warning: This function is deprecated, use the dom_ptr version instead!
DOM_Node eppobject::epp::getresDataInfo(const DOM_Node & responseNode, const string & tag)
{
   if(responseNode.isNull())
     {
	throw epp_XMLException(__FILE__, __LINE__, "Unable to find response-element");
     }
   
   DOM_Node resDataNode = ((DOM_Element*)&responseNode)->getElementsByTagName("resData").item(0);
   if(resDataNode.isNull())
     {
	throw epp_XMLException(__FILE__, __LINE__, "Unable to find resData-element");
     }
   
   DOM_NodeList elemNodes = resDataNode.getChildNodes();
   
   if(elemNodes.getLength() == 0)
     {
	throw epp_XMLException(__FILE__, __LINE__, "Empty resData-element");
     }
   
   DOM_Node elNode;
   
   for(unsigned int i = 0; i < elemNodes.getLength(); i++)
     {
	elNode = elemNodes.item(i);
	
	if(toString(elNode.getNodeName()).find(":" + tag) != string::npos)
	  return elNode;
     }
   
   // Return empty element if it does not find the tag
   return DOM_Node();
}


// Warning: This function is deprecated, use the dom_ptr version instead!
epp_Service_ref eppobject::epp::createServiceObject(DOM_Node & node)
{
   epp_Service_ref eService(new epp_Service());
   
   eService->m_name.ref(new epp_string(toString(node.getPrefix())));
   eService->m_xmlns.ref(new epp_string(toString(node.getNamespaceURI())));
   string sLocation;
   getAttribute(node, "xsi:schemaLocation", sLocation);
   eService->m_schema_location.ref(new epp_string(sLocation));
   
   return eService;
}

void eppobject::epp::addUnspecElement(EPP_output & outputobject, const epp_Unspec_ref & unspec)
{
   if(unspec == NULL)
     {
	return;
     }
   
   epp_string unspecXML = unspec->toXML();
   
   if(unspecXML.empty())
     {
	outputobject.putTag("unspec", "");
     }
   else
     {
	dom_ptr unspecDoc = createDOMDocument("<unspec>" + unspecXML + "</unspec>");
	DomPrint dp(outputobject);
	dp.putDOMTree(unspecDoc);
     }
}

//lint +e1773
//lint +e1746
//lint +e1764
/************************************************************************
* EPP RTK C++
* Copyright (C) 2001 Global Name Registry
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*
* Contact information:  [EMAIL PROTECTED]
*
*                       EPP RTK
*                       GNR Ltd.
*                       125 High Holborn
*                       London WC1V 6QA
*                       United Kingdom
************************************************************************/

#include "dom_wrapper.h"

using namespace std;

string domtools::GenericNode::getFirstChildElementData(void)
{
   dom_ptr ptr(getFirstChildElement());
   if (ptr->isNull()) return "";
   return ptr->getNodeData();
}

string domtools::GenericNode::getTagData(const string & tag)
{
   dom_ptr ptr(getTag(tag));
   if (ptr->isNull()) return "";
   return ptr->getNodeData();
}


domtools::Node * domtools::Parser::parseString(const string & str)
{
   cout << "parseString: " << str << endl;
   return parseMemory(str.c_str(),(int)str.length());
}


#ifdef HAVE_XERCES

domtools::Node * domtools::XercesNamedNodeMap::item(int pos)
{
   return new XercesNode(node.item(pos));
}
      
int domtools::XercesNamedNodeMap::getLength(void)
{
   return node.getLength();
}
      
bool domtools::XercesNode::isNull(void)
{
   return node.isNull();
}

string domtools::XercesNode::getLocalName(void)
{
   return domtools::toString(node.getLocalName());
}

unsigned short domtools::XercesNode::getNodeType(void)
{
   switch (node.getNodeType()) {
    case DOM_Node::DOCUMENT_NODE: return Node::DOCUMENT_NODE;
    case DOM_Node::ELEMENT_NODE: return Node::ELEMENT_NODE;
    case DOM_Node::XML_DECL_NODE: return Node::XML_DECL_NODE;
    case DOM_Node::PROCESSING_INSTRUCTION_NODE: return Node::PROCESSING_INSTRUCTION_NODE;
    case DOM_Node::CDATA_SECTION_NODE: return Node::CDATA_SECTION_NODE;
    case DOM_Node::TEXT_NODE: return Node::TEXT_NODE;
    case DOM_Node::ATTRIBUTE_NODE: return Node::ATTRIBUTE_NODE;
    default: DOMTOOLS_EXCEPTION("Unknown node type");
   };
}
      
domtools::Node * domtools::XercesParser::parseFile(const string & filename)
{
   ::DOMParser parser;
   parser.setDoNamespaces(true);
   parser.setToCreateXMLDeclTypeNode(false);
   try {
      parser.parse(filename.c_str());
      DOM_Document doc = parser.getDocument();
      if (doc.isNull()) return new XercesNode();
      return new XercesNode(doc);
   } catch(...) {
   }
   return new XercesNode();
}


domtools::Node * domtools::XercesParser::parseMemory(const void * const buffer, int length)
{
   ::DOMParser parser;
   parser.setDoNamespaces(true);
   parser.setToCreateXMLDeclTypeNode(false);
   MemBufInputSource* memBufIS = new MemBufInputSource
     (
      (const XMLByte*)buffer
      , length
      , "domtools"
      , false
      );
  
   try {
      parser.parse(*memBufIS);
      DOM_Document doc = parser.getDocument();
      delete memBufIS;
      if (!doc.isNull()) return new XercesNode(doc);
   } catch(...) {
      delete memBufIS;
   };
   return new XercesNode();
}


#endif
/************************************************************************
* EPP RTK C++
* Copyright (C) 2001 Global Name Registry
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*
* Contact information:  [EMAIL PROTECTED]
*
*                       EPP RTK
*                       GNR Ltd.
*                       125 High Holborn
*                       London WC1V 6QA
*                       United Kingdom
************************************************************************/

#ifndef __DOM_WRAPPER_H
#define __DOM_WRAPPER_H


// \file Encapsulates XML parser specific functionality. Supports many DOM functions, plus additional utility functions.

#include "refcount.h"
#include "dom_tools.h"
#include "dom_output.h"

#ifdef HAVE_XERCESC_PARSERS_DOMPARSER_HPP
# undef HAVE_XERCES
# define HAVE_XERCES 1
#endif

#ifdef HAVE_XERCES
# include <xercesc/framework/MemBufInputSource.hpp>
#endif


namespace domtools {

   class Node;

   /// Used for attribute maps etc.
   class NamedNodeMap {
    public:
      virtual ~NamedNodeMap(void) { }
      virtual Node * item(int pos) = 0;
      virtual int getLength(void) = 0;
   };
   
   /** A partially DOM compliant interface with additional utility functions
    * 
    *  Methods present in the DOM specifications are marked as such. 
    *  Expect these classes to deviate somewhat from the DOM even for those
    *  methods. For instance, we use standard C++ strings. 
    * 
    *  When it comes to conventions for interpreting the DOM IDLs for C++,
    *  this class mostly follows Xerces.
    */
   
   class Node {
    public:
      static const int DOCUMENT_NODE = 0;
      static const int XML_DECL_NODE = 1;
      static const int PROCESSING_INSTRUCTION_NODE = 2;
      static const int ELEMENT_NODE = 3;
      static const int CDATA_SECTION_NODE = 4;
      static const int TEXT_NODE = 5;
      static const int ATTRIBUTE_NODE = 6;
      
      virtual ~Node(void) {}
      
      // --------------------------------------------------------------------
      // Methods implementing (parts of) DOM Level 1 CORE interface "Node":
      
      /** Get the type of this node
       *  DOM level 1 interface Node
       */
      virtual unsigned short getNodeType(void) = 0;

      /// Return the "local" part of the nodes name (namespace identifier excluded)
      virtual std::string getLocalName(void) = 0;

      /// DOM function getFirstChild
      virtual Node * getFirstChild(void) = 0;
      
      /// DOM function
      virtual Node * getNextSibling(void) = 0;
      
      /// DOM function
      virtual std::string getNodeName(void) = 0;
      
      /// DOM function
      virtual std::string getNodeValue(void) = 0;

      virtual NamedNodeMap * getAttributes(void) = 0;

      
      
      // --------------------------------------------------------------------
      // From the element interface
      
      /// Get a named attribute of the current node.
      virtual std::string getAttribute(const std::string &) = 0;

      
      // --------------------------------------------------------------------

      
      
      /// Determine whether a node actually reference a value or not.
      virtual bool isNull(void) = 0;
      
      /// Return the first child node of the current node that is a DOM element.
      virtual Node * getFirstChildElement(void) = 0;
      
      /// Get the data of the first child element, or an empty string if the element does not exist.
      virtual std::string getFirstChildElementData(void) = 0;

      /// Return the namespace URI
      virtual std::string getNamespaceURI(void) = 0;

      /// Return the namespace prefix
      virtual std::string getPrefix(void) = 0;

      ///� Return the node data
      virtual std::string getNodeData(void) = 0;
      
      /// Return the first sibling of this node that is an element
      virtual Node * getNextSiblingElement(void) = 0;

      /// Get the tag named by the string argument, searching from the document root of the current node
      virtual Node * getTag(const std::string &) = 0;  
      
      /// Get the data of the node for the tag represented by the string argument, searching from the document root
      virtual std::string getTagData(const std::string & tag) = 0;
      
      /// Return the first child of the tag represented by the argument, searching from the document root
      virtual Node * getFirstChildOfTag(const std::string &) = 0;
      
      
      
      // XML Decl specific
      virtual std::string getVersion(void) = 0;
      virtual std::string getEncoding(void) = 0;
      virtual std::string getStandalone(void) = 0;
   };
   
   /// Implements generic functionality that does not have to be provided for every xml parser
   class GenericNode : public Node {
    public:
      virtual ~GenericNode() { }
      virtual std::string getFirstChildElementData(void);
      
      // These functions work on a tag referenced from the document root of the current node
      virtual std::string getTagData(const std::string & tag);
   };


   /// Use dom_ptr to simplify storage management. 
   typedef refcnt_ptr<domtools::Node> dom_ptr;
   typedef refcnt_ptr<domtools::NamedNodeMap> dom_namedmap_ptr;
   
   
   class Parser {
    public:
      virtual ~Parser() { }
      virtual Node * parseFile(const std::string & filename) = 0;
      virtual Node * parseMemory(const void * const buffer, int length) = 0;
      virtual Node * parseString(const std::string & str);
   };
   
#ifdef HAVE_XERCES
   // Xerces support

   class XercesNode;
   
   /// Implementation of domtools::NamedNodeMap for the Xerces XML parser
   class XercesNamedNodeMap : public NamedNodeMap {
    private:
      DOM_NamedNodeMap node;
    public:
      explicit XercesNamedNodeMap(const DOM_NamedNodeMap & n) : node(n)
	{
	}

      XercesNamedNodeMap(void)
	{
	}
      
      virtual ~XercesNamedNodeMap()
	{
	}
      
      virtual Node * item(int pos);
      virtual int getLength(void);
      
   };
   
   /// Implementation of domtools::Node for the Xerces XML parser
   class XercesNode : public GenericNode {      
    private:
      DOM_Node node;
    public:
      explicit XercesNode(const DOM_Node & n) : node(n)
	{
	}

      XercesNode(void)
	{
	}
      
      virtual bool isNull(void);
      virtual std::string getLocalName(void);
      
      virtual ~XercesNode(void)
	{
	}


      virtual std::string getNodeData(void)
	{
	   if (isNull()) return "";
	   std::string tmp;
	   domtools::getNodeData(node,tmp);
	   return tmp;
	}
      
      virtual Node * getFirstChildElement(void) 
	{
	   if (isNull()) return new XercesNode();
	   return new XercesNode(domtools::getFirstChildElement(node));
	}
      
      virtual Node * getNextSiblingElement(void) 
	{
	   if (isNull()) return new XercesNode();
	   return new XercesNode(domtools::getNextSiblingElement(node));
	}

      virtual Node * getFirstChildOfTag(const std::string & tag) 
	{
	   if (isNull()) return new XercesNode();
	   return new XercesNode(domtools::getFirstChildOfTag(node,tag));
	}

      virtual Node * getTag(const std::string & tag)
	{
	   if (isNull()) return new XercesNode();
	   return new XercesNode(domtools::getSingleTag(node,tag));
	}

      virtual std::string getAttribute(const std::string & attr)
	{
	   if (isNull()) return "";
	   if (node.getNodeType() != DOM_Node::ELEMENT_NODE) return "";
	   DOM_Element e = (DOM_Element &)node;
	   return toString(e.getAttribute(attr.c_str()));
	}

      virtual Node * getFirstChild(void)
	{
	   if (isNull()) return new XercesNode();
	   return new XercesNode(node.getFirstChild());
	}
      
      virtual std::string getNamespaceURI(void)
	{
	   if (isNull()) return "";
	   return toString(node.getNamespaceURI());
	}

      virtual std::string getPrefix(void)
	{
	   if (isNull()) return "";
	   return toString(node.getPrefix());
	}

      virtual Node * getNextSibling(void)
	{
	   if (isNull()) return new XercesNode();
	   return new XercesNode(node.getNextSibling());
	}

      virtual std::string getNodeValue(void)
	{
	   if (isNull()) return "";
	   return toString(node.getNodeValue());
	}

      virtual std::string getNodeName(void)
	{
	   if (isNull()) return "";
	   return toString(node.getNodeName());
	}

      virtual NamedNodeMap * getAttributes(void)
	{
	   if (isNull()) return 0;
	   return new XercesNamedNodeMap(node.getAttributes());
	}
      
      virtual unsigned short getNodeType(void);
      
      
      virtual std::string getVersion(void)
	{
	   if (node.isNull() || (node.getNodeType() != DOM_Node::XML_DECL_NODE)) return "";
	   return toString(((DOM_XMLDecl &)node).getVersion());
	}
      
      virtual std::string getEncoding(void)
	{
	   if (node.isNull() || (node.getNodeType() != DOM_Node::XML_DECL_NODE)) return "";
	   return toString(((DOM_XMLDecl &)node).getEncoding());
	}
      
      virtual std::string getStandalone(void)
	{
	   if (node.isNull() || (node.getNodeType() != DOM_Node::XML_DECL_NODE)) return "";
	   return toString(((DOM_XMLDecl &)node).getStandalone());
	}
   };

   /// Implementation of domtools::Parser for the Xerces XML parser
   class XercesParser : public Parser {
    public:
      
      XercesParser()
	{
	}
      
      ~XercesParser()
	{
	}
      
      virtual Node * parseFile(const std::string & filename);
      virtual Node * parseMemory(const void * const buffer, int length);
   };
   
#endif
   
}

#endif
/************************************************************************
* EPP RTK C++
* Copyright (C) 2001 Global Name Registry
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*
* Contact information:  [EMAIL PROTECTED]
*
*                       EPP RTK
*                       GNR Ltd.
*                       125 High Holborn
*                       London WC1V 6QA
*                       United Kingdom
************************************************************************/

#include "dom_print.h"
#include "dom_tools.h"

//#define XDebug(__cmd__) cerr << __FILE__ "," << __LINE__ << ": " << __cmd__ << endl;
#define XDebug(__cmd__)

using namespace std;
using namespace domtools;

void domtools::DomPrint::putDOMTree(const dom_ptr node)
{
   if (node->isNull()) return;

   string name;
   string value;
   
   dom_ptr tmp;
   dom_namedmap_ptr attrs;
   int len, pos;
   string::size_type spos;
   
   bool pi = false;
   
   switch (node->getNodeType()) {
    case Node::DOCUMENT_NODE:
      tmp = dom_ptr(node->getFirstChild());
      while (!tmp->isNull()) {
	 putDOMTree(tmp);
	 tmp = dom_ptr(tmp->getNextSibling());
      }
      return;
    case Node::XML_DECL_NODE:
      XDebug("XML_DECL_NODE");
      out.beginPI("xml");
      value= node->getVersion();
      out.putAttribute("version",value);
      value= node->getEncoding();
      if (value != "") out.putAttribute("encoding",value);
      value= node->getStandalone();
      if (value != "") out.putAttribute("standalone",value);
      out.endPI();
      return;
    case Node::PROCESSING_INSTRUCTION_NODE:
      pi = true;
      XDebug("PI");
      
      //-fallthrough
    case Node::ELEMENT_NODE:
      name = node->getNodeName();
      
      if (pi) out.beginPI(name);
      else out.beginTag(name);
      
      attrs = dom_namedmap_ptr(node->getAttributes());
      
      len = attrs->getLength();
      pos = 0;
      while (pos < len) {
	 tmp = dom_ptr(attrs->item(pos));
	 putDOMTree(tmp);
	 pos++;
      }
      
      canIgnore=true;
      tmp = dom_ptr(node->getFirstChild());
      while (!tmp->isNull()) {
	 putDOMTree(tmp);
	 tmp = dom_ptr(tmp->getNextSibling());
      }

      if (pi) out.endPI();
      else out.endTag(name);
      canIgnore=true;
      
      return;
    case Node::CDATA_SECTION_NODE:
      // We dont give a damn about the separation of CDATA and text. We will escape anything
      // anyway.
    case Node::TEXT_NODE:
      value = node->getNodeValue();
      cout << "value: " << value << endl;
      if (value != "") {
	 if (ignorews && canIgnore) {
	    spos = value.find_first_not_of(" \t\r\n");
	    if (spos != string::npos) out.putCDATA(value.substr(spos));
	 } else out.putCDATA(value);
      }
      return;
    case Node::ATTRIBUTE_NODE:
      // FIXME: Handle attributes without value
      out.putAttribute( node->getNodeName() , node->getNodeValue() );
      return;
    default:
      out.putCDATA("[UNKNOWN NODE TYPE]");
      XDebug("[UNKNOWN NODE TYPE]\n");
   };
}
/************************************************************************
* EPP RTK C++
* Copyright (C) 2001 Global Name Registry
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*
* Contact information:  [EMAIL PROTECTED]
*
*                       EPP RTK
*                       GNR Ltd.
*                       125 High Holborn
*                       London WC1V 6QA
*                       United Kingdom
************************************************************************/

#ifndef __DOM_PRINT_H
#define __DOM_PRINT_H

#include <string>
#include <iostream>

#include "dom_output.h"
#include "dom_wrapper.h"

namespace domtools {
   
   
   class DomPrint {
    private:
      //lint -e1725
      // out is a reference on purpose. Thus any constructors added should
      // _always_ initialize out from a reference passed in.
      basic_output & out;
      //lint +e1725
      
      bool ignorews;
      bool canIgnore;
      
      xml_string_output defaultOutput;
    public:
      DomPrint() : out(defaultOutput)
	{
	   reset();
	}

      DomPrint ( basic_output & inOut) : out(inOut)
	{
	   reset();
	}

      
      xml_string_output getDefaultOutput() const
	{
	   return defaultOutput;
	}
      

      void reset(void)
	{
	   ignorews = true;
	   canIgnore = true;
	}
      
      void putDOMTree(const domtools::dom_ptr);
      
      void setWhitespace(bool ignore)
	{
	   ignorews = ignore;
	}
   };
   
}

#endif

Reply via email to