Question

I'm writing a server and I wanted to use XML with my Java client. I'm using CygWin with XercesC 3.1.1 for my development test and this works fine (I looped 30000 with this function and had no crash). However, on my target machine it's running HP-UX with XercesC 2.7. To implement the differences in the XercesC implementation I wrote a separate class to handle each version.

When I try to run the code with XercesC 2.7. I always get a NULL pointer when I try to create the DOMWriter, and a SIGABORT when trying again.

Since I couldn't find anyything on google I hope that someone can shed some light on what I'm doing wrong here. I've been looking at the sample code provided with the XercesC souorce, and I also have some production code from fellow programmers, and I can't see any difference for the live of it.

I tried to create an SSCE which is a bit long, but it is the shortest sample that I could create.

xml_serialize.h

#ifndef XML_SERIALIZE_H_
#define XML_SERIALIZE_H_

#include <string>

#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/dom/DOM.hpp>
#if defined(XERCES_NEW_IOSTREAMS)
#include <iostream>
#else
#include <iostream.h>
#endif
#include <xercesc/util/OutOfMemoryException.hpp>

class XStr
{
public :
    // -----------------------------------------------------------------------
    //  Constructors and Destructor
    // -----------------------------------------------------------------------
    XStr(const char* const toTranscode)
    {
        // Call the private transcoding method
        fUnicodeForm = xercesc::XMLString::transcode(toTranscode);
    }

    ~XStr()
    {
     xercesc::XMLString::release(&fUnicodeForm);
    }


    // -----------------------------------------------------------------------
    //  Getter methods
    // -----------------------------------------------------------------------
    const XMLCh* unicodeForm() const
    {
        return fUnicodeForm;
    }

private :
    // -----------------------------------------------------------------------
    //  Private data members
    //
    //  fUnicodeForm
    //      This is the Unicode XMLCh format of the string.
    // -----------------------------------------------------------------------
    XMLCh*   fUnicodeForm;
};

#define X(str) XStr(str).unicodeForm()

std::string fromXMLString(XMLCh *oXMLString);

class XMLSerialize
{
private:
        xercesc::DOMImplementation *mImpl;

protected:
        xercesc::DOMImplementation *getDOMImplementation(void);

public:
    XMLSerialize(void);
    virtual ~XMLSerialize(void);

public:

    /**
     * Creates an empty DOM
     */
    xercesc::DOMDocument *createDocument(const std::string &oDocumentName);

    /**
     * Parses an XML from a string.
     */
    xercesc::DOMDocument *parseDocument(const std::string &oDocumentName, std::string const &oReferenceId);

    /**
     * Serializes the document into a string
     */
    int serialize(xercesc::DOMDocument *oDocument, std::string &oXMLOut, bool bDocumentRelease = true);
};

#endif /* XML_SERIALIZE_H_ */

xml_serialize.cpp

#include <xercesc/util/XMLString.hpp>
#include <xercesc/dom/DOM.hpp>
#include <xercesc/util/TransService.hpp>
#include <xercesc/framework/MemBufFormatTarget.hpp>
#include <xercesc/util/OutOfMemoryException.hpp>

#include <sstream>
#include <vector>
#include <iostream>

#include "xml_serialize.h"

int serializeEnvironment(void);
XMLSerialize *serializer = NULL;

XMLSerialize::XMLSerialize()
{
    mImpl = xercesc::DOMImplementationRegistry::getDOMImplementation(X("Core"));
}

XMLSerialize::~XMLSerialize()
{
}

xercesc::DOMDocument *XMLSerialize::createDocument(const std::string &oDocumentName)
{
    if(mImpl == NULL)
        return NULL;

    xercesc::DOMDocument *doc = mImpl->createDocument(
            0,                      // root element namespace URI.
            X(oDocumentName.c_str()),       // root element name
            0);                 // document type object (DTD).

    if(doc == NULL)
        return NULL;

    return doc;
}

int XMLSerialize::serialize(xercesc::DOMDocument *oDocument, std::string &oXMLOut, bool bDocumentRelease)
{
    int result = 0;
    XMLCh *xmlUnicode = NULL;
    char *strXML = NULL;
    xercesc::DOMWriter *serializer = NULL;

    if(mImpl == NULL)
    {
        oXMLOut = "ERROR: XercesC DOMImplementationRegistry not initialized";
        result = 1;
        goto Quit;
    }

    serializer = ((xercesc::DOMImplementationLS*)mImpl)->createDOMWriter();
    if(serializer == NULL)
    {
        oXMLOut = "ERROR: XercesC unable to instantiate a DOMWriter!";
        result = 2;
        goto Quit;
    }

    xmlUnicode = serializer->writeToString(*oDocument);
    strXML = xercesc::XMLString::transcode(xmlUnicode);
    oXMLOut = strXML;

    if(bDocumentRelease == true)
        oDocument->release();

    result = 0;

Quit:
    if(strXML != NULL)
        xercesc::XMLString::release(&strXML);

    if(xmlUnicode != NULL)
        xercesc::XMLString::release(&xmlUnicode);

    if(serializer != NULL)
        serializer->release();

    return result;
}

int serializeEnvironment(void)
{
    int errorCode = 0;
    xercesc::DOMElement *rootElem = NULL;
    xercesc::DOMElement *item = NULL;
    xercesc::DOMElement *element = NULL;
    xercesc::DOMText *nameNode = NULL;
    xercesc::DOMCDATASection *dataNode = NULL;
    std::string xml;

    try
    {
        xercesc::DOMDocument *doc = serializer->createDocument("EnvironmentList");
        if(doc == NULL)
            return 1;

        rootElem = doc->getDocumentElement();
        std::vector<std::pair<std::string, std::string> > env;
        for(int i = 0; i < 5; i++)
        {
            std::string key;
            std::string value;

            std::stringstream ss;
            ss << "KEY";
            ss << i;
            ss >> key;
            ss.clear();

            ss << "VALUE";
            ss << i;
            ss >> value;
            ss.clear();

            env.push_back(std::make_pair(key, value));
        }

        for(std::vector<std::pair<std::string, std::string> >::const_iterator it = env.begin(); it != env.end(); ++it)
        {
            std::pair<std::string, std::string>entry = *it;
            std::string name = entry.first;
            std::string value = entry.second;

            if(value.empty())
                value = "";

            item = doc->createElement(X("item"));
            rootElem->appendChild(item);

            element = doc->createElement(X("item"));
            nameNode = doc->createTextNode(X(name.c_str()));
            item->appendChild(element);
            element->appendChild(nameNode);

            element = doc->createElement(X("item"));
            dataNode = doc->createCDATASection(X(value.c_str()));
            item->appendChild(element);
            element->appendChild(dataNode);
        }

        errorCode = serializer->serialize(doc, xml);
        std::cout << xml << std::endl;

        doc->release();
        errorCode = 0;
    }
    catch (const xercesc::OutOfMemoryException&)
    {
        XERCES_STD_QUALIFIER cerr << "OutOfMemoryException" << XERCES_STD_QUALIFIER endl;
        errorCode = 2;
    }
    catch (const xercesc::DOMException& e)
    {
        XERCES_STD_QUALIFIER cerr << "DOMException code is:  " << e.code << XERCES_STD_QUALIFIER endl;
        errorCode = 3;
    }
    catch (...)
    {
        XERCES_STD_QUALIFIER cerr << "An error occurred creating the document" << XERCES_STD_QUALIFIER endl;
        errorCode = 4;
    }

    return errorCode;
}

int main()
{
    xercesc::XMLPlatformUtils::Initialize();

   serializer = new XMLSerialize();

   int error = 0;
   for(int i = 0; i < 2; i++)
   {
    std::cout << "Serializing:" << i << " ... " << std::endl;
    if((error = serializeEnvironment()) != 0)
        std::cout << "ERROR" << error << std::endl;

    std::cout << "Done" << std::endl;
   }

    xercesc::XMLPlatformUtils::Terminate();

    return 0;
}

output

Serializing:0 ... 
ERROR: XercesC unable to instantiate a DOMWriter!
Done
Serializing:1 ... 
aCC runtime: pure virtual function called for class "xercesc_2_7::DOMImplementationLS".
Abort(coredump)

update

I finally managed to compile 2.7 for cygwin and tested the above code there. This works fine, so there must be some problem with the HP-UX environment.

Was it helpful?

Solution

I was compiling the code with gcc and aparently the xerces library was compiled with aCC. So nopw I switched to aCC in my makefile and now it works.

One should expect that the produced libraries are compatible, but apparently this is not the case. So the above code is actually correct.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top