Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
This example reads XML node by node.
ReadXml.cpp
//------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
//------------------------------------------------------------
#ifndef UNICODE
#define UNICODE
#endif
#include <windows.h>
#include <stdio.h>
#include "WebServices.h"
#include "process.h"
#include "string.h"
#pragma comment(lib, "WebServices.lib")
#pragma comment(lib, "Rpcrt4.lib")
// Print out rich error info
void PrintError(HRESULT errorCode, WS_ERROR* error)
{
wprintf(L"Failure: errorCode=0x%lx\n", errorCode);
if (errorCode == E_INVALIDARG || errorCode == WS_E_INVALID_OPERATION)
{
// Correct use of the APIs should never generate these errors
wprintf(L"The error was due to an invalid use of an API. This is likely due to a bug in the program.\n");
DebugBreak();
}
HRESULT hr = NOERROR;
if (error != NULL)
{
ULONG errorCount;
hr = WsGetErrorProperty(error, WS_ERROR_PROPERTY_STRING_COUNT, &errorCount, sizeof(errorCount));
if (FAILED(hr))
{
goto Exit;
}
for (ULONG i = 0; i < errorCount; i++)
{
WS_STRING string;
hr = WsGetErrorString(error, i, &string);
if (FAILED(hr))
{
goto Exit;
}
wprintf(L"%.*s\n", string.length, string.chars);
}
}
Exit:
if (FAILED(hr))
{
wprintf(L"Could not get error string (errorCode=0x%lx)\n", hr);
}
}
void PrintString(const WS_XML_STRING* string)
{
if (string->length == 0)
{
return;
}
WCHAR* chars = NULL;
int charCount = 0;
charCount =
MultiByteToWideChar(
CP_UTF8,
MB_ERR_INVALID_CHARS,
(char*)string->bytes,
string->length, NULL, 0);
if (charCount == 0)
{
printf("<error: MultiByteToWideChar failed>");
goto Exit;
}
chars = (WCHAR*)HeapAlloc(
GetProcessHeap(),
0,
charCount * sizeof(WCHAR));
if (chars == NULL)
{
printf("<error: HeapAlloc failed>");
goto Exit;
}
if (MultiByteToWideChar(
CP_UTF8,
MB_ERR_INVALID_CHARS,
(char*)string->bytes, string->length,
chars, charCount) != charCount)
{
printf("<error: MultiByteToWideChar failed>");
goto Exit;
}
printf("%.*S", charCount, chars);
Exit:
if (chars != NULL)
{
HeapFree(GetProcessHeap(), 0, chars);
}
}
void PrintText(const WS_XML_TEXT* text)
{
switch (text->textType)
{
case WS_XML_TEXT_TYPE_UTF8:
{
const WS_XML_UTF8_TEXT* utf8Text = (const WS_XML_UTF8_TEXT*) text;
printf("WS_XML_TEXT_TYPE_UTF8(value='");
PrintString(&utf8Text->value);
printf("')");
}
break;
case WS_XML_TEXT_TYPE_UTF16:
{
const WS_XML_UTF16_TEXT* utf16Text = (const WS_XML_UTF16_TEXT*) text;
printf("WS_XML_TEXT_TYPE_UTF16(value='%.*S')", utf16Text->byteCount / sizeof(WCHAR), (WCHAR*)utf16Text->bytes);
}
break;
case WS_XML_TEXT_TYPE_BASE64:
{
const WS_XML_BASE64_TEXT* base64Text = (const WS_XML_BASE64_TEXT*) text;
printf("WS_XML_TEXT_TYPE_BASE64(value={ ");
for (ULONG i = 0; i < base64Text->length; i++)
{
printf("%02x", base64Text->bytes[i]);
}
printf(" })");
}
break;
case WS_XML_TEXT_TYPE_BOOL:
{
const WS_XML_BOOL_TEXT* boolText = (const WS_XML_BOOL_TEXT*) text;
printf("WS_XML_TEXT_TYPE_BOOL(value='%s')", boolText->value ? "true" : "false");
}
break;
case WS_XML_TEXT_TYPE_INT32:
{
const WS_XML_INT32_TEXT* int32Text = (const WS_XML_INT32_TEXT*) text;
printf("WS_XML_TEXT_TYPE_INT32(value='%d')", int32Text->value);
}
break;
case WS_XML_TEXT_TYPE_INT64:
{
const WS_XML_INT64_TEXT* int64Text = (const WS_XML_INT64_TEXT*) text;
printf("WS_XML_TEXT_TYPE_INT64(value='%I64d')", int64Text->value);
}
break;
case WS_XML_TEXT_TYPE_UINT64:
{
const WS_XML_UINT64_TEXT* uint64Text = (const WS_XML_UINT64_TEXT*) text;
printf("WS_XML_TEXT_TYPE_UINT64(value='%I64u')", uint64Text->value);
}
break;
case WS_XML_TEXT_TYPE_FLOAT:
{
const WS_XML_FLOAT_TEXT* floatText = (const WS_XML_FLOAT_TEXT*) text;
printf("WS_XML_TEXT_TYPE_FLOAT(value='%f')", floatText->value);
}
break;
case WS_XML_TEXT_TYPE_DOUBLE:
{
const WS_XML_DOUBLE_TEXT* doubleText = (const WS_XML_DOUBLE_TEXT*) text;
printf("WS_XML_TEXT_TYPE_DOUBLE(value='%f')", doubleText->value);
}
break;
case WS_XML_TEXT_TYPE_DECIMAL:
{
const WS_XML_DECIMAL_TEXT* decimalText = (const WS_XML_DECIMAL_TEXT*) text;
const DECIMAL* dec = &decimalText->value;
printf("WS_XML_TEXT_TYPE_DECIMAL(value={%x %x %x, %I64x})", dec->wReserved, dec->signscale, dec->Hi32, dec->Lo64);
}
break;
case WS_XML_TEXT_TYPE_GUID:
{
WS_XML_GUID_TEXT* guidText = (WS_XML_GUID_TEXT*) text;
RPC_WSTR s;
if (UuidToString(&guidText->value, &s) == RPC_S_OK)
{
printf("WS_XML_TEXT_TYPE_GUID(value='%ls')", s);
RpcStringFree(&s);
}
else
{
printf("WS_XML_TEXT_TYPE_GUID(value='<error: UuidToString failed>')");
}
}
break;
case WS_XML_TEXT_TYPE_UNIQUE_ID:
{
WS_XML_UNIQUE_ID_TEXT* uniqueIdText = (WS_XML_UNIQUE_ID_TEXT*) text;
RPC_WSTR s;
if (UuidToString(&uniqueIdText->value, &s) == RPC_S_OK)
{
printf("WS_XML_TEXT_TYPE_UNIQUEID(value='%ls')", s);
RpcStringFree(&s);
}
else
{
printf("WS_XML_TEXT_TYPE_UNIQUEID(value='<error: UuidToString failed>')");
}
}
break;
case WS_XML_TEXT_TYPE_DATETIME:
{
const WS_XML_DATETIME_TEXT* dateTimeText = (const WS_XML_DATETIME_TEXT*)text;
WS_DATETIME value = dateTimeText->value;
printf("WS_XML_DATETIME_TEXT(ticks='%I64u',format='%d')", value.ticks, value.format);
}
break;
case WS_XML_TEXT_TYPE_TIMESPAN:
{
const WS_XML_TIMESPAN_TEXT* timeSpanText = (const WS_XML_TIMESPAN_TEXT*)text;
printf("WS_XML_TIMESPAN_TEXT(value='%I64u')", timeSpanText->value.ticks);
}
break;
case WS_XML_TEXT_TYPE_QNAME:
{
const WS_XML_QNAME_TEXT* qnameText = (const WS_XML_QNAME_TEXT*)text;
printf("WS_XML_QNAME_TEXT(prefix='");
PrintString(qnameText->prefix);
printf("', localName='");
PrintString(qnameText->localName);
printf("', ns='");
PrintString(qnameText->ns);
printf("')");
}
break;
case WS_XML_TEXT_TYPE_LIST:
{
const WS_XML_LIST_TEXT* listText = (const WS_XML_LIST_TEXT*)text;
printf("WS_XML_LIST_TEXT(value={");
for (ULONG i = 0; i < listText->itemCount; i++)
{
PrintText(listText->items[i]);
printf(" ");
}
printf("}");
}
break;
default:
printf("<error: Unexpected textType>");
break;
}
}
// Main entry point
int __cdecl wmain(int argc, __in_ecount(argc) wchar_t **argv)
{
UNREFERENCED_PARAMETER(argc);
UNREFERENCED_PARAMETER(argv);
HRESULT hr = NOERROR;
WS_ERROR* error = NULL;
WS_XML_READER* xmlReader = NULL;
// Create an error object for storing rich error information
hr = WsCreateError(
NULL,
0,
&error);
if (FAILED(hr))
{
goto Exit;
}
// Create an XML reader
hr = WsCreateReader(
NULL,
0,
&xmlReader,
error);
if (FAILED(hr))
{
goto Exit;
}
char* xml =
"<?xml version='1.0' encoding='UTF-8' standalone='yes'?>"
"<Orders xmlns='http://example.com'>"
"<!-- Order #1 -->"
"<PurchaseOrder id='1'>"
"<Quantity>42</Quantity>"
"<ProductName>Toaster</ProductName>"
"</PurchaseOrder>"
"<!-- Order #2 -->"
"<PurchaseOrder id='2'>"
"<Quantity>5</Quantity>"
"<ProductName><![CDATA[Block&Tackle]></ProductName>"
"</PurchaseOrder>"
"</Orders>";
BYTE* bytes = (BYTE*) xml;
ULONG byteCount = (ULONG)strlen(xml);
// Setup the source input
WS_XML_READER_BUFFER_INPUT bufferInput;
ZeroMemory(&bufferInput, sizeof(bufferInput));
bufferInput.input.inputType = WS_XML_READER_INPUT_TYPE_BUFFER;
bufferInput.encodedData = bytes;
bufferInput.encodedDataSize = byteCount;
// Setup the source encoding
WS_XML_READER_TEXT_ENCODING textEncoding;
ZeroMemory(&textEncoding, sizeof(textEncoding));
textEncoding.encoding.encodingType = WS_XML_READER_ENCODING_TYPE_TEXT;
textEncoding.charSet = WS_CHARSET_AUTO;
// Setup the reader
hr = WsSetInput(xmlReader, &textEncoding.encoding, &bufferInput.input, NULL, 0, error);
if (FAILED(hr))
{
goto Exit;
}
WS_CHARSET charSet;
hr = WsGetReaderProperty(xmlReader, WS_XML_READER_PROPERTY_CHARSET, &charSet, sizeof(charSet), error);
if (FAILED(hr))
{
goto Exit;
}
switch (charSet)
{
case WS_CHARSET_UTF8:
printf("charSet=utf-8\n");
break;
case WS_CHARSET_UTF16LE:
printf("charSet=utf-16LE\n");
break;
case WS_CHARSET_UTF16BE:
printf("charSet=utf-16BE\n");
break;
default:
printf("<error: Unexpected charset>\n");
hr = E_FAIL;
goto Exit;
}
ULONG depth = 0;
for (;;)
{
// Get the current node of the reader
const WS_XML_NODE* node;
hr = WsGetReaderNode(xmlReader, &node, error);
if (FAILED(hr))
{
goto Exit;
}
for (ULONG i = 0; i < depth; i++)
{
printf(" ");
}
// Print out the type of node and its contents
switch (node->nodeType)
{
case WS_XML_NODE_TYPE_ELEMENT:
{
const WS_XML_ELEMENT_NODE* elementNode = (const WS_XML_ELEMENT_NODE*) node;
printf("WS_XML_NODE_TYPE_ELEMENT(prefix='");
PrintString(elementNode->prefix);
printf("', localName='");
PrintString(elementNode->localName);
printf("', ns='");
PrintString(elementNode->ns);
printf("', attributes={");
for (ULONG i = 0; i < elementNode->attributeCount; i++)
{
if (i != 0)
{
printf(", ");
}
const WS_XML_ATTRIBUTE* attribute = elementNode->attributes[i];
if (attribute->isXmlNs)
{
printf("(isXmlNs=TRUE, prefix='");
PrintString(attribute->prefix);
printf("', ns='");
PrintString(attribute->ns);
printf("')");
}
else
{
printf("(isXmlNs=FALSE, prefix='");
PrintString(attribute->prefix);
printf("', localName='");
PrintString(attribute->localName);
printf("', ns='");
PrintString(attribute->ns);
printf("', value=");
PrintText(attribute->value);
printf(")");
}
}
printf("})\n");
}
depth++;
break;
case WS_XML_NODE_TYPE_END_ELEMENT:
printf("WS_XML_NODE_TYPE_END_ELEMENT\n");
depth--;
break;
case WS_XML_NODE_TYPE_TEXT:
{
const WS_XML_TEXT_NODE* textNode = (const WS_XML_TEXT_NODE*) node;
printf("WS_XML_NODE_TYPE_TEXT(value=");
PrintText(textNode->text);
printf(")\n");
}
break;
case WS_XML_NODE_TYPE_CDATA:
printf("WS_XML_NODE_TYPE_CDATA\n");
depth++;
break;
case WS_XML_NODE_TYPE_END_CDATA:
printf("WS_XML_NODE_TYPE_END_CDATA\n");
depth--;
break;
case WS_XML_NODE_TYPE_COMMENT:
{
const WS_XML_COMMENT_NODE* commentNode = (const WS_XML_COMMENT_NODE*) node;
printf("WS_XML_NODE_TYPE_COMMENT(value='");
PrintString(&commentNode->value);
printf("')\n");
}
break;
case WS_XML_NODE_TYPE_BOF:
printf("WS_XML_NODE_TYPE_BOF\n");
depth++;
break;
case WS_XML_NODE_TYPE_EOF:
printf("WS_XML_NODE_TYPE_EOF\n");
depth--;
break;
default:
printf("<error: Unexpected nodeType>\n");
hr = E_FAIL;
goto Exit;
}
// See if we've reached the end of the document
if (node->nodeType == WS_XML_NODE_TYPE_EOF)
{
break;
}
// Advance the reader
hr = WsReadNode(xmlReader, error);
if (FAILED(hr))
{
goto Exit;
}
}
Exit:
if (FAILED(hr))
{
// Print out the error
PrintError(hr, error);
}
fflush(
stdout);
if (xmlReader != NULL)
{
WsFreeReader(xmlReader);
}
if (error != NULL)
{
WsFreeError(error);
}
fflush(stdout);
return SUCCEEDED(hr) ? 0 : -1;
}