From: Larry Lindstrom on
Hi Folks:

I'm trying to put together, or find something someone has put
togeter, that will behave the way XPath is defined to behave.

I've attempted to write a utility based on the code presented here:

http://msdn.microsoft.com/en-us/library/ms754523%28VS.85%29.aspx

My utility runs, and will parse XML if the expression starts at the
document's root, with or without a leading "/".

Relative expressions, starting with the name of a node that isn't
the root, always return a list of zero length.

Expressions of attributes always fail.

I've attempted to build this example, but was presented with a
bunch of compiler errors.

I then attempted to transpose the original sample code from MSXML3
to MSXM6.

I was unable to get the original code through the compiler,
probably because I'm not experienced with COM or XML. So I transposed
the sample into something that would compile.

The resulting code, as close to the original sample as I can make
it, fails for the same expressions as the utility I built.

Can somebody take a look at this, or the original sample, and tell
me why this code fails, or if the original code fails to parse
relative expressions or attributes.

Or if I'm not building the XML or expressions properly.

Thanks
Larry

#include <stdio.h>
#include <iostream>

using namespace std;

#include <comutil.h> // For _bstr_t
#include <msxml6.h>
#include <winnls.h>
#import <msxml6.dll>
const int UTF8_CODEPAGE = 65001;

typedef __int64 int64_t;
#define DIM(a) (sizeof(a) / sizeof(a[0]))

// Forward declarations for functions defined below main:
string *compose_xml(string *xml_string_ptr);
wstring *multi_to_wide(const char *text, wstring *wide_string_ptr);
inline char *itoa_s(int value, char *conversion_buffer,
int conversion_buffer_size, int
radix);

int main(int argc, char* argv[])
{
// const char *expression = "email/record_key"; // Works
// const char *expression = "record_key/test_element"; // Returns
list of zero length.
// const char *expression = "record_key"; // Returns list of zero
length.
// const char *expression = "/email/record_key/
test_element(a)attribute1"; // selectNodes() fails.
const char *expression = "test_element(a)attribute1"; // selectNodes()
fails.
BSTR xml_bstr;
BSTR property_name_bstr;
BSTR property_value_bstr;
BSTR expression_bstr;
wstring wide_string_buffer;
VARIANT property_name_variant;
IXMLDOMElement *pXMLDocElement = NULL;
IXMLDOMNodeList *pXMLDomNodeList = NULL;
long count = 0L;

CoInitialize(NULL);

VARIANT_BOOL is_successful; // Required by IXMLDOMDocument2::load().
// try{
// IXMLDOMDocument2Ptr pXMLDoc = NULL;
IXMLDOMDocument2 *pXMLDoc = NULL;
string xml;

HRESULT hr = CoCreateInstance(CLSID_DOMDocument60,
NULL,
CLSCTX_INPROC_SERVER,
IID_IXMLDOMDocument2,
(void**)&pXMLDoc);

// Compose the sample XML file
compose_xml(&xml);

printf("Expression %s.\n\n", expression);
printf("XML:\n%s\n", xml.c_str());

multi_to_wide(xml.c_str(), &wide_string_buffer);

xml_bstr = SysAllocString(wide_string_buffer.c_str());
hr = pXMLDoc->loadXML(xml_bstr, &is_successful);

// If document does not load report the parse error
// if(hr!=VARIANT_TRUE) // This returns true (error) when hr ==
S_OK
if(hr!=S_OK)
{
return 0;
}
// Otherwise, build node list using SelectNodes
// and returns its length as console output
else
{
multi_to_wide("SelectionLanguage", &wide_string_buffer);
property_name_bstr = SysAllocString(wide_string_buffer.c_str());
property_name_variant.vt = VT_BSTR;
multi_to_wide("XPath", &wide_string_buffer);
property_value_bstr = SysAllocString(wide_string_buffer.c_str
());
property_name_variant.bstrVal = property_value_bstr;
hr = pXMLDoc->setProperty(property_name_bstr,
property_name_variant);
multi_to_wide("SelectionNamespaces", &wide_string_buffer);
property_name_bstr = SysAllocString(wide_string_buffer.c_str());
property_name_variant.vt = VT_BSTR;
multi_to_wide("xmlns:xsl='http://www.w3.org/1999/XSL/
Transform'", &wide_string_buffer);
property_value_bstr = SysAllocString(wide_string_buffer.c_str
());
property_name_variant.bstrVal = property_value_bstr;
hr = pXMLDoc->setProperty(property_name_bstr,
property_name_variant);

pXMLDoc->get_documentElement(&pXMLDocElement);
// IXMLDOMNodeListPtr pXMLDomNodeList = NULL;
// pXMLDomNodeList = pXMLDocElement->selectNodes("//
xsl:template");
multi_to_wide(expression, &wide_string_buffer);
expression_bstr = SysAllocString(wide_string_buffer.c_str());
hr = pXMLDoc->selectNodes(expression_bstr, &pXMLDomNodeList);
if(hr == S_OK)
{
count = 0;
hr = pXMLDomNodeList->get_length(&count);
printf("The number of <xsl:template> nodes is %i.\n", count);
}
else
{
printf("selectNodes() failed\n", count);
}
}
return 0;
}

string *compose_xml(string *xml_string_ptr)
{
int email_record_type = 1;
int donation_record_key = 100;
char conversion_buffer[50];

*xml_string_ptr = "<email>\n";
*xml_string_ptr += " <record_type>\n ";
*xml_string_ptr += itoa_s(int(email_record_type),
conversion_buffer, DIM(conversion_buffer), 10);
*xml_string_ptr += "\n </record_type>\n";
*xml_string_ptr += " <record_key>\n ";
*xml_string_ptr += itoa_s(donation_record_key, conversion_buffer,
DIM(conversion_buffer), 10);
// #ifdef _DEBUG
*xml_string_ptr += "\n <test_element attribute1=\"this is
first element's first attribute\">\n ";
*xml_string_ptr += itoa_s(donation_record_key + 1,
conversion_buffer, DIM(conversion_buffer), 10);
*xml_string_ptr += "\n </test_element>";
*xml_string_ptr += "\n <test_element attribute1=\"this is
second element's first attribute\">\n ";
*xml_string_ptr += itoa_s(donation_record_key + 2,
conversion_buffer, DIM(conversion_buffer), 10);
*xml_string_ptr += "\n </test_element>\n";
*xml_string_ptr += " </record_key>\n";
*xml_string_ptr += " <record_key>\n ";
*xml_string_ptr += "Another record key";
*xml_string_ptr += "\n <test_element attribute1=\"this is
third element's first attribute\">\n ";
*xml_string_ptr += itoa_s(donation_record_key + 3,
conversion_buffer, DIM(conversion_buffer), 10);
*xml_string_ptr += "\n </test_element>";
*xml_string_ptr += "\n <test_element attribute1=\"this is
fourth element's first attribute\">\n ";
*xml_string_ptr += "Last test element";
*xml_string_ptr += "\n </test_element>";
// #endif
*xml_string_ptr += "\n </record_key>\n";
*xml_string_ptr += "</email>\n";

return xml_string_ptr;
}

wstring *multi_to_wide(const char *text, wstring *wide_string_ptr)
{
int wide_char_count = 0;

if(text == NULL)
{
if(wide_string_ptr != NULL)
{
wide_string_ptr->erase();
}
}
else
{
int wide_buffer_size = strlen(text) + 1;
WCHAR *wide_buffer = new WCHAR[wide_buffer_size];

wide_char_count =
MultiByteToWideChar(UTF8_CODEPAGE, 0, text, -1,
wide_buffer, wide_buffer_size);

if(wide_string_ptr != NULL)
{
*wide_string_ptr = wide_buffer;
}

delete []wide_buffer;
}

return wide_string_ptr;
}

inline char *itoa_s(int value, char *conversion_buffer,
int conversion_buffer_size, int
radix)
{
errno_t conversion_return_val = 0;
char *return_val = conversion_buffer;

if((conversion_buffer == NULL) || (conversion_buffer_size <= 0))
{
// Missing conversion buffer, return hard coded blank.
return_val = "";
}
else
{
conversion_return_val =
_itoa_s(value, conversion_buffer,

conversion_buffer_size, radix);

if(conversion_return_val != 0)
{
conversion_buffer[0] = '0';
}
}

return return_val;
}
From: Christian ASTOR on
On 19 oct, 12:55, Larry Lindstrom <larryl_tu...(a)hotmail.com> wrote:

>    I've attempted to build this example, but was presented with a
> bunch of compiler errors.

Do you mean the XpathSelectNodes.cpp sample ?
If so and you get errors like "error C2872: 'IXMLDOMParseErrorPtr' :
ambiguous symbol", you must replace by MSXML2::IXMLDOMParseErrorPtr to
compile it...
From: Friedel Jantzen on
Am Tue, 20 Oct 2009 09:43:50 -0700 (PDT) schrieb Christian ASTOR:

> On 19 oct, 12:55, Larry Lindstrom <larryl_tu...(a)hotmail.com> wrote:
>
>> � �I've attempted to build this example, but was presented with a
>> bunch of compiler errors.
>
> Do you mean the XpathSelectNodes.cpp sample ?
> If so and you get errors like "error C2872: 'IXMLDOMParseErrorPtr' :
> ambiguous symbol", you must replace by MSXML2::IXMLDOMParseErrorPtr to
> compile it...

Thank you for your reply, Christian.
I am not the OP, but tried to compile this sample, too.
Getting 8 compiler errors, I removed 6 by specifying the namespace MSXML2::
(using CComPtr<> will not work).
Then I was stuck with the remaining error, occuring twice:
'setProperty' is not an element of 'MSXML2::IXMLDOMDocument'
There is no setProperty method.

Regarding Larry's MSXML6 sample:
This compiled, but did not link with the free MSVC 2008 :
Unresolved externals: CLSID_DOMDocument60, IID_IXMLDOMDocument2

Friedel
From: Alain on
"Friedel Jantzen" <nospam_plz(a)freenet.de> a �crit dans le message de news:
ti4e7pat8nng$.1mxivpgu5pa14.dlg(a)40tude.net...

> Then I was stuck with the remaining error, occuring twice:
> 'setProperty' is not an element of 'MSXML2::IXMLDOMDocument'
> There is no setProperty method.

It should be IXMLDOMDocument2
If you check the generated msxml3.tlh file, it would be strange that there
is no setProperty method for IXMLDOMDocument2


From: Larry Lindstrom on
On Oct 20, 10:48 pm, Friedel Jantzen <nospam_...(a)freenet.de> wrote:
> Am Tue, 20 Oct 2009 09:43:50 -0700 (PDT) schrieb Christian ASTOR:
>
> > On 19 oct, 12:55, Larry Lindstrom <larryl_tu...(a)hotmail.com> wrote:
>
> >>    I've attempted to build this example, but was presented with a
> >> bunch of compiler errors.
>
> > Do you mean the XpathSelectNodes.cpp sample ?
> > If so and you get errors like "error C2872: 'IXMLDOMParseErrorPtr' :
> > ambiguous symbol", you must replace by MSXML2::IXMLDOMParseErrorPtr to
> > compile it...
>
> Thank you for your reply, Christian.
> I am not the OP, but tried to compile this sample, too.
> Getting 8 compiler errors, I removed 6 by specifying the namespace MSXML2::
> (using CComPtr<> will not work).
> Then I was stuck with the remaining error, occuring twice:
>  'setProperty' is not an element of 'MSXML2::IXMLDOMDocument'
> There is no setProperty method.
>
> Regarding Larry's MSXML6 sample:
> This compiled, but did not link with the free MSVC 2008 :
> Unresolved externals:  CLSID_DOMDocument60, IID_IXMLDOMDocument2
>
> Friedel

Thanks Everybody:

Friedel, this is what a couple of windows my project configuration
look like:

Linker - General
Additional Library Directories:
C:\Program Files\Microsoft SDKs\Windows\v6.0A\Lib

Linker - Input
Additional Dependancies:
msxml6.lib

I'd only built the debug code. When I attempted a release build, I
had the same unresolved externals you had. When I applied these two
changes to the release configuration, the build succeeded.

MSXLM's documentation recommends using MSXLM 6.0 for new
applications, so I think I'm justified in attempting the conversion.
However, I'm new to XML and I'm just copying the SelectionLanguage and
SelectionNamespaces property values without really understanding their
contents.

I do appreciate the posts.

Larry