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 Will Sappington <ws...@ndma.us> on 2007/02/12 04:37:27 UTC

Problem evaluating XPath expressions

Hello all,

 

I'm writing a configuration utility that we call an "application
profile" or simply profile, that is essentially an ini file on steroids.
It's a hierarchical structure - application/section/item - that allows
multiple applications to use a single profile.  I'm migrating it from
"key = value" format to XML and I'm using Xalan/Xerces for evaluating
XPath expressions to retrieve the configuration items.

 

>From a functional standpoint, the interface to the profile is:

-          open the profile (load the XML file, parse it into a DOM
tree)

-          execute a getItem() call for each of the one or more items to
be retrieved

-          close the profile

 

After using the SimpleXPath... sample program to set up a working XPath
evaluation, I tried splitting things up along open/read/close functional
lines.  That is, I tried reading the XML file and parsing it into a
Xalan DOM tree in the open() method, doing the XPath evaluation in the
getItem() method, and the terminate() functions in the close() method.
To do this I had to put certain objects common to the open() and
getItem() methods into Profile class member data, specifically the
XalanDocument* and the XalanSourceTreeDOMSupport.  

 

The open() method runs successfully, parses the doc, and sets up the
XalanDocument pointer.  However, when I try to evaluate an XPath
expression, the instantiation of the XalanDocumentPrefixResolver object
fails with a "generic" exception, that is:

 

XalanDocumentPrefixResolver     thePrefixResolver(_pXmlDoc);

 

where _pXmlDoc is in the Profile class private member data

 

throws an exception caught by the (...) catch.  The code for the methods
in question is below.  Is there a way to do what I'm trying to do?  Can
I, from inside what is essentially a wrapper class, open and parse a
document into a DOM tree in one method, and then use the results of that
method to execute one or more XPath evaluations against the DOM tree in
another method?  I'd really hate to have to parse the document every
time a user makes a call to getItem().  Thanks in advance, any help
would be most appreciated.

 

Best,

 

-will  (code follows, catches and some other irrelevant stuff left out
for brevity)

 

 

int Profile::_openXmlDoc (const char* pXmlFilespec)

{

    try

    {

        XMLPlatformUtils::Initialize();

        XPathEvaluator::initialize();

 

        {

            // Initialize the XalanSourceTree subsystem...

            XalanSourceTreeInit     theSourceTreeInit;

 

            // We'll use these to parse the XML file.

            // now declared in private member data

//             XalanSourceTreeDOMSupport  theDOMSupport;

 

            XalanSourceTreeParserLiaison    theLiaison(_DomSupport);

 

            // Hook the two together...

            _DomSupport.setParserLiaison(&theLiaison);

 

            const XalanDOMString    theFileName(pXmlFilespec);

 

            // Create an input source that represents a local file...

            const LocalFileInputSource
theInputSource(theFileName.c_str());

 

            // Parse the document...

            XalanDocument* const theDocument =
theLiaison.parseXMLStream(theInputSource);

            if (theDocument == NULL)

            {

                ::sprintf(_zErr, "Error (%s): document parsing failed
for file (%s)\n",

                          pThisFnc, theFileName.c_str());

                rc = E_ANY_ERROR;

            }

            else

            {

                /* set these member vars so the XPath stuff can use them
*/

                _pXmlDoc = theDocument;

            }

        }

    }

    return (rc);

}  // end _open()

 

int Profile::_getStringItem (const char* pAppName, const char*
pSectionName, const char* pItemName,

                             char* pBufRet, size_t& bufLen)

{

    ::memset((void*)xpathExpr, 0, sizeof(xpathExpr));

    ::sprintf(xpathExpr, pXPathTplt, pAppName, pSectionName, pItemName);

 

    try

    {

        // use the document pointer stored in member data

        // ** this statement throws an exception caught by the (...)
catch

 

        XalanDocumentPrefixResolver     thePrefixResolver(_pXmlDoc);

        XPathEvaluator                  theEvaluator;

 

        // OK, let's find the context node...  using member data for
DomSupport and pXmlDoc?

        // but we never get to this point

 

        XalanNode* const pContextNode =
theEvaluator.selectSingleNode(_DomSupport,

 
_pXmlDoc,

 
XalanDOMString(pDfltContext).c_str(),

 
thePrefixResolver);

        if (pContextNode == 0)

        {

            ::sprintf(_zErr, "Error (%s): No nodes matched the context
path (%s)\n",

                      pThisFnc, pDfltContext);

            rc = E_ANY_ERROR;

        }

        else

        {

            // OK, let's evaluate the expression...

            const XObjectPtr
theResult(theEvaluator.evaluate(_DomSupport,

 
pContextNode,

 
XalanDOMString(xpathExpr).c_str(),

 
thePrefixResolver));

            if (theResult.null())

            {

                /* a null result means we didn't find it, set the
returned length

                    to zero and set an error */

 

                bufLen = 0;

                ::sprintf(_zErr, "Warning (%s): item not found, no node
matched "

                                 "the XPath expression:\n    (%s)\n",
pThisFnc, xpathExpr);

                rc = E_ITEM_NOTFOUND;

            }

            else

            {

                /* we found something, jump through a couple of hoops to
get it

                    into a C-string, copy it to the return buffer, and
set the

                    returned length */

 

                /* the transcode method transcodes the result string
(UTF-16) to

                    chars and stores them in a vector of chars.  the
chars from

                    the vector are then assigned to a std::string object
by

                    iterating through the vector.  once assigned to the
string

                    they are in a form we can use them. */

 

                XalanVector<char> charData;

                std::string rtnStr;

 

                theResult->str().transcode(charData);

                rtnStr.assign(charData.begin(), charData.end());

 

                /* clear the return buffer, copy the string in, and set
the returned length */

 

                ::memset((void*)pBufRet, 0, bufLen);

                ::strncpy(pBufRet, rtnStr.c_str(), bufLen - 1);

                pBufRet[bufLen - 1] = 0;

                bufLen = ::strlen(rtnStr.c_str());

            }

        }

    }

 

    return (rc);

}  // end getItem()


RE: Problem evaluating XPath expressions

Posted by Will Sappington <ws...@ndma.us>.
Thanks Dave for the quick reply, I'll try what you suggest.

-will

-----Original Message-----
From: David Bertoni [mailto:dbertoni@apache.org] 
Sent: Monday, February 12, 2007 1:50 AM
To: xalan-c-users@xml.apache.org
Subject: Re: Problem evaluating XPath expressions

Will Sappington wrote:
> Hello all,
> 
>  
> 
> I'm writing a configuration utility that we call an "application 
> profile" or simply profile, that is essentially an ini file on 
> steroids.  It's a hierarchical structure - application/section/item - 
> that allows multiple applications to use a single profile.  I'm 
> migrating it from "key = value" format to XML and I'm using
Xalan/Xerces 
> for evaluating XPath expressions to retrieve the configuration items.
>

...

> 
> XalanDocumentPrefixResolver     thePrefixResolver(_pXmlDoc);
> 
>  
> 
> where _pXmlDoc is in the Profile class private member data
>

 From looking at your code, I suspect the _pXmlDoc data member is
pointing 
to an instance that's already been destroyed.

Here's what the comments for XMLParserLiason::parseXMLStream() say:

/**
  * Parse the text pointed at by the reader as XML, and return a DOM
  * Document interface.  It is recommended that you pass in some sort of
  * recognizable name, such as the filename or URI, with which the
reader
  * can be recognized if the parse fails.
  *
  * The liaison owns the XalanDocument instance, and will delete it when
  * when asked (see DestroyDocument()), or when the liaison is reset, or
  * goes out of scope.
  */

So, the instance you created is destroyed when the 
XalanSourceTreeParserLiaison instance is destroyed in
Profile::_openXmlDoc().

In general, Xalan-C implements very tightly controlled ownership of 
objects.  The easiest way for you to handle this is to make the 
XalanSourceTreeParserLiason instance a member of your class.

Dave

Re: XPath result - null or zero length?

Posted by David Bertoni <db...@apache.org>.
Will Sappington wrote:
> I searched the archives for "xpath result" (unquoted) and didn't get any
> useful hits so:
> 
> The SimpleXPathAPI example does this after establishing the context
> node:
> 
> // OK, let's evaluate the expression...
> const XObjectPtr	theResult(
> 				theEvaluator.evaluate(
> 				theDOMSupport,
> 				theContextNode,
> 				XalanDOMString(argv[3]).c_str(),
> 				thePrefixResolver));
> 
> assert(theResult.null() == false);
> 
> cout << "The string value of the result is:"
> 	 << endl
> 	 << theResult->str()
> 	 << endl
> 	 << endl;
> 
> It would appear from this that the test for an unsuccessful XPath
> evaluation is theResult.null() returning true.  However, if I evaluate
> an XPath expression containing an element or attribute that is not in
> the file, that test fails - .null() returns false - and after converting
> the result to a regular C char string, it is empty, zero length.  If I
> give the SimpleXPathAPI sample program an expression that will not
> match, it prints "The string value of the result is ", indicating that
> it too got a zero length result instead of null.  

XObjectPtr is a smart-pointer class, so the call to the null() member 
function just determines whether or not it's pointing to an XObject 
instance. In this case,

Any calls made using the -> operator are passed on to the underlying 
XObject instance.  The XObject class holds the actual result of the 
evaluation.  It's type depends on the type of the XPath expression you've 
evaluated.

If you get a zero-length string, that just means that the result of the 
expression has that value.  That could be an empty string, or an empty 
node-set.

> 
> The API docs for XPathEvaluator::evaluate() just say that it returns the
> result of the search.  To find out exactly what that is, I dug through
> the XPathEvaluator::evaluate() code as far as I could but I got lost in
> all the cases in XPath::executeMore().  Searched the archive but didn't
> find anything.

The result of an XPath 1.0 expression can have a type of string, number, 
boolean or node-set.  I'm assuming most of your expressions are location 
paths, so those will be of type node-set.  In that case, you can call 
XObject::nodeset(), to get a reference to the underlying NodeRefListBase 
instance.  However, if the expression is not a node-set, then calling that 
function will result in an exception.  If you're worried about the type of 
the resulting XObject instance, you can call XObject::getType()

> 
> Q: which test should I use for an unsuccessful match, null or zero
> length, or could I get both and they mean different things?

You call nodeset() to get a reference to the underlying NodeRefListBase, 
then call getLength() to see how many nodes there are.

Dave

XPath result - null or zero length?

Posted by Will Sappington <ws...@ndma.us>.
I searched the archives for "xpath result" (unquoted) and didn't get any
useful hits so:

The SimpleXPathAPI example does this after establishing the context
node:

// OK, let's evaluate the expression...
const XObjectPtr	theResult(
				theEvaluator.evaluate(
				theDOMSupport,
				theContextNode,
				XalanDOMString(argv[3]).c_str(),
				thePrefixResolver));

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

cout << "The string value of the result is:"
	 << endl
	 << theResult->str()
	 << endl
	 << endl;

It would appear from this that the test for an unsuccessful XPath
evaluation is theResult.null() returning true.  However, if I evaluate
an XPath expression containing an element or attribute that is not in
the file, that test fails - .null() returns false - and after converting
the result to a regular C char string, it is empty, zero length.  If I
give the SimpleXPathAPI sample program an expression that will not
match, it prints "The string value of the result is ", indicating that
it too got a zero length result instead of null.  

The API docs for XPathEvaluator::evaluate() just say that it returns the
result of the search.  To find out exactly what that is, I dug through
the XPathEvaluator::evaluate() code as far as I could but I got lost in
all the cases in XPath::executeMore().  Searched the archive but didn't
find anything.

Q: which test should I use for an unsuccessful match, null or zero
length, or could I get both and they mean different things?

Thanks in advance,

-will

RE: Xalan initialization

Posted by Will Sappington <ws...@ndma.us>.
-----Original Message-----
From: David Bertoni [mailto:dbertoni@apache.org] 
Sent: Thursday, February 15, 2007 5:48 PM
To: xalan-c-users@xml.apache.org
Subject: Re: Xalan initialization

Will Sappington wrote:
> While researching the XPath evaluator question I came across something
> that raised a question about Xalan initialization so I'll ask it while
I
> continue digging.
> 
> I came across the following in the mail list archive, dated
2006-04-26,
> re: "Regarding XPath query":
> 
> As I said previously, the best thing to do is to call
>> XalanTransformer::initialize() in main(), and remove any usage of the
>> "Init" classes.
> 
> The sample app on which the code I'm writing is based - SimpleXPathAPI
-
> calls XMLPlatformUtils::Initialize() and XPathEvaluator::initialize()
> and also instantiates a XalanSourceTreeInit class.
> 
> My code does exactly this and is working.  The example code Dave sent
me
> in a previous post uses XalanTransformer::initialize() instead of
> XPathEvaluator::initialize().

What you're doing is fine, but not everything is initialized when you do
this.

> 
> Q: should I replace XPathEvaluator::initialize() with
> XalanTransformer::initialize()?  (probably yes)

This initializes more stuff, so it will use more memory, etc.  The 
advantage is you avoid mysterious crashes when you start using something
in 
  another subsystem, and you forgot to do further initialization.

> 
> Q: do I still need the XalanSourceTreeInit class? (really don't know)

If you use XalanTransformer::initialize(), then you don't need 
XPathEvaluator::initialize() or XalanSourceTreeInit.  For more details, 
take a look at what XalanTransformer::initialize() does, vs. what 
XPathEvaluator::initialize() does, vs. what the class
XalanSourceTreeInit does.

Dave

==================

Thank you,

-will

Re: Xalan initialization

Posted by David Bertoni <db...@apache.org>.
Will Sappington wrote:
> While researching the XPath evaluator question I came across something
> that raised a question about Xalan initialization so I'll ask it while I
> continue digging.
> 
> I came across the following in the mail list archive, dated 2006-04-26,
> re: "Regarding XPath query":
> 
> As I said previously, the best thing to do is to call
>> XalanTransformer::initialize() in main(), and remove any usage of the
>> "Init" classes.
> 
> The sample app on which the code I'm writing is based - SimpleXPathAPI -
> calls XMLPlatformUtils::Initialize() and XPathEvaluator::initialize()
> and also instantiates a XalanSourceTreeInit class.
> 
> My code does exactly this and is working.  The example code Dave sent me
> in a previous post uses XalanTransformer::initialize() instead of
> XPathEvaluator::initialize().

What you're doing is fine, but not everything is initialized when you do this.

> 
> Q: should I replace XPathEvaluator::initialize() with
> XalanTransformer::initialize()?  (probably yes)

This initializes more stuff, so it will use more memory, etc.  The 
advantage is you avoid mysterious crashes when you start using something in 
  another subsystem, and you forgot to do further initialization.

> 
> Q: do I still need the XalanSourceTreeInit class? (really don't know)

If you use XalanTransformer::initialize(), then you don't need 
XPathEvaluator::initialize() or XalanSourceTreeInit.  For more details, 
take a look at what XalanTransformer::initialize() does, vs. what 
XPathEvaluator::initialize() does, vs. what the class XalanSourceTreeInit does.

Dave

Xalan initialization

Posted by Will Sappington <ws...@ndma.us>.
While researching the XPath evaluator question I came across something
that raised a question about Xalan initialization so I'll ask it while I
continue digging.

I came across the following in the mail list archive, dated 2006-04-26,
re: "Regarding XPath query":

As I said previously, the best thing to do is to call
> XalanTransformer::initialize() in main(), and remove any usage of the
> "Init" classes.

The sample app on which the code I'm writing is based - SimpleXPathAPI -
calls XMLPlatformUtils::Initialize() and XPathEvaluator::initialize()
and also instantiates a XalanSourceTreeInit class.

My code does exactly this and is working.  The example code Dave sent me
in a previous post uses XalanTransformer::initialize() instead of
XPathEvaluator::initialize().

Q: should I replace XPathEvaluator::initialize() with
XalanTransformer::initialize()?  (probably yes)

Q: do I still need the XalanSourceTreeInit class? (really don't know)

Thank you in advance,

-will

RE: Problem evaluating XPath expressions

Posted by Will Sappington <ws...@ndma.us>.
Hello Dave and all,

Prior to Dave posting the example below of how to initialize
Xalan/Xerces before instantiating library objects as member data, I
figured out a way of doing it that also works, described below.  I'd
like to know if anyone has any thoughts regarding using a static member
function vs. as separate class as Dave describes below.  I'm not so far
along that I couldn't switch if my method isn't good for some reason.
I'm aware of usability issues such as the static function requiring the
user to explicitly get/delete as opposed to just instantiating the
classes and letting them go out of scope.  I'm more concerned with any
pitfalls this may cause in using the libraries, threading issues, and
the like.  The get/delete methods do implement a counter and I'm
intending to go back and pthread_mutex them for thread safety.  But
before I spend much more effort on this I'd like to know if I'm heading
down a dangerous path.

Thank you everyone for all your help these past couple of days.

-will 

-----Original Message-----
From: Will Sappington [mailto:wsappington@ndma.us] 
Sent: Wednesday, February 14, 2007 6:10 PM
To: xalan-c-users@xml.apache.org
Subject: RE: Problem evaluating XPath expressions

Dave, thank you very much for taking the time to do this.  I followed up
my post below with another one later last night about an idea I hit upon
that is essentially what you are saying below.  I'm using a static
member function, getInstance() that initializes the X libraries only on
the first call and then instantiates a Profile class with 'new' and
returns a pointer to the instance.  As with your method below, the X
library initialization occurs before the parserLiaison constructs as
member data and everyone is happy.  It appears to be working fine.  I'll
read your suggestions below more thoroughly for things I could do to
improve my implementation.

Thanks again for all your help,

-will

-----Original Message-----
From: David Bertoni [mailto:dbertoni@apache.org] 
Sent: Wednesday, February 14, 2007 4:28 PM
To: xalan-c-users@xml.apache.org
Subject: Re: Problem evaluating XPath expressions

Will Sappington wrote:
<snip>

Dave Bertoni wrote:

If you're going to do Xerces-C and Xalan-C initialization in the 
constructor of your class, you'll need to create a simple class that 
initializes Xerces-C and Xalan-C in the right order, and make that class
a 
member of your class, ensuring that it appears before any other Xerces-C
or 
Xalan-C class in the class definition.  Here's an example, in
pseudo-code:

class XercesXalanInit
{
public:

     XercesXalanInit()
     {
         if (++s_initCount == 1)
         {
             PlatformUtils::Initialize();
             XalanTransformer::initialize();
         }
     }

     ~XercesXalanInit()
     {
         if (--s_initCount == 0)
         {
             XalanTransformer::terminate();
             PlatformUtils::Terminate();
         }
     }

     static unsigned long   s_initCount;
};

XercesXalanInit::s_initCount = 0;

class myClass
{
public:

     myClass() :
         m_init(),
         m_liason()
     {
     }

     // all my public member functions here...

private:

     XercesXalanInit    m_init;

     XalanSourceTreeParserLiaison   m_liason;
};


Ultimately, it's much better if you initialize Xerces-C and Xalan-C
_once_, 
when your application starts, and not when each instance is created.
Also, 
you'll notice that I put some counting in the XercesXalanInit init
class, 
because you should only call them each once.  Finally, if your
application 
will be multi-threaded, you will either need to initialize the libraries

once, before any threads start, or make the counting in XercesXalanInit 
thread-safe.

Dave

RE: Problem evaluating XPath expressions

Posted by Will Sappington <ws...@ndma.us>.
Dave, thank you very much for taking the time to do this.  I followed up
my post below with another one later last night about an idea I hit upon
that is essentially what you are saying below.  I'm using a static
member function, getInstance() that initializes the X libraries only on
the first call and then instantiates a Profile class with 'new' and
returns a pointer to the instance.  As with your method below, the X
library initialization occurs before the parserLiaison constructs as
member data and everyone is happy.  It appears to be working fine.  I'll
read your suggestions below more thoroughly for things I could do to
improve my implementation.

Thanks again for all your help,

-will

-----Original Message-----
From: David Bertoni [mailto:dbertoni@apache.org] 
Sent: Wednesday, February 14, 2007 4:28 PM
To: xalan-c-users@xml.apache.org
Subject: Re: Problem evaluating XPath expressions

Will Sappington wrote:
> Hi Dave,
> 
> I think I may have hit a dead end with this.  When I define 
> XalanSourceTreeParserLiaison _parserLiaison; as member data, the
program
> crashes with an assertion during construction of the Profile class.
The
> first line of the constructor doesn't even execute so the assertion is
> occurring in the construction of the member classes.  I stepped into
it
> and found that it occurs during construction of the parserLiaison when
> it calls XalanMemMgrs::getDefaultXercesMemMgr() which is what
> XALAN_DEFAULT_MEMMGR is #defined as.  After that call there is an
assert
> (ptr != 0) and that is where the crash occurs.  I'm assuming this is
> because neither of the ::initialize() methods have been called.  Of
> course there's no opportunity to do so prior to member data
construction
> so it would appear I'm screwed.  Is there a way to instantiate a
memory
> manager such that the getDefaultXercesMemMgr() call would be able to
> find it?

If you're going to do Xerces-C and Xalan-C initialization in the 
constructor of your class, you'll need to create a simple class that 
initializes Xerces-C and Xalan-C in the right order, and make that class
a 
member of your class, ensuring that it appears before any other Xerces-C
or 
Xalan-C class in the class definition.  Here's an example, in
pseudo-code:

class XercesXalanInit
{
public:

     XercesXalanInit()
     {
         if (++s_initCount == 1)
         {
             PlatformUtils::Initialize();
             XalanTransformer::initialize();
         }
     }

     ~XercesXalanInit()
     {
         if (--s_initCount == 0)
         {
             XalanTransformer::terminate();
             PlatformUtils::Terminate();
         }
     }

     static unsigned long   s_initCount;
};

XercesXalanInit::s_initCount = 0;

class myClass
{
public:

     myClass() :
         m_init(),
         m_liason()
     {
     }

     // all my public member functions here...

private:

     XercesXalanInit    m_init;

     XalanSourceTreeParserLiaison   m_liason;
};


Ultimately, it's much better if you initialize Xerces-C and Xalan-C
_once_, 
when your application starts, and not when each instance is created.
Also, 
you'll notice that I put some counting in the XercesXalanInit init
class, 
because you should only call them each once.  Finally, if your
application 
will be multi-threaded, you will either need to initialize the libraries

once, before any threads start, or make the counting in XercesXalanInit 
thread-safe.

Dave

Re: Problem evaluating XPath expressions

Posted by David Bertoni <db...@apache.org>.
Will Sappington wrote:
> Hi Dave,
> 
> I think I may have hit a dead end with this.  When I define 
> XalanSourceTreeParserLiaison _parserLiaison; as member data, the program
> crashes with an assertion during construction of the Profile class.  The
> first line of the constructor doesn't even execute so the assertion is
> occurring in the construction of the member classes.  I stepped into it
> and found that it occurs during construction of the parserLiaison when
> it calls XalanMemMgrs::getDefaultXercesMemMgr() which is what
> XALAN_DEFAULT_MEMMGR is #defined as.  After that call there is an assert
> (ptr != 0) and that is where the crash occurs.  I'm assuming this is
> because neither of the ::initialize() methods have been called.  Of
> course there's no opportunity to do so prior to member data construction
> so it would appear I'm screwed.  Is there a way to instantiate a memory
> manager such that the getDefaultXercesMemMgr() call would be able to
> find it?

If you're going to do Xerces-C and Xalan-C initialization in the 
constructor of your class, you'll need to create a simple class that 
initializes Xerces-C and Xalan-C in the right order, and make that class a 
member of your class, ensuring that it appears before any other Xerces-C or 
Xalan-C class in the class definition.  Here's an example, in pseudo-code:

class XercesXalanInit
{
public:

     XercesXalanInit()
     {
         if (++s_initCount == 1)
         {
             PlatformUtils::Initialize();
             XalanTransformer::initialize();
         }
     }

     ~XercesXalanInit()
     {
         if (--s_initCount == 0)
         {
             XalanTransformer::terminate();
             PlatformUtils::Terminate();
         }
     }

     static unsigned long   s_initCount;
};

XercesXalanInit::s_initCount = 0;

class myClass
{
public:

     myClass() :
         m_init(),
         m_liason()
     {
     }

     // all my public member functions here...

private:

     XercesXalanInit    m_init;

     XalanSourceTreeParserLiaison   m_liason;
};


Ultimately, it's much better if you initialize Xerces-C and Xalan-C _once_, 
when your application starts, and not when each instance is created.  Also, 
you'll notice that I put some counting in the XercesXalanInit init class, 
because you should only call them each once.  Finally, if your application 
will be multi-threaded, you will either need to initialize the libraries 
once, before any threads start, or make the counting in XercesXalanInit 
thread-safe.

Dave

RE: Problem evaluating XPath expressions

Posted by Will Sappington <ws...@ndma.us>.
Hi Dave,

I think I may have hit a dead end with this.  When I define 
XalanSourceTreeParserLiaison _parserLiaison; as member data, the program
crashes with an assertion during construction of the Profile class.  The
first line of the constructor doesn't even execute so the assertion is
occurring in the construction of the member classes.  I stepped into it
and found that it occurs during construction of the parserLiaison when
it calls XalanMemMgrs::getDefaultXercesMemMgr() which is what
XALAN_DEFAULT_MEMMGR is #defined as.  After that call there is an assert
(ptr != 0) and that is where the crash occurs.  I'm assuming this is
because neither of the ::initialize() methods have been called.  Of
course there's no opportunity to do so prior to member data construction
so it would appear I'm screwed.  Is there a way to instantiate a memory
manager such that the getDefaultXercesMemMgr() call would be able to
find it?

-will

-----Original Message-----
From: David Bertoni [mailto:dbertoni@apache.org] 
Sent: Tuesday, February 13, 2007 3:01 PM
To: xalan-c-users@xml.apache.org
Subject: Re: Problem evaluating XPath expressions


Member variables are defined in the class definition, but not
initialized 
there.  Initialization occurs in the constructor, in the member 
initialization list.

The reason the constructor that accepts the DOMSupport instance is 
deprecated is because the XalanSourceTreeParserLiaison instance no
longer 
needs the DOMSupport instance.  You can simply use the constructor that 
takes a MemoryManager instance, and use the default.

Dave

RE: Problem evaluating XPath expressions

Posted by Will Sappington <ws...@ndma.us>.
Thanks very much.

Re: member variable initialization - Doh, yeah, I knew that :-).  The
parameterized constructor didn't register with me as an initialization.
Still making my way up the C++ learning curve.

-will

-----Original Message-----
From: David Bertoni [mailto:dbertoni@apache.org] 
Sent: Tuesday, February 13, 2007 3:01 PM
To: xalan-c-users@xml.apache.org
Subject: Re: Problem evaluating XPath expressions

Member variables are defined in the class definition, but not
initialized 
there.  Initialization occurs in the constructor, in the member 
initialization list.

The reason the constructor that accepts the DOMSupport instance is 
deprecated is because the XalanSourceTreeParserLiaison instance no
longer 
needs the DOMSupport instance.  You can simply use the constructor that 
takes a MemoryManager instance, and use the default.

Dave

Re: Problem evaluating XPath expressions

Posted by David Bertoni <db...@apache.org>.
Will Sappington wrote:
> Hi Dave, (sorry for the top-posting but OutHouse doesn't maintain the
> threading on emails very well so bottom-posting doesn't work very well.)
> 
> I just got back to this and I'm having trouble implementing it.  I moved
> the XalanSourceTreeInit and XalanSourceTreeParserLiaison instances to
> the private member data of the class and put the appropriate includes
> and "XALAN_USING_XALAN" statements at the top.  These are the 4
> instances of Xalan member data:
> 
> XalanDocument* _pXmlDoc;        ///< ptr to the Xalan DOM document
> XalanSourceTreeDOMSupport   _DomSupport;
> 
> // Initialize the XalanSourceTree subsystem...
> XalanSourceTreeInit     theSourceTreeInit;
> XalanSourceTreeParserLiaison    theLiaison(_DomSupport);
> 
>   The compiler gives an error on the XalanSourceTreeParserLiaison
> declaration, specifically on the symbol _DomSupport.  I'm not sure why
> this construction works inside as local function data and not as member
> data, but regardless, I looked up the XalanSourceTreeParserLiaison API
> for a different constructor and saw that this form has been deprecated.
> It now suggests the form that takes only a memory manager reference
> (defaulted to XALAN_DEFAULT_MEMMGR).  I looked for a corresponding
> setter to set the DOMSupport instance but couldn't find one.  What am I
> missing here?  Thanks in advance for any help.

Member variables are defined in the class definition, but not initialized 
there.  Initialization occurs in the constructor, in the member 
initialization list.

The reason the constructor that accepts the DOMSupport instance is 
deprecated is because the XalanSourceTreeParserLiaison instance no longer 
needs the DOMSupport instance.  You can simply use the constructor that 
takes a MemoryManager instance, and use the default.

Dave

RE: Problem evaluating XPath expressions

Posted by Will Sappington <ws...@ndma.us>.
Hi Dave, (sorry for the top-posting but OutHouse doesn't maintain the
threading on emails very well so bottom-posting doesn't work very well.)

I just got back to this and I'm having trouble implementing it.  I moved
the XalanSourceTreeInit and XalanSourceTreeParserLiaison instances to
the private member data of the class and put the appropriate includes
and "XALAN_USING_XALAN" statements at the top.  These are the 4
instances of Xalan member data:

XalanDocument* _pXmlDoc;        ///< ptr to the Xalan DOM document
XalanSourceTreeDOMSupport   _DomSupport;

// Initialize the XalanSourceTree subsystem...
XalanSourceTreeInit     theSourceTreeInit;
XalanSourceTreeParserLiaison    theLiaison(_DomSupport);

  The compiler gives an error on the XalanSourceTreeParserLiaison
declaration, specifically on the symbol _DomSupport.  I'm not sure why
this construction works inside as local function data and not as member
data, but regardless, I looked up the XalanSourceTreeParserLiaison API
for a different constructor and saw that this form has been deprecated.
It now suggests the form that takes only a memory manager reference
(defaulted to XALAN_DEFAULT_MEMMGR).  I looked for a corresponding
setter to set the DOMSupport instance but couldn't find one.  What am I
missing here?  Thanks in advance for any help.

-will

-----Original Message-----
From: David Bertoni [mailto:dbertoni@apache.org] 
Sent: Monday, February 12, 2007 1:50 AM
To: xalan-c-users@xml.apache.org
Subject: Re: Problem evaluating XPath expressions

Will Sappington wrote:
> Hello all,
> 
>  
> 
> I'm writing a configuration utility that we call an "application 
> profile" or simply profile, that is essentially an ini file on 
> steroids.  It's a hierarchical structure - application/section/item - 
> that allows multiple applications to use a single profile.  I'm 
> migrating it from "key = value" format to XML and I'm using
Xalan/Xerces 
> for evaluating XPath expressions to retrieve the configuration items.
>

...

> 
> XalanDocumentPrefixResolver     thePrefixResolver(_pXmlDoc);
> 
>  
> 
> where _pXmlDoc is in the Profile class private member data
>

 From looking at your code, I suspect the _pXmlDoc data member is
pointing 
to an instance that's already been destroyed.

Here's what the comments for XMLParserLiason::parseXMLStream() say:

/**
  * Parse the text pointed at by the reader as XML, and return a DOM
  * Document interface.  It is recommended that you pass in some sort of
  * recognizable name, such as the filename or URI, with which the
reader
  * can be recognized if the parse fails.
  *
  * The liaison owns the XalanDocument instance, and will delete it when
  * when asked (see DestroyDocument()), or when the liaison is reset, or
  * goes out of scope.
  */

So, the instance you created is destroyed when the 
XalanSourceTreeParserLiaison instance is destroyed in
Profile::_openXmlDoc().

In general, Xalan-C implements very tightly controlled ownership of 
objects.  The easiest way for you to handle this is to make the 
XalanSourceTreeParserLiason instance a member of your class.

Dave


Re: Problem evaluating XPath expressions

Posted by David Bertoni <db...@apache.org>.
Will Sappington wrote:
> Hello all,
> 
>  
> 
> I’m writing a configuration utility that we call an “application 
> profile” or simply profile, that is essentially an ini file on 
> steroids.  It’s a hierarchical structure – application/section/item – 
> that allows multiple applications to use a single profile.  I’m 
> migrating it from “key = value” format to XML and I’m using Xalan/Xerces 
> for evaluating XPath expressions to retrieve the configuration items.
>

...

> 
> XalanDocumentPrefixResolver     thePrefixResolver(_pXmlDoc);
> 
>  
> 
> where _pXmlDoc is in the Profile class private member data
>

 From looking at your code, I suspect the _pXmlDoc data member is pointing 
to an instance that's already been destroyed.

Here's what the comments for XMLParserLiason::parseXMLStream() say:

/**
  * Parse the text pointed at by the reader as XML, and return a DOM
  * Document interface.  It is recommended that you pass in some sort of
  * recognizable name, such as the filename or URI, with which the reader
  * can be recognized if the parse fails.
  *
  * The liaison owns the XalanDocument instance, and will delete it when
  * when asked (see DestroyDocument()), or when the liaison is reset, or
  * goes out of scope.
  */

So, the instance you created is destroyed when the 
XalanSourceTreeParserLiaison instance is destroyed in Profile::_openXmlDoc().

In general, Xalan-C implements very tightly controlled ownership of 
objects.  The easiest way for you to handle this is to make the 
XalanSourceTreeParserLiason instance a member of your class.

Dave