Sample 2: Parsing a CDF file for specific tags
//*******************************
// XML OM test code
//
// *******************************
#include <windows.h>
#include <windowsx.h>
#include <stdlib.h>
#include <stdio.h>
#include <io.h>
#include <urlmon.h>
#include <hlink.h>
#include <dispex.h>
#include "mshtml.h"
#include "msxml.h"
#define ASSERT(x) if(!(x)) DebugBreak()
#define CHECK_ERROR(cond, err) if (!(cond)) {pszErr=(err); goto done;}
#define SAFERELEASE(p) if (p) {(p)->Release(); p = NULL;} else ;
#define WALK_ELEMENT_COLLECTION(pCollection, pDispItem) \
{\
long length;\
\
if (SUCCEEDED(pChildren->get_length(&length)) && length > 0)\
{\
VARIANT vIndex, vEmpty;\
vIndex.vt = VT_I4;\
vEmpty.vt = VT_EMPTY;\
\
for (long i=0; i<length; i++)\
{\
vIndex.lVal = i;\
IDispatch *pDispItem = NULL;\
if (SUCCEEDED(pCollection->item(vIndex, vEmpty, &pDispItem)))\
{
#define END_WALK_ELEMENT_COLLECTION(pDispItem) \
pDispItem->Release();\
}\
}\
}\
}
void Indent(int indent)
{
while (indent-->0)
{
printf(" ");
}
}
void Output(int indent, const char *format, ...)
{
va_list argptr;
va_start(argptr, format);
Indent(indent);
(void)vprintf(format, argptr);
}
void OutputLn(int indent, const char *format, ...)
{
va_list argptr;
va_start(argptr, format);
printf("\n");
Indent(indent);
(void)vprintf(format, argptr);
}
//
// Dump an element attribute member if present.
//
void DumpAttrib(IXMLElement *pElem, BSTR bstrAttribName)
{
VARIANT vProp;
VariantInit(&vProp);
if (SUCCEEDED(pElem->getAttribute(bstrAttribName, &vProp)))
{
if (vProp.vt == VT_BSTR)
{
printf(" %S=\"%S\"", bstrAttribName, vProp.bstrVal);
}
VariantClear(&vProp);
}
}
//
// Helper routine to quickly find out if this is a named element
// currently only used to improve the format of the output.
//
BOOL IsNamedElement(IXMLElement *pElem)
{
BSTR bstrName;
if (SUCCEEDED(pElem->get_tagName(&bstrName)))
{
if (bstrName)
{
SysFreeString(bstrName);
return TRUE;
}
}
return FALSE;
}
//
// Returns TRUE if this element had children.
//
void DumpElement
(
IXMLElement *pElem, // the XML element to dump
int indent // indentation level
)
{
BSTR bstrTagName = NULL;
BSTR bstrContent = NULL;
IXMLElementCollection * pChildren;
//
// Note this nonsense with children and grandchildren is just so we get
// nicely formatted output!
//
BOOL fHadNamedChild = FALSE;
//
// Dump the name of the NODE.
//
pElem->get_tagName(&bstrTagName);
if (bstrTagName)
{
//
// Special case the output of the special tags.
//
if (wcscmp(bstrTagName, L"XML") == 0)
{
Output(indent, "<\?XML version=\"1.0\"\?>\n");
SysFreeString(bstrTagName);
return;
}
else if (wcscmp(bstrTagName, L"DOCTYPE") == 0)
{
Output(indent,
"<!DOCTYPE CHANNEL SYSTEM \"http://www.w3c.org/Channel.dtd\">\n");
SysFreeString(bstrTagName);
return;
}
else
{
OutputLn(indent, "<%S", bstrTagName);
}
}
//
// Dump the attributes if present.
//
DumpAttrib(pElem, L"VALUE");
DumpAttrib(pElem, L"HREF");
DumpAttrib(pElem, L"HOUR");
DumpAttrib(pElem, L"DAY");
DumpAttrib(pElem, L"IsClonable");
DumpAttrib(pElem, L"Type");
//
// Dump the text contents if present.
//
XMLELEM_TYPE xmlElemType;
if (SUCCEEDED(pElem->get_type((long *)&xmlElemType)))
{
if (xmlElemType == XMLELEMTYPE_TEXT)
{
if (SUCCEEDED(pElem->get_text(&bstrContent)))
{
if (bstrContent)
{
printf("%S", bstrContent);
SysFreeString(bstrContent);
}
}
}
}
//
// Find the children if they exist.
//
if (SUCCEEDED(pElem->get_children(&pChildren)) && pChildren)
{
//
// Close the tag if present but with "children present" closure
// that is use > instead of />.
//
if (bstrTagName) printf(">");
WALK_ELEMENT_COLLECTION(pChildren, pDisp)
{
//
// pDisp will iterate over an IDispatch for each item in the collection.
//
IXMLElement * pChild;
if (SUCCEEDED(pDisp->QueryInterface(
IID_IXMLElement, (void **)&pChild)))
{
if (IsNamedElement(pChild))
fHadNamedChild = TRUE;
//
// Recursively dump children.
//
DumpElement(pChild, indent+1);
pChild->Release();
}
}
END_WALK_ELEMENT_COLLECTION(pDisp);
pChildren->Release();
//
// Display closing tag.
//
if (bstrTagName)
{
if (fHadNamedChild)
{
OutputLn(indent, "</%S>", bstrTagName);
}
else
{
printf("</%S>", bstrTagName);
}
}
}
else
{
//
// No children so terminate tag on same line.
//
if (bstrTagName) printf("/>");
}
if (bstrTagName)
SysFreeString(bstrTagName);
}
int MyStrToOleStrN(LPOLESTR pwsz, int cchWideChar, LPCTSTR psz)
{
int i;
i=MultiByteToWideChar(CP_ACP, 0, psz, -1, pwsz, cchWideChar);
if (!i)
{
//DBG_WARN("MyStrToOleStrN string too long; truncated");
pwsz[cchWideChar-1]=0;
}
else
ZeroMemory(pwsz+i, sizeof(OLECHAR)*(cchWideChar-i));
return i;
}
int _cdecl main (int argc, char **argv)
{
PSTR pszErr = NULL;
IXMLDocument *pDoc = NULL;
IStream *pStm = NULL;
IPersistStreamInit *pPSI = NULL;
IXMLElement *pElem = NULL;
TCHAR buf[MAX_PATH];
TCHAR *pszURL;
WCHAR *pwszURL=NULL;
BSTR pBURL=NULL;
HRESULT hr;
//
// Check usage.
//
if (argc != 2)
{
fprintf (stderr, "Usage: omtest2 URL\n");
fprintf (stderr, "Eg omtest2 c:\\nt\\private\\inet\\xml\\test\\channel.uni\n");
fprintf (stderr, "or omtest2 http://ohserv/users/julianj/channel.xml\n");
exit (1);
}
//
// HACK if passed in a file name, expand if it doesn't look like a URL.
//
if (CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, argv[1], 7, "http://", 7) == CSTR_EQUAL)
{
pszURL = argv[1];
}
else
{
pszURL = buf;
GetFullPathName(argv[1], MAX_PATH, pszURL, NULL);
}
hr = CoInitialize(NULL);
ASSERT(SUCCEEDED(hr));
//
// Create an empty XML document.
//
hr = CoCreateInstance(CLSID_XMLDocument, NULL, CLSCTX_INPROC_SERVER,
IID_IXMLDocument, (void**)&pDoc);
CHECK_ERROR (pDoc, "CoCreateInstance Failed");
//
// Synchronously create a stream on a URL.
//
//hr = URLOpenBlockingStream(0, pszURL, &pStm, 0,0);
//CHECK_ERROR(SUCCEEDED(hr) && pStm, "Couldn't open stream on URL")
//
// Get the IPersistStreamInit interface to the XML doc.
//
//hr = pDoc->QueryInterface(IID_IPersistStreamInit, (void **)&pPSI);
//CHECK_ERROR(SUCCEEDED(hr), "QI for IPersistStreamInit failed");
//
// Init the XML doc from the stream.
//
//hr = pPSI->Load(pStm);
pwszURL = (WCHAR *)LocalAlloc(LMEM_FIXED, ((sizeof(WCHAR))*(strlen(pszURL) + 2)));
CHECK_ERROR(pwszURL, "Mem Alloc Failure");
hr = MyStrToOleStrN(pwszURL, (strlen(pszURL) + 1), pszURL);
CHECK_ERROR(SUCCEEDED(hr), "Failed to convert to UNICODE");
pBURL = SysAllocString(pwszURL);
CHECK_ERROR(pBURL, "Mem Alloc Failure");
LocalFree(pwszURL);
hr = pDoc->put_URL(pBURL);
if (SUCCEEDED(hr))
{
//
// Now walk the OM and look at interesting things.
//
hr = pDoc->get_root(&pElem);
CHECK_ERROR(SUCCEEDED(hr), "Failed to get_root of XML object");
//
// Dump the top level meta nodes of the document.
//
BSTR bstrVal;
hr = pDoc->get_version(&bstrVal);
if(FAILED(hr) || !bstrVal)
{
bstrVal = SysAllocString(L"1.0");
}
//
Output(0, "<\?XML version=\"%S\" ",bstrVal);
SysFreeString(bstrVal);
bstrVal = NULL;
hr = pDoc->get_encoding(&bstrVal);
if(SUCCEEDED(hr) && bstrVal)
{
Output(0, "encoding=\"%S\" ",bstrVal);
SysFreeString(bstrVal);
}
Output(0, "\?>\n");
//
// Look for doctype information.
//
// Disabled till DavidSch makes a fix
/*
bstrVal = NULL;
hr = pDoc->get_doctype(&bstrVal);
if(SUCCEEDED(hr) && bstrVal)
{
Output(0, "<!DOCTYPE %S>",bstrVal);
SysFreeString(bstrVal);
}
*/
//
// Dump the root element and all children of the XML object.
//
DumpElement(pElem, 0); // -1 to counteract nameless outer container
}
else
{
//
// Failed to parse stream, output error information.
//
IXMLError *pXMLError = NULL ;
XML_ERROR xmle;
hr = pDoc->QueryInterface(IID_IXMLError, (void **)&pXMLError);
CHECK_ERROR(SUCCEEDED(hr), "Couldn't get IXMLError");
ASSERT(pXMLError);
hr = pXMLError->GetErrorInfo(&xmle);
SAFERELEASE(pXMLError);
CHECK_ERROR(SUCCEEDED(hr), "GetErrorInfo Failed");
printf("%s: Error on line %d. Found %S while expecting %S\r\n",
argv[0],
xmle._nLine,
xmle._pszFound,
xmle._pszExpected);
SysFreeString(xmle._pszFound);
SysFreeString(xmle._pszExpected);
SysFreeString(xmle._pchBuf);
}
done: // Clean up.
//
// Release any used interfaces.
//
SAFERELEASE(pPSI);
SAFERELEASE(pStm);
SAFERELEASE(pElem);
SAFERELEASE(pDoc);
SysFreeString(pBURL);
if (pszErr)
fprintf (stderr, "%s, last error %d\n", pszErr, GetLastError());
return 0;
}
Top of Page
© 1997 Microsoft Corporation. All rights reserved. Terms of Use.