You are viewing a plain text version of this content. The canonical link for it is here.
Posted to c-users@xalan.apache.org by "Anton V. Kozhevnikov" <an...@imp.uran.ru> on 2005/07/19 19:30:51 UTC

Document modification and XPath (again)

Hi!

I have the same problem with the document modification: I want to select 
a node using XPath and then modify this node
(remove it, add attributes to it or add a child node). Here is the part 
of my source:

DOMDocument *doc = 0;
XercesDOMSupport* theDOMSupport;
XercesParserLiaison* theParserLiaison;
XercesDOMWrapperParsedSource* parsedSource;
XPathEvaluator* theEvaluator;
XercesDocumentWrapper* docWrapper;

XalanNode* contextNode;
XalanNode* rootNode;
vector <XalanNode*> results;

void getResults(XalanNode* node, const string& expr)
{
    XObjectPtr theResult;

    try {
        theResult = theEvaluator->evaluate(*theDOMSupport, node,
            XalanDOMString(expr.c_str()).c_str(), 
XalanDocumentPrefixResolver(docWrapper));
    }
    catch (...) {
        cout << "Exception!" << endl;
    }

    assert(theResult.null() == false);

    const NodeRefListBase& contextNodeList = theResult->nodeset();
    int numItems = contextNodeList.getLength();

    results.clear();

    for (int i=0; i<numItems; i++ ) {
        results.push_back(contextNodeList.item(i));
    }
}

void cd(const string& path, int index, string& message)
{
    if (path[0] == '/' && path != "//" )
        getResults(rootNode, path);
    else
        getResults(contextNode, path);

    if (results.size() == 0) {
        cout << "cd(" << index << ") found an empty result set!" << endl;
        return;
    }
    if (index < 0 || index >= results.size()) {
        cout << "cd(" << index << ") index out of reange!" << endl;
        return;
    }

    contextNode = results[index];
}

void mkdir(const std::string& name, bool cdInto, std::string& message)
{
    assert(contextNode != 0);

    try {
        DOMElement* element = (DOMElement*)docWrapper->mapNode(contextNode);
        XMLCh* TagName = XMLString::transcode(name.c_str());
        DOMElement* newElement = 
(DOMElement*)doc->createElementNS(element->getNamespaceURI(), TagName);

        element->appendChild(newElement);
        docWrapper->rebuildWrapper();

        if (cdInto) {
            if (contextNode->hasChildNodes() && 
(contextNode->getLastChild() == 0)) {
                cout << "Unbelievable!" << endl;
                throw;
            }
            contextNode = contextNode->getLastChild();
        }
    }
    catch (XalanDOMException e) {
        int i = e.getExceptionCode();
        std::cout << "mkdir: XalanDOMException: code" << i << "\n";
    }
    catch (...) {
        std::cout << "mkdir: unknown exception\n";
    }

}

void setNodeValue(const string& attrName, const string& value, 
std::string& message)
{
    assert(contextNode != 0);

    try {
        DOMElement* element = (DOMElement*)docWrapper->mapNode(contextNode);
        if (attrName.length() == 0) {
            element->setTextContent(XMLString::transcode(value.c_str()));
        }
        else {
            
element->setAttribute(XMLString::transcode(attrName.c_str()),XMLString::transcode(value.c_str()));
        }
        docWrapper->rebuildWrapper();
    }
    catch(DOMException e) {
        std::cout << "setNodeValue: DOMException\n";
    }
    catch (XalanDOMException e) {
        int i = e.getExceptionCode();
        std::cout << "setNodeValue: XalanDOMException: code" << i << "\n";
    }
    catch(...) {
        std::cout << "setNodeValue: unknown exception\n";
    }
}

int main(void) {
    theDOMSupport = new XercesDOMSupport();
    theParserLiaison = new XercesParserLiaison(*theDOMSupport);
    theParserLiaison->setBuildWrapperNodes(true);
    theParserLiaison->setBuildMaps(true);
    parsedSource = new XercesDOMWrapperParsedSource(doc, 
*theParserLiaison, *theDOMSupport);
    docWrapper = 
theParserLiaison->mapDocumentToWrapper(parsedSource->getDocument());

    theEvaluator = new XPathEvaluator();

    rootNode = contextNode = docWrapper->getDocumentElement();

    cd("//cms:programSpecific", 0, message);
    mkdir("IO", true, message);

    int i,j;
    string attrs[5] = {"attr1","attr2","attr3","attr4","attr5"};
    for (i=0; i<2; i++ ) {
        mkdir("dir1", false, message);
        mkdir("dir2", false, message);
        mkdir("dir3", true, message);
        for (j=0; j<2; j++)
            setNodeValue(attrs[j],"value1",message);
    }
}

And now comes the most exciting part: the program's outputs:
[vay@re test_xalan]$ ./a.out
[vay@re test_xalan]$ ./a.out
Unbelievable!
Aborted
[vay@re test_xalan]$ ./a.out
[vay@re test_xalan]$ ./a.out
[vay@re test_xalan]$ ./a.out
Unbelievable!
Aborted
[vay@re test_xalan]$ ./a.out
[vay@re test_xalan]$ ./a.out
mkdir: XalanDOMException: code4
setNodeValue: XalanDOMException: code4
setNodeValue: XalanDOMException: code4
[vay@re test_xalan]$ ./a.out
Unbelievable!
Aborted
[vay@re test_xalan]$ ./a.out
mkdir: XalanDOMException: code4
mkdir: XalanDOMException: code4
setNodeValue: XalanDOMException: code4
setNodeValue: XalanDOMException: code4

Same input, same binary executable. Where am I wrong?
This was compiled using the latest xalan from CVS 
(xml-xalan_20050717042537.tar.gz), though xalan-1.8 gives the same results.

[vay@re vay]$ g++ --version
g++ (GCC) 3.2.3 20030502 (Red Hat Linux 3.2.3-52)

[vay@re vay]$ uname -a
Linux re 2.4.21-27.0.1.EL #1 Mon Dec 20 18:56:53 EST 2004 i686 i686 i386 
GNU/Linux

With best regards,
A.