From: Larry Lindstrom on 19 Oct 2009 06:55 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 20 Oct 2009 12:43 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 21 Oct 2009 01:48 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 21 Oct 2009 02:24 "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 21 Oct 2009 06:37 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
|
Next
|
Last
Pages: 1 2 Prev: XSLT messages with DOM smart pointers in C++ Next: Question about win32 C++ roles |