(Is there any problem with setting the context node to
a "/" in selectSingleNode?)

Not that I'm aware of.  I've used the document root as the context node
in both 'theEvaluator.evaluate() (or something like that) and in
selectNodeList() in the example I gave you and have had no problems.

-will

-----Original Message-----
From: Coker, Jonathan M [mailto:[EMAIL PROTECTED] 
Sent: Thursday, March 29, 2007 1:49 PM
To: xalan-c-users@xml.apache.org
Subject: RE: Xalan parser in a class

Thanks Will.  I will look through your code and get back with questions.
I joined the list on 3/1 so I will look for archives to find your
discussion with Dave.  Part of what I am trying to do is clean up order
dependencies in some initialization files.  If I can collect a set of
nodes from anywhere in a document then use each one of those as the
context node for a data extractor function, I can get rid of some very
inflexible code.  (Is there any problem with setting the context node to
a "/" in selectSingleNode?)

Thanks again,

Jonathan

-----Original Message-----
From: Will Sappington [mailto:[EMAIL PROTECTED] 
Sent: Thursday, March 29, 2007 11:56 AM
To: xalan-c-users@xml.apache.org
Subject: RE: Xalan parser in a class

I cut out some code that illustrates what I did.  I pasted it in-line
below, prolly coulda' sent it as an attachment, OutHouse's word wrap
really screws it up, but oh well.  The issue I was having trouble with
is that certain objects that need to be in member data (parserLiaison?)
need the Xalan and Xerces platform initialization done before they are
instantiated, but that can't happen if you are instantiating them as
member data because the class constructor hasn't yet run.

Dave suggested a way of doing this by creating a ProfileInit class that
calls the ::initialize() methods in its constructor and then
instantiating the init class before instantiating the Profile class.
Prior to receiving his suggestion I had started work on doing the
::initialize() stuff in a static member that gets called to instantiate
the profile.  Either way works.  

Dave and I had some lengthy discussion about this in two threads that
started around Feb. 12, one titled "problem evaluating XPath
expressions" and the other a little later titled "Xalan initialization".
Between the information in these threads and the sample code below,
there should be enough to get you going.  Dave's suggestion for handling
the initialization appears in the "problem evaluating XPath expressions"
thread on 2/14.  HTH,

-will

class Profile
{
public:

    /*=========================================
    = public member data and functions
    ==========================================*/

    /// get an instance of the profile
    static Profile* getInstance (const char* pFilespec = NULL) throw
(NdmaEx&);

    /// delete an instance of the profile
    static void deleteInstance (Profile* pInstance) throw (NdmaEx&);

    /// open a profile with the specified filename
    void openProfile (const char* pFilespec) throw (NdmaEx&);

    /// retrieve an item from the profile
    const ProfileItem* getItem (const char* pAppName, const char*
pSectionName, const char* pItemName) throw (NdmaEx&);

    /// close the profile
    void closeProfile () const;

protected:

private:

    XalanDocument*              _pXmlDoc; ///< ptr to the Xalan DOM
document
    XalanSourceTreeInit         _sourceTreeInit; ///< source tree init
class, ctor does init
    XalanSourceTreeDOMSupport   _domSupport; ///< Xalan DOM support
class
    XalanSourceTreeParserLiaison    _parserLiaison; ///< helper class
between parser & DOM

};

Profile* Profile::getInstance (const char* pFilespec) throw (NdmaEx&) {
    Profile*    pInstance = NULL;
    /* make sure we only initialize once */

    if (instanceCount == 0)
    {
        /* intialize the Xerces system */

        XMLPlatformUtils::Initialize();

        /* initialize the Xalan XPath evaluator */

        XPathEvaluator::initialize();
        pInstance = new Profile(pFilespec);
        instanceCount++;
    }
    return (pInstance);
}

void Profile::deleteInstance (Profile* pInstance) throw (NdmaEx&) {
    pInstance->_close();

    /* delete it anyway, if we're down to zero instances, shutdown the
XML libraries */

    delete pInstance;
    if (--instanceCount == 0)
    {
        XPathEvaluator::terminate();
        XMLPlatformUtils::Terminate();
    }

    return;
}

int Profile::openProfile (const char* pXmlFilespec) {
    // Hook the DOM support and the parser liaison together...
    _domSupport.setParserLiaison(&_parserLiaison);

    // convert the filename to a UTF-16 string for use by Xalan
    const XalanDOMString    theFileName(pXmlFilespec);

    // Create an input source that represents a local file...
    step++;
    const LocalFileInputSource  theInputSource(theFileName.c_str());

    // Parse the document...
    step++;
    XalanDocument* const theDocument =
_parserLiaison.parseXMLStream(theInputSource);

    if (theDocument == NULL)
    {
        /* parsing failed, set an error */

        rc = E_ANY_ERROR;
    }
    else
    {
        /* set these member vars so the XPath stuff can use them */

        _pXmlDoc = theDocument;
    }

    return (rc);
}

ProfileItem* Profile::getItem (const char* pAppName, const char*
pSectionName, const char* pItemName) {

    XalanDocumentPrefixResolver thePrefixResolver(_pXmlDoc);

    XPathEvaluator theEvaluator;

    /* find the context node (the starting point... */
    XalanNode* const pContextNode =
theEvaluator.selectSingleNode(_domSupport, _pXmlDoc,
XalanDOMString(pDfltContext).c_str(),
 
thePrefixResolver);
    if (pContextNode == 0)
    {
        rc = E_ANY_ERROR;
    }
    else
    {
        /* found the context node, evaluate the expression */

        NodeRefList nodeList;
        theEvaluator.selectNodeList(nodeList,
                                    _domSupport,
                                    pContextNode,
                                    XalanDOMString(xpathExpr).c_str(),
                                    _pXmlDoc->getDocumentElement());

        const NodeRefList::size_type    listLen = nodeList.getLength();

        if (listLen == 0)
        {
            /* a zero length result means we didn't find it */

            rc = E_ITEM_NOTFOUND;
        }
        else
        {
            /* got a set of item nodes, do something with them */
        }
    }   /* end (found the context node) */
    return (rc);
}


-----Original Message-----
From: Coker, Jonathan M [mailto:[EMAIL PROTECTED]
Sent: Thursday, March 29, 2007 12:23 PM
To: xalan-c-users@xml.apache.org
Subject: RE: Xalan parser in a class

I have started working on this but my first attempt fails during the
creation of the prefixResolver.  It looks like the
NamespaceNodeTreeWalker instantiation is failing in the
XalanDocumentPrefixResolver constructor.  I am going to make sure I do
not have any 'bookkeeping' errors and then I may post some code
segments.  Thanks again for all of the assistance.

Jonathan 

-----Original Message-----
From: Will Sappington [mailto:[EMAIL PROTECTED]
Sent: Thursday, March 29, 2007 11:13 AM
To: xalan-c-users@xml.apache.org
Subject: RE: Xalan parser in a class

I did exactly this (with help from Dave, Thanks Dave!) for an XML
configuration file reader I just wrote.  I put the XalanDocument*,
XalanSourceTreeInit, XalanSourceTreeDOMSupport, and
XalanSourceTreeParserLiaison in class member data.  Works fine.  Crazy
busy for the next couple of hours but I'll post up some code snippets
first chance I get.

-will

-----Original Message-----
From: David Bertoni [mailto:[EMAIL PROTECTED]
Sent: Wednesday, March 28, 2007 5:09 PM
To: xalan-c-users@xml.apache.org
Subject: Re: Xalan parser in a class

Coker, Jonathan M wrote:
> Hello,
>    Most of the examples I have seen have all of the Xalan code in a 
> single routine.  I would like to wrap this in a class and break some
of
> the functionality into different member functions.  For example, I
would
> like to create a function that would take node as an argument then use

> it for the context node to evaluate a path.  In order to do this it 
> seems like some of the things that are created (XercescDOMSupport, 
> XercesParserLiason, etc.) are good candidates for data members on the 
> class.  Does this seem reasonable or am I going to have a lot of
trouble
> trying to do this?

It's a reasonable thing, and essential if you're concerned with object
lifetimes.  For example, any documents you create with a
XercesParserLiaison instance are destroyed when that instance goes out
of scope.

As a side note, I would encourage you to use Xalan-C's default source
tree implementation, rather than the Xerces-C DOM, unless your
application has a specific need for the Xerces-C DOM.

Dave

Reply via email to