Failed to compile gsoap-generated server code with C++ Builder - c++

I am trying to build a server application using gsoap 2.8.17. I've created a header file with service function prototype and a result record definition
testserver.h:
#ifndef TESTSERVER_H
#define TESTSERVER_H
#include <string>
//gsoap ns service name: TestServer
//gsoap ns service namespace: http://mycomp:8080/TestServer.wsdl
//gsoap ns service location: http://mycomp:8080/TestServer.cgi
//gsoap ns schema namespace: urn:TestServer
class Record
{
public:
int id;
std::string name;
std::string address;
double param1;
};
int ns__GetRecord(int id, Record* result);
#endif
Then I've invoked the gSOAP RPC compiler:
soapcpp2.exe testserver.h
The compiler produced the following files:
soapC.cpp
soapClient.cpp
soapClientLib.cpp
soapServer.cpp
soapServerLib.cpp
soapH.h
soapStub.h
TestServer.h
TestServer.nsmap
TestServer.wsdl
TestServer.GetRecord.req.xml
TestServer.GetRecord.res.xml
ns.xsd
TestServer.wsdl
<?xml version="1.0" encoding="UTF-8"?>
<definitions name="TestServer"
targetNamespace="http://mycomp:8080/TestServer.wsdl"
xmlns:tns="http://mycomp:8080/TestServer.wsdl"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:ns="urn:TestServer"
xmlns:SOAP="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:HTTP="http://schemas.xmlsoap.org/wsdl/http/"
xmlns:MIME="http://schemas.xmlsoap.org/wsdl/mime/"
xmlns:DIME="http://schemas.xmlsoap.org/ws/2002/04/dime/wsdl/"
xmlns:WSDL="http://schemas.xmlsoap.org/wsdl/"
xmlns="http://schemas.xmlsoap.org/wsdl/">
<types>
<schema targetNamespace="urn:TestServer"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:ns="urn:TestServer"
xmlns="http://www.w3.org/2001/XMLSchema"
elementFormDefault="unqualified"
attributeFormDefault="unqualified">
<import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
<complexType name="Record"><!-- Record -->
<sequence>
<element name="id" type="xsd:int" minOccurs="1" maxOccurs="1"/><!-- Record::id -->
<element name="name" type="xsd:string" minOccurs="1" maxOccurs="1"/><!-- Record::name -->
<element name="address" type="xsd:string" minOccurs="1" maxOccurs="1"/><!-- Record::address -->
<element name="param1" type="xsd:double" minOccurs="1" maxOccurs="1"/><!-- Record::param1 -->
</sequence>
</complexType>
<!-- operation request element -->
<element name="GetRecord">
<complexType>
<sequence>
<element name="id" type="xsd:int" minOccurs="1" maxOccurs="1"/><!-- ns__GetRecord::id -->
</sequence>
</complexType>
</element>
<!-- operation response element -->
<element name="GetRecordResponse">
<complexType>
<sequence>
<element name="result" type="ns:Record" minOccurs="0" maxOccurs="1" nillable="true"/><!-- ns__GetRecord::result -->
</sequence>
</complexType>
</element>
</schema>
</types>
<message name="GetRecordRequest">
<part name="Body" element="ns:GetRecord"/><!-- ns__GetRecord::ns__GetRecord -->
</message>
<message name="GetRecordResponse">
<part name="Body" element="ns:GetRecordResponse"/>
</message>
<portType name="TestServerPortType">
<operation name="GetRecord">
<documentation>Service definition of function ns__GetRecord</documentation>
<input message="tns:GetRecordRequest"/>
<output message="tns:GetRecordResponse"/>
</operation>
</portType>
<binding name="TestServer" type="tns:TestServerPortType">
<SOAP:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="GetRecord">
<SOAP:operation soapAction=""/>
<input>
<SOAP:body parts="Body" use="literal"/>
</input>
<output>
<SOAP:body parts="Body" use="literal"/>
</output>
</operation>
</binding>
<service name="TestServer">
<documentation>gSOAP 2.8.17 generated service definition</documentation>
<port name="TestServer" binding="tns:TestServer">
<SOAP:address location="http://mycomp:8080/TestServer.cgi"/>
</port>
</service>
</definitions>
As documentation recommends I added soapServerLib.cpp to my project, but the C++ Builder 2010 compiler produces errors:
[BCC32 Error] soapC.cpp(1611): E2238 Multiple declaration for 'ns__GetRecord(soap *,int,Record *)'
[BCC32 Error] soapStub.h(224): E2344 Earlier declaration of 'ns__GetRecord(soap *,int,Record *)'
[BCC32 Error] soapC.cpp(1611): E2303 Type name expected
[BCC32 Error] soapC.cpp(1611): E2379 Statement missing ;
[BCC32 Error] soapC.cpp(1717): E2379 Statement missing ;
soapStub.h(224):
SOAP_FMAC5 int SOAP_FMAC6 ns__GetRecord(struct soap*, int id, Record *result);
soapC.cpp(1598-1619):
SOAP_FMAC1 struct ns__GetRecord * SOAP_FMAC2 soap_instantiate_ns__GetRecord(struct soap *soap, int n, const char *type, const char *arrayType, size_t *size)
{
(void)type; (void)arrayType; /* appease -Wall -Werror */
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "soap_instantiate_ns__GetRecord(%d, %s, %s)\n", n, type?type:"", arrayType?arrayType:""));
struct soap_clist *cp = soap_link(soap, NULL, SOAP_TYPE_ns__GetRecord, n, soap_fdelete);
if (!cp)
return NULL;
if (n < 0)
{ cp->ptr = (void*)SOAP_NEW(struct ns__GetRecord);
if (size)
*size = sizeof(struct ns__GetRecord);
}
else
{ cp->ptr = (void*)SOAP_NEW_ARRAY(struct ns__GetRecord, n); // <<<-- error here
if (size)
*size = n * sizeof(struct ns__GetRecord);
}
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Instantiated location=%p\n", cp->ptr));
if (!cp->ptr)
soap->error = SOAP_EOM;
return (struct ns__GetRecord*)cp->ptr;
}
Why is ns__GetRecord interpreted as a structure while it's a function name? What should I fix in my TestServer.h to make soapcpp2.exe produce a compilable code ?

The only solution I found is to remove the soap_instantiate_ns__GetRecord function body.
SOAP_FMAC1 struct ns__GetRecord * SOAP_FMAC2 soap_instantiate_ns__GetRecord(struct
soap *soap, int n, const char *type, const char *arrayType, size_t *size)
{
return NULL;
}
Then the server code compiles and works fine.

Related

Zero bytes sent back to client from IIS using ISAPI extension

I'm trying to write a pro-forma ISAPI extension in an attempt to better understand IIS. I have the following code for the exension:
#include <httpext.h>
#include <cstring>
#include <cstdio>
#include <fstream>
#include <iostream>
#include <windows.h>
BOOL WINAPI GetExtensionVersion(HSE_VERSION_INFO * versionInfo)
{
versionInfo->dwExtensionVersion = HSE_VERSION;
strcpy_s( versionInfo->lpszExtensionDesc, "ISAPIExtension.dll");
return TRUE;
}
DWORD WINAPI HttpExtensionProc(EXTENSION_CONTROL_BLOCK* ecb)
{
char * msg = "<html><head/><body>Hello world</body></html>";
DWORD msg_length = strlen(msg) * sizeof(char);
DWORD sent_length = msg_length;
std::cout << sent_length;
auto result = ecb->WriteClient(ecb->ConnID, msg, &sent_length, 0);
if (!result || sent_length != msg_length)
{
std::fstream output("errors.txt");
output << "Could not write to client. Last error was " << GetLastError();
output.flush();
output.close();
return HSE_STATUS_ERROR;
}
std::cout << sent_length;
return HSE_STATUS_SUCCESS;
}
IIS Express responds with HTTP 200, but zero bytes were sent back to the client. Is anything in the above wrong? For reference, this is my applicationhost.config:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<configSections>
<sectionGroup name="system.applicationHost">
<section name="applicationPools"/>
<section name="sites"/>
</sectionGroup>
<sectionGroup name="system.webServer">
<section name="globalModules"/>
<section name="handlers"/>
<section name="caching"/>
<section name="modules"/>
<section name="staticContent"/>
<section name="httpErrors"/>
<sectionGroup name="tracing">
<section name="traceFailedRequests" overrideModeDefault="Allow" />
<section name="traceProviderDefinitions" overrideModeDefault="Deny" />
</sectionGroup>
<!-- The following section elements are not specified in this file, but without these
declarations, IIS will 500 requests -->
<sectionGroup name="security">
<section name="isapiCgiRestriction"/>
<section name="access"/>
<sectionGroup name="authentication">
<section name="anonymousAuthentication"/>
</sectionGroup>
</sectionGroup>
<section name="serverRuntime"/>
</sectionGroup>
</configSections>
<system.applicationHost>
<applicationPools>
<add name="UnmanagedClassicAppPool" managedRuntimeVersion="" managedPipelineMode="Classic" autoStart="true" />
</applicationPools>
<sites>
<site name="Default Web Site" id="1" serverAutoStart="true">
<application path="/" applicationPool="UnmanagedClassicAppPool">
<virtualDirectory path="/" physicalPath="%IIS_USER_HOME%\blog" />
</application>
<bindings>
<binding protocol="http" bindingInformation=":8080:localhost" />
</bindings>
<traceFailedRequestsLogging directory="%IIS_USER_HOME%\TraceLogFiles" enabled="true" maxLogFileSizeKB="1024" />
</site>
</sites>
</system.applicationHost>
<system.webServer>
<security>
<isapiCgiRestriction notListedIsapisAllowed="true"/>
</security>
<globalModules>
<add name="StaticFileModule" image="%IIS_BIN%\static.dll" />
<add name="AnonymousAuthenticationModule" image="%IIS_BIN%\authanon.dll" />
<add name="IsapiModule" image="%IIS_BIN%\isapi.dll" />
<add name="FailedRequestsTracingModule" image="%IIS_BIN%\iisfreb.dll" />
</globalModules>
<staticContent>
<mimeMap fileExtension=".html" mimeType="text/html" />
</staticContent>
<modules>
<add name="StaticFileModule"/>
<add name="AnonymousAuthenticationModule"/>
<add name="IsapiModule"/>
<add name="FailedRequestsTracingModule"/>
</modules>
<handlers accessPolicy="Read, Execute, Script">
<add name="ISAPI-dll" path="*.dll" verb="*" modules="IsapiModule" resourceType="File" requireAccess="Execute" allowPathInfo="true" />
<add name="StaticFile" path="*.html" verb="*" modules="StaticFileModule" resourceType="Either" requireAccess="Read" />
</handlers>
<tracing>
<traceProviderDefinitions>
<add name="ISAPI Extension" guid="{a1c2040e-8840-4c31-ba11-9871031a19ea}">
<areas>
<clear />
</areas>
</add>
</traceProviderDefinitions>
<traceFailedRequests>
<add path="*">
<traceAreas>
<add provider="ISAPI Extension" verbosity="Verbose" />
</traceAreas>
<failureDefinitions statusCodes="200-999" />
</add>
</traceFailedRequests>
</tracing>
</system.webServer>
</configuration>
Adding a Content-Type header fixes the issue:
DWORD WINAPI HttpExtensionProc(EXTENSION_CONTROL_BLOCK* ecb)
{
char msg [] = "<html><head/><body>Hello world</body></html>";
DWORD msg_length = strlen(msg);
DWORD sent_length = msg_length;
HSE_SEND_HEADER_EX_INFO HeaderExInfo;
HeaderExInfo.pszStatus = "200 OK";
HeaderExInfo.pszHeader = "Content-type: text/html\r\n\r\n";
HeaderExInfo.cchStatus = strlen(HeaderExInfo.pszStatus);
HeaderExInfo.cchHeader = strlen(HeaderExInfo.pszHeader);
HeaderExInfo.fKeepConn = FALSE;
ecb->ServerSupportFunction(ecb->ConnID, HSE_REQ_SEND_RESPONSE_HEADER_EX, &HeaderExInfo, NULL, NULL);
auto result = ecb->WriteClient(ecb->ConnID, msg, &sent_length, 0);
if (!result || sent_length != msg_length)
{
return HSE_STATUS_ERROR;
}
return HSE_STATUS_SUCCESS;
}
Microsoft has posted a similar ISAPI extension sample on their GitHub account: https://github.com/Microsoft/Windows-classic-samples/tree/master/Samples/Win7Samples/web/iis/extensions/simple

can anyone create a simple libvirt program which just starts the domain

virConnectCreateXML doest seem to work for me
i created the following program and compiled it but it seems some linking problems or some kind of problem so i get these error
me.cpp: In function ‘int main(int, char**)’:
me.cpp:21:45: error: ‘virConnectCreateXML’ was not declared in this scope
dom = virConnectCreateXML(conn, xmlconfig, 0);
^
me.cpp:24:5: error: return-statement with no value, in function returning ‘int’ [-fpermissive]
return;
^
me.cpp:26:57: error: ‘virDomainName’ was not declared in this scope
fprintf(stderr, "Guest %s has booted", virDomainName(dom));
^
Program:
/* example ex9.c */
/* compile with: gcc -g -Wall ex9.c -o ex9 -lvirt */
#include <stdio.h>
#include <stdlib.h>
#include <libvirt/libvirt.h>
int main(int argc,char *argv[]){virConnectPtr conn;
char *host;
conn = virConnectOpen("qemu:///system");
if (conn == NULL) {
fprintf(stderr, "Failed to open connection to qemu:///system\n");
return 1;
}
virDomainPtr dom;
const char *xmlconfig = "<domain type='kvm'>
<name>win7</name>
<uuid>3666e50e-c616-42eb-aec8-b7fb1ad5f8f9</uuid>
<memory unit='KiB'>2072576</memory>
<currentMemory unit='KiB'>2072576</currentMemory>
<vcpu placement='static'>2</vcpu>
<os>
<type arch='x86_64' machine='pc-i440fx-2.5'>hvm</type>
<boot dev='hd'/>
</os>
<features>
<acpi/>
<apic/>
<hyperv>
<relaxed state='on'/>
<vapic state='on'/>
<spinlocks state='on' retries='8191'/>
</hyperv>
<vmport state='off'/>
</features>
<cpu mode='host-model'>
<model fallback='allow'/>
</cpu>
<clock offset='localtime'>
<timer name='rtc' tickpolicy='catchup'/>
<timer name='pit' tickpolicy='delay'/>
<timer name='hpet' present='no'/>
<timer name='hypervclock' present='yes'/>
</clock>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>restart</on_crash>
<pm>
<suspend-to-mem enabled='no'/>
<suspend-to-disk enabled='no'/>
</pm>
<devices>
<emulator>/usr/sbin/qemu-system-x86_64</emulator>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='/var/lib/libvirt/images/win7.qcow2'/>
<target dev='hda' bus='ide'/>
<address type='drive' controller='0' bus='0' target='0' unit='0'/>
</disk>
<disk type='file' device='cdrom'>
<driver name='qemu' type='raw'/>
<source file='/home/dravigon/win7.iso'/>
<target dev='hdb' bus='ide'/>
<readonly/>
<address type='drive' controller='0' bus='0' target='0' unit='1'/>
</disk>
<controller type='usb' index='0' model='ich9-ehci1'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x7'/>
</controller>
<controller type='usb' index='0' model='ich9-uhci1'>
<master startport='0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0' multifunction='on'/>
</controller>
<controller type='usb' index='0' model='ich9-uhci2'>
<master startport='2'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x1'/>
</controller>
<controller type='usb' index='0' model='ich9-uhci3'>
<master startport='4'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x2'/>
</controller>
<controller type='pci' index='0' model='pci-root'/>
<controller type='ide' index='0'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
</controller>
<controller type='virtio-serial' index='0'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
</controller>
<interface type='direct'>
<mac address='52:54:00:56:27:95'/>
<source dev='enp3s0' mode='bridge'/>
<model type='rtl8139'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</interface>
<serial type='pty'>
<target port='0'/>
</serial>
<console type='pty'>
<target type='serial' port='0'/>
</console>
<channel type='spicevmc'>
<target type='virtio' name='com.redhat.spice.0'/>
<address type='virtio-serial' controller='0' bus='0' port='1'/>
</channel>
<input type='tablet' bus='usb'/>
<input type='mouse' bus='ps2'/>
<input type='keyboard' bus='ps2'/>
<graphics type='spice' autoport='yes'>
<image compression='off'/>
</graphics>
<sound model='ich6'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
</sound>
<video>
<model type='vga' vram='16384' heads='1'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
</video>
<redirdev bus='usb' type='spicevmc'>
</redirdev>
<redirdev bus='usb' type='spicevmc'>
</redirdev>
<memballoon model='virtio'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
</memballoon>
</devices>
</domain>";
dom = virConnectCreateXML(conn, xmlconfig, 0);
if (!dom) {
fprintf(stderr, "Domain creation failed");
return;
}
fprintf(stderr, "Guest %s has booted", virDomainName(dom));
virDomainFree(dom);
virConnectClose(conn);
return 0;
}
help is thanked in advance
yeah found out the problem the functions
virConnectCreateXML
and its relaced by virDomainCreateXML function

How to read xsd file where root element is not a named type

I have an XML and XSD file. I can read the XML using Xerces if XSD file has the root XML element define as a named complexType but I am trying to figure out how to read the file if root item in XSD is not named type. Here are my files:
The XML file
<?xml version="1.0"?>
<x:books xmlns:x="urn:BookStore"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:BookStore books.xsd">
<book id="bk001">
<author>Writer</author>
<title>The First Book</title>
<genre>Fiction</genre>
<price>44.95</price>
<pub_date>2000-10-01</pub_date>
<review>An amazing story of nothing.</review>
</book>
<book id="bk002">
<author>Poet</author>
<title>The Poet's First Poem</title>
<genre>Poem</genre>
<price>24.95</price>
<pub_date>2001-10-01</pub_date>
<review>Least poetic poems.</review>
</book>
</x:books>
The XSD file:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="urn:BookStore"
xmlns:bks="urn:BookStore">
<xsd:complexType name="BookForm">
<xsd:sequence>
<xsd:element name="author" type="xsd:string"/>
<xsd:element name="title" type="xsd:string"/>
<xsd:element name="genre" type="xsd:string"/>
<xsd:element name="price" type="xsd:float" />
<xsd:element name="pub_date" type="xsd:date" />
<xsd:element name="review" type="xsd:string"/>
</xsd:sequence>
<xsd:attribute name="id" type="xsd:string"/>
</xsd:complexType>
<xsd:element name="books"> <!-- not mapped to named typed! -->
<xsd:complexType >
<xsd:sequence>
<xsd:element name="book"
type="bks:BookForm"
minOccurs="0"
maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
Reading the library (reading only two fields)
#include <iostream>
#include "books.h"
using namespace std;
using namespace BookStore;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
try {
// what do I do here since BooksForm is not defined now and XSD file
// doesn't map it to the root element of XML?
auto_ptr<BooksForm> bookBank (books( "books.xml" ));
for (BooksForm::book_const_iterator i = (bookBank->book().begin());
i != bookBank->book().end();
++i)
{
cout << "Author is '" << i->author() << "'' " << endl;
cout << "Title is '" << i->title() << "'' " << endl;
cout << endl;
}
}
catch (const xml_schema::exception& e)
{
cerr << e << endl;
return 1;
}
return a.exec();
}
So this code works if XSD file is in format as in this post but I want to know how can I read the XML if the XSD file is in above format. I need to do this in this small demo so I can resolve the similar situation in another larger and more complex XML file which is a given thing.

Validate XML file against embedded XSD resource with umlauts in C++ / MSXML

I would like to validate an XML file in C++ using the MSXML6 parser and have followed the instructions on http://msdn.microsoft.com/en-us/library/ms762774%28v=vs.85%29.aspx . However, the project I'm working on requires the XSD schema to be embedded in the binary file.
This is the XML file, which should be validated (all files simplified for demonstration purposes):
<?xml version="1.0" encoding="UTF-8"?>
<Document xsi:schemaLocation="urn:test schema.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:test">
<Party>
<Id>1</Id>
<Name>Bob</Name>
<Salary>100.00</Salary>
</Party>
<Party>
<Id>2</Id>
<Name>Alice</Name>
<Salary>200.00</Salary>
</Party>
<Party>
<Id>3</Id>
<Name>Günther</Name>
<Salary>300.00</Salary>
</Party>
</Document>
And here's the XSD schema:
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<xs:schema xmlns="urn:test" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:test" elementFormDefault="qualified">
<xs:simpleType name="NameType">
<xs:restriction base="xs:string">
<xs:pattern value="([A-Za-z0-9ÄÖÜäöü]){1,10}"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="PartyType">
<xs:sequence>
<xs:element name="Id" type="xs:integer"/>
<xs:element name="Name" type="NameType"/>
<xs:element name="Salary" type="xs:decimal"/>
</xs:sequence>
</xs:complexType>
<xs:element name="Document">
<xs:complexType>
<xs:choice minOccurs="1" maxOccurs="9999999">
<xs:element name="Party" type="PartyType"/>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
The above XSD schema is embedded as a Win32 resource in the executable and can be referenced via the identifier "IDR_XSDSCHEMA1" (see comment line with OPTION 1):
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#import <msxml6.dll>
#include "resource.h"
// Macro that calls a COM method returning HRESULT value.
#define CHK_HR(stmt) do { hr=(stmt); if (FAILED(hr)) return bstrResult; } while(0)
//Method for acquiring own handle
HMODULE GetThisDllHandle()
{
MEMORY_BASIC_INFORMATION info;
size_t len = VirtualQueryEx(GetCurrentProcess(), (void*)GetThisDllHandle, &info, sizeof(info));
return len ? (HMODULE)info.AllocationBase : NULL;
}
_bstr_t validateFile(_bstr_t bstrFile)
{
//Schema collection
MSXML2::IXMLDOMSchemaCollectionPtr pXS;
//XML document
MSXML2::IXMLDOMDocument2Ptr pXD;
//XSD document
MSXML2::IXMLDOMDocument2Ptr pXSD;
//Validation object
MSXML2::IXMLDOMParseErrorPtr pErr;
_bstr_t bstrResult = L"";
HRESULT hr = S_OK;
//Load XSD schema from resource
HMODULE handle = GetThisDllHandle();
HRSRC rc = ::FindResource(handle, MAKEINTRESOURCE(IDR_XSDSCHEMA1), L"XSDSCHEMA");
HGLOBAL rcData = ::LoadResource(handle, rc);
LPVOID data = (::LockResource(rcData));
::FreeResource(rcData);
//Load schema stream into document
CHK_HR(pXSD.CreateInstance(__uuidof(MSXML2::DOMDocument60), NULL, CLSCTX_INPROC_SERVER));
if (pXSD->loadXML((LPCSTR)data) != VARIANT_TRUE)
return bstrResult;
// Create a schema cache
CHK_HR(pXS.CreateInstance(__uuidof(MSXML2::XMLSchemaCache60), NULL, CLSCTX_INPROC_SERVER));
//--> OPTION 1: VALIDATING AGAINST EMBEDDED XSD RESOURCE; DOESN'T WORK <--
CHK_HR(pXS->add(L"urn:test", pXSD.GetInterfacePtr()));
//--> OPTION 2: VALIDATING AGAINST PHYSICAL XSD FILE; WORKS FINE <--
//CHK_HR(pXS->add(L"urn:test", L"schema.xsd"));
// Create a DOMDocument and set its properties.
CHK_HR(pXD.CreateInstance(__uuidof(MSXML2::DOMDocument60), NULL, CLSCTX_INPROC_SERVER));
pXD->async = VARIANT_FALSE;
pXD->validateOnParse = VARIANT_TRUE;
pXD->preserveWhiteSpace = VARIANT_TRUE;
//Assign the schema cache to the Document's schema collection
pXD->schemas = pXS.GetInterfacePtr();
//Load XML file
if(pXD->load(bstrFile) != VARIANT_TRUE)
{
pErr = pXD->parseError;
bstrResult = _bstr_t(L"Validation failed on ") + bstrFile +
_bstr_t(L"\n=====================") +
_bstr_t(L"\nReason: ") + _bstr_t(pErr->Getreason()) +
_bstr_t(L"\nSource: ") + _bstr_t(pErr->GetsrcText()) +
_bstr_t(L"\nLine: ") + _bstr_t(pErr->Getline());
}
else
{
bstrResult = _bstr_t(L"Validation succeeded for ") + bstrFile +
_bstr_t(L"\n======================\n") +
_bstr_t(pXD->xml);
}
return bstrResult;
}
int _tmain(int argc, _TCHAR* argv[])
{
HRESULT hr = CoInitialize(NULL);
if(SUCCEEDED(hr))
{
try
{
_bstr_t bstrOutput = validateFile(L"Document.xml");
MessageBox(NULL, bstrOutput, L"schemaCache",MB_OK);
}
catch(_com_error &e)
{
MessageBox(NULL, e.Description(), L"schemaCache",MB_OK);
}
CoUninitialize();
}
return 0;
}
Unfortunately, I have encountered some strange behavior while trying to run the validation routine (OPTION 1 comment). It seems, that the umlauts in the XSD resource aren't properly decoded while being loaded into the stream. This results in a messed up validation reference, as seen in the following result:
However, when the schema file is loaded directly from disk (OPTION 2 comment), the validation routine runs just fine:
I have already tried to convert the loaded stream from Unicode to Multi-Byte and vice versa, however to no avail. Is there something I'm missing here? Or are Win32 resources limited to a specific character set? Thanks for any suggestions.
See comment from WhozCraig: Using MultiByteToWideChar() with CP_UTF8 as an input argument returns a valid Unicode string.

xerces c issue with creating an object from a just serialized object

I'm having an issue where I serialize an object to a string and then create it again from the same string. When I try and create the same object from the string and check the values, the functions aren't returning correctly. It returns the whole XML object as a string.
I looked at the resulting xml and it looks correct. So I'm at a loss as to what to do.
Thanks for any insight into this issue.
An example is below.
#include "XMLHelper.hxx"
void serializeObject(XmlHelper::Object& mess, std::string& result);
int _tmain(int argc, _TCHAR* argv[])
{
XmlHelper::objectType oType(XmlHelper::objectType::Status);
XmlHelper::Object obj(oType);
unsigned long time(134000000);
XmlHelper::Status status(time);
obj.status().set(status);
std::string result;
serializeObject(obj, result);
if (obj.status().present() )
{
std::cout<<"Message is Status"<<std::endl;
}
if (obj.objectType() == "Status" )
{
std::cout<<"Message is Status"<<std::endl;
}
if (obj.objectType() == XmlHelper::objectType::Status )
{
std::cout<<"Message is Status"<<std::endl;
}
XmlHelper::Object otherObj(result);
if (otherObj.status().present() )
{
std::cout<<"Message is Status"<<std::endl;
}
else if (otherObj.objectType() == "ThingA")
{
std::cout<<"Message is ThingA"<<std::endl;
}
else if (otherObj.objectType() == "ThingB")
{
std::cout<<"Message is ThingB"<<std::endl;
}
return 0;
}
void serializeObject(XmlHelper::Object& mess, std::string& result)
{
std::ostringstream buff;
xml_schema::namespace_infomap nsm;
nsm[""].schema = "XMLHelper.xsd";
Object_(buff, mess, nsm, "UTF-8", xml_schema::flags::no_xml_declaration);
result=buff.str();
}
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<!--<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.com/TENAXML">-->
<xsd:complexType name ="Status" >
<xsd:sequence>
<xsd:element name="timeOfUpdate" type="xsd:unsignedLong" minOccurs="1" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name ="ThingA" >
<xsd:sequence>
<xsd:element name="number" type="xsd:unsignedLong" minOccurs="1" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name ="ThingB" >
<xsd:sequence>
<xsd:element name="number" type="xsd:unsignedLong" minOccurs="1" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:simpleType name="objectType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="Status"/>
<xsd:enumeration value="ThingA"/>
<xsd:enumeration value="ThingB"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="Object" >
<xsd:sequence>
<xsd:element name="objectType" type ="objectType" minOccurs="1" maxOccurs="1" />
<xsd:element name ="thingA" type ="ThingA" minOccurs="0" maxOccurs="1"/>
<xsd:element name ="thingB" type ="ThingB" minOccurs="0" maxOccurs="1"/>
<xsd:element name ="status" type ="Status" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType >
<xsd:element name="Object" type="Object" />
</xsd:schema>
Come to find out I was doing the building of the object which parses the XML completely wrong. What seems to be the correct way is the below.
std::istringstream iss (result);
std::auto_ptr<XmlHelper::Object> otherObj(XmlHelper::Object_(iss));
I also didn't have my xsd file in the correct directory.
Hopefully, this helps someone else.