views:

733

answers:

0

Hello, I am new to this site so I apologize in advance.

I am trying to modify an XML document using Xerces C 2.8. I'm somewhat familiar with Xercess though not proficient with it. What I am trying to do is: 1. make a function that will take a search node string and an insert node string, 2. parse a document and gather all searchnode matches 3. iterate through the nodelist and for each node create a new element named (insert node) 4. append the child nodes of the search node to the insert node and remove them from the search node 5. finally append the insert node to the search node.

I have the basic code in place but it is throwing: Encountered DOM Exception: An attempt is made to reference a node in a context where it does not exist.

Here is the contents of how I am parsing. This is an inherited class. The parent class merely sets the parser, error handler (I am using a known good error handler), output filename and so on. I can provide that code if needed however I am using the parent class for other transformations so I'm fairly certain the problem is localized to the "manipulate" method. Note that the caller catches the different xerces exceptions... that's how I know it's a DOMException being thrown.

UIIcon::InsertNodeXML::InsertNodeXML(std::string searchNodeName,
                std::string sourceFileName,
                xercesc::XercesDOMParser* parser,
                UIIcon::ErrorObj* errorHandler,
                std::string insertNodeName) :
            XMLConversionBase(searchNodeName,
                              TEMPFILEEXTENTION,
                              sourceFileName,
                               parser,
                               errorHandler),
            _searchNodeName(searchNodeName),
            _insertNodeName(insertNodeName){
if (_searchNodeName.compare("") == 0){
    throw std::string("Seach Node Name cannot be blank");
}
if (_insertNodeName.compare("") == 0){
    throw std::string("Insert Node Name cannot be blank");
}

}

void UIIcon::InsertNodeXML::convertDocument(){

xercesc::XMLFormatTarget* outfile = NULL;
xercesc::DOMWriter* writer = NULL;
 xercesc::DOMDocument* doc = NULL;


try{
    _parser->parse(xercesc::XMLString::transcode(_sourceFileName.c_str()));

    //doc = _parser->adoptDocument();
    doc = _parser->getDocument();

    manipulateDoc(doc);


    if (_errorHandler->getErrorStatus()){
        throw _errorHandler->getErrorMessageString();
    }

    xercesc::DOMImplementation* impl = xercesc::DOMImplementationRegistry::
                                       getDOMImplementation(DualString("Core").asXMLString());


    // construct the DOMWriter
    writer = ((xercesc::DOMImplementationLS*)impl)->createDOMWriter();
    // create the output xml document
    outfile = new xercesc::LocalFileFormatTarget( DualString( _outputFileName ).asXMLString() ) ;

    // add spacing and such for human-readable output
    if( writer->canSetFeature( xercesc::XMLUni::fgDOMWRTFormatPrettyPrint, true ) ){
        writer->setFeature( xercesc::XMLUni::fgDOMWRTFormatPrettyPrint , true );
    }

    doc->normalizeDocument() ;

    writer->writeNode( outfile , *doc ) ;

    //doc->release();
    delete( doc );
    delete( outfile ) ;
    delete( writer ) ;
    _parser->resetDocumentPool();
}
catch (...){
    if (doc != NULL){
        //doc->release();
        delete( doc );
    }
    //delete outputfile if it was created since there was an error
    FileFunctions(_outputFileName).deleteFile();
    delete( outfile ) ;
    delete( writer ) ;
    _parser->resetDocumentPool();
    throw;
}

}

// find the nodes matching search and add the new insert node. // Append the child nodes of search to the new node and remove them from search void UIIcon::InsertNodeXML::manipulateDoc(xercesc::DOMDocument doc){

//xercesc::DOMElement* rootElem = doc->getDocumentElement();

try{
    std::cout << "\ngetting node list using tag name: " << _searchNodeName << std::endl;
    xercesc::DOMNodeList *nodeList = doc->getElementsByTagName(DualString(_searchNodeName).asXMLString());
    xercesc::DOMNode *child = NULL;
    // traverse through tree looking for instances of search node.
    unsigned int length =  nodeList->getLength();

    std::cout << "\n" << length << " nodes found.\n\n";

    for (unsigned int i = 0; i < length; i++){

        std::cout << "\ngathering first child node" << std::endl;

        child = nodeList->item(i);
        // manipulate doc
        std::cout << "\ncreating new element" << std::endl;

        xercesc::DOMElement *newElement = doc->createElement(DualString(_insertNodeName).asXMLString());

        std::cout << "\ngetting child's node list" << std::endl;

        xercesc::DOMNodeList *nNodeList = child->getChildNodes();
        xercesc::DOMNode *nChild = NULL;

        unsigned int nLength =  nNodeList->getLength();
        std::cout << "\n" << nLength << " nodes found in child node.\n\n";

        for (unsigned int j = 0; j < nLength; j++){

            std::cout << "\ngathering child's node # " << j << std::endl;
            nChild = nNodeList->item(j);

            std::cout << "\nappending child's child node to new element and removing child's child node" << std::endl;
            newElement->appendChild(child->removeChild(nChild));

        }
        std::cout << "\nappending new element to child element" << std::endl;

        /* *****************************************************
         *   ERROR THROW FROM ->APPENDCHILD BELOW
         *******************************************************/
        child->appendChild(newElement);
        std::cout << "\nnew element appended to child element" << std::endl;

    }
}
catch (std::string e){
    throw std::string("Could not insert xml node: ") + e;
}
catch (...){
   throw;
}

}

Thanks for any help. If there is a better way to perform the manipulation I'm open to that as well. I will have to write a sister class to remove a node later so... this is setup for easy abstraction later.