📄 zhang.txt
字号:
A C++ Template Wrapper for the XML SAX API
by Yingjun Zhang
Figure 1:
<BookedOrders xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance">
<CustomerOrder>
<OrderID>1000</OrderID>
<Customer>XYZ Inc.</Customer>
<Item>Steel</Item>
<Unit>Ton</Unit>
<Quantity>2.8</Quantity>
</CustomerOrder>
<CustomerOrder>
<OrderID>1001</OrderID>
<Customer>ABC Inc.</Customer>
<Item>Plastic</Item>
<Unit>Roll</Unit>
<Quantity>30.5</Quantity>
</CustomerOrder>
</BookedOrders>
Listing 1:
// ...
class CustomerOrderHandler : public ISAXContentHandler
{
private:
int m_OrderID;
wchar_t m_CustomerName[20];
wchar_t m_ItemName[20];
wchar_t m_Unit[20];
double m_Quantity;
XmlString m_CurrentTag;
public:
CustomerOrderHandler(){}
virtual ~CustomerOrderHandler(){}
// other member functions not shown
virtual HRESULT STDMETHODCALLTYPE startElement(
/* [in] */ wchar_t __RPC_FAR *pwchNamespaceUri,
/* [in] */ int cchNamespaceUri,
/* [in] */ wchar_t __RPC_FAR *pwchLocalName,
/* [in] */ int cchLocalName,
/* [in] */ wchar_t __RPC_FAR *pwchRawName,
/* [in] */ int cchRawName,
/* [in] */ ISAXAttributes __RPC_FAR *pAttributes)
{
// record where the document is being parsed
m_CurrentTag = XmlString(pwchLocalName, cchLocalName);
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE endElement(
/* [in] */ wchar_t __RPC_FAR *pwchNamespaceUri,
/* [in] */ int cchNamespaceUri,
/* [in] */ wchar_t __RPC_FAR *pwchLocalName,
/* [in] */ int cchLocalName,
/* [in] */ wchar_t __RPC_FAR *pwchRawName,
/* [in] */ int cchRawName)
{
m_CurrentTag = XmlString(pwchLocalName, cchLocalName);
if (m_CurrentTag == L"CustomerOrder") // whole order has been parsed,
{ // process this order now.
std::wcout << L"Order " << m_OrderID
<< L" from " << m_CustomerName
<< L": " << m_ItemName
<< L" " << m_Quantity
<< L" " << m_Unit
<< L"s has been processed." << std::endl;
}
m_CurrentTag = L""; // clear the status for next element
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE characters(
/* [in] */ wchar_t __RPC_FAR *pwchChars,
/* [in] */ int cchChars)
{
if (m_CurrentTag == L"OrderID")
m_OrderID = xmlstring_cast<int>(XmlString(pwchChars, cchChars));
else if (m_CurrentTag == L"Customer")
{
wcsncpy(m_CustomerName, pwchChars, cchChars);
m_CustomerName[cchChars] = L'\0';
}
else if (m_CurrentTag == L"Item")
{
wcsncpy(m_ItemName, pwchChars, cchChars);
m_ItemName[cchChars] = L'\0';
}
else if (m_CurrentTag == L"Unit")
{
wcsncpy(m_Unit, pwchChars, cchChars);
m_Unit[cchChars] = L'\0';
}
else if (m_CurrentTag == L"Quantity")
m_Quantity = xmlstring_cast<double>(XmlString(pwchChars, cchChars));
return S_OK;
}
};
#endif
Listing 2:
//.....
template <class Data, class Functor>
class DocumentContentHandler : public BaseContentHandler
{
protected:
typedef DocumentContentHandler<Data, Functor> DocHandlerType;
typedef map<XmlString, BaseContentHandler*> ContentHandlerMap;
typedef ContentHandlerMap::iterator ContentHandlerIterator;
protected:
ContentHandlerMap m_AllHandlers;
stack<BaseContentHandler*> m_ActiveHandlers;
ISAXXMLReader* m_pXMLReader;
public:
// destructor and other functions not shown
DocumentContentHandler(const XmlString& strDocumentName,
Functor* pFunctor)
: BaseContentHandler(strDocumentName)
{
m_AllHandlers.insert(
ContentHandlerMap::value_type(strDocumentName,this));
CompositeContentHandler<Data, Functor>* pHandler =
new DataHandler(Data::GetClassName(),this,pFunctor);
}
virtual HRESULT STDMETHODCALLTYPE startElement(
/* [in] */ wchar_t __RPC_FAR *pwchNamespaceUri,
/* [in] */ int cchNamespaceUri,
/* [in] */ wchar_t __RPC_FAR *pwchLocalName,
/* [in] */ int cchLocalName,
/* [in] */ wchar_t __RPC_FAR *pwchRawName,
/* [in] */ int cchRawName,
/* [in] */ ISAXAttributes __RPC_FAR *pAttributes)
{
ContentHandlerIterator iter =
m_AllHandlers.find(XmlString(pwchLocalName));
if (iter != m_AllHandlers.end())
{
m_ActiveHandlers.push(iter->second);
m_pXMLReader->putContentHandler(iter->second);
}
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE endElement(
/* [in] */ wchar_t __RPC_FAR *pwchNamespaceUri,
/* [in] */ int cchNamespaceUri,
/* [in] */ wchar_t __RPC_FAR *pwchLocalName,
/* [in] */ int cchLocalName,
/* [in] */ wchar_t __RPC_FAR *pwchRawName,
/* [in] */ int cchRawName)
{
if(!m_ActiveHandlers.empty())
m_ActiveHandlers.pop();
if(!m_ActiveHandlers.empty())
m_pXMLReader->putContentHandler(
m_ActiveHandlers.top());
return S_OK;
}
};
Listing 3:
// only partial listing
template <class Data, class Functor>
class CompositeContentHandler : public BaseContentHandler
{
BaseContentHandler* m_pDocumentHandler;
Functor* m_pFunctor;
Data m_Data;
vector<ContentHandlerPtr> m_ChildHandlers;
public:
CompositeContentHandler(const XmlString& name,
BaseContentHandler* pDocumentHandler, Functor* pFunctor)
: BaseContentHandler(name), m_pDocumentHandler(pDocumentHandler),
m_pFunctor(pFunctor)
{
BaseContentHandler* pTempHandler;
const XmlBindingEntry* pEntry = m_Data.GetXmlBindingEntries();
while(pEntry->eDataType != eXML_EMPTY)
{
pTempHandler = CreateHandler(pDocumentHandler, pEntry);
m_ChildHandlers.push_back(pTempHandler);
m_pDocumentHandler->AddContentHandler(pTempHandler);
++pEntry;
}
m_pDocumentHandler->AddContentHandler(this);
}
virtual HRESULT STDMETHODCALLTYPE endElement(
/* [in] */ wchar_t __RPC_FAR *pwchNamespaceUri,
/* [in] */ int cchNamespaceUri,
/* [in] */ wchar_t __RPC_FAR *pwchLocalName,
/* [in] */ int cchLocalName,
/* [in] */ wchar_t __RPC_FAR *pwchRawName,
/* [in] */ int cchRawName)
{
CopyTo(&m_Data);
(*m_pFunctor)(m_Data);
return m_pDocumentHandler->endElement(
pwchNamespaceUri, cchNamespaceUri, pwchLocalName, cchLocalName,
pwchRawName, cchRawName);
}
virtual void CopyTo(void* dest)
{
ClassContentHandlers::iterator iter, iterEnd;
iter=m_ChildHandlers.begin();
iterEnd = m_ChildHandlers.end();
for(;iter!= iterEnd; ++iter)
(*iter)->CopyTo(dest);
}
};
Listing 4:
#if !defined(CUSTOMERORDER__H)
#define CUSTOMERORDER__H
#include "XmlBinding.h"
#include <iostream>
using std::wostream;
class CustomerOrder
{
BEGIN_XML_BINDING(L"CustomerOrder", CustomerOrder)
XML_ELEMENT(L"OrderID", eXML_INT, m_OrderID)
XML_ELEMENT(L"Customer", eXML_STRING, m_CustomerName)
XML_ELEMENT(L"Item", eXML_STRING, m_ItemName)
XML_ELEMENT(L"Unit", eXML_STRING, m_Unit)
XML_ELEMENT(L"Quantity", eXML_DOUBLE, m_Quantity)
END_XML_BINDING()
int m_OrderID;
wchar_t m_CustomerName[20];
wchar_t m_ItemName[20];
wchar_t m_Unit[20];
double m_Quantity;
public:
friend wostream& operator << (wostream& wo, const CustomerOrder& order);
};
wostream& operator << (wostream& wo, const CustomerOrder& order)
{
return wo << L"Order " << order.m_OrderID
<< L" from " << order.m_CustomerName
<< L": " << order.m_ItemName
<< L" " << order.m_Quantity
<< L" " << order.m_Unit
<< L"s has been processed." << std::endl;
}
#endif
Listing 5:
#if !defined(CUSTOMERORDERPROCESSOR__H)
#define CUSTOMERORDERPROCESSOR__H
#include "CustomerOrder.h"
#include <iostream>
class CustomerOrderProcessor
{
public:
//The processings for the business order would go here.
//For simplicity, it only prints the order out
void operator() (const CustomerOrder& co)
{
std::wcout << co;
}
};
#endif
Listing 6:
#pragma warning (disable:4786)
#include "DocumentContentHandler.h"
#include "CustomerOrderProcessor.h"
#include <iostream>
int main()
{
typedef DocumentContentHandler<CustomerOrder, CustomerOrderProcessor>
CustomerOrderHandler;
::CoInitialize(NULL);
CustomerOrderProcessor order_processor;
CustomerOrderHandler order_handler(L"BookedOrders", &order_processor);
order_handler.Setup();
XmlString URL(L"CustomerOrder.xml");
HRESULT hr = order_handler.Parse(URL);
std::wcout << L"All Customer Order Processing Finished." << std::endl;
::CoUninitialize();
return 0;
}
5
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -