// TranxMgr.cpp: implementation for the CTranxMgr // // Copyright (c)1997-2001 Microsoft Corporation // ////////////////////////////////////////////////////////////////////// #include "precomp.h" #include "XMLReader.h" /* Routine Description: Name: CXMLContent::CXMLContent Functionality: Trivial. Virtual: No. Arguments: None. Return Value: None as any constructor Notes: if you create any local members, think about initialize them here. */ CXMLContent::CXMLContent () : m_dwTotalElements(0), m_hOutFile(NULL), m_bFinished(false), m_bInSection(false), m_bSingleArea(true) { } /* Routine Description: Name: CXMLContent::~CXMLContent Functionality: Trivial. Virtual: Yes. Arguments: None. Return Value: None as any destructor Notes: if you create any local members, think about releasing them here. */ CXMLContent::~CXMLContent() { if (m_hOutFile != NULL) { ::CloseHandle(m_hOutFile); } } /* Routine Description: Name: CXMLContent::startElement Functionality: Analyze the elements. If the element is what we are interested in, then we will cache the information. Virtual: Yes. Arguments: pwchNamespaceUri - The namespace URI. cchNamespaceUri - The length for the namespace URI. pwchLocalName - The local name string. cchLocalName - The length of the local name. pwchQName - The QName (with prefix) or, if QNames are not available, an empty string. cchQName - The length of the QName. pAttributes - COM interface to the attribute object. Return Value: Success: S_OK; Failure: E_FAIL (this causes the parser not to continue parsing). Notes: See MSDN ISAXContentHandler::startElement for detail. We must maintain our handler to stay compatible with MSDN's specification. */ STDMETHODIMP CXMLContent::startElement ( IN const wchar_t * pwchNamespaceUri, IN int cchNamespaceUri, IN const wchar_t * pwchLocalName, IN int cchLocalName, IN const wchar_t * pwchQName, IN int cchQName, IN ISAXAttributes * pAttributes ) { // // If we have finished then we will stop here. // if ( m_bFinished ) { return E_FAIL; } ++m_dwTotalElements; // // if we are not in our section, we will only need to carry out // further if this element is a Section element // if (m_bInSection == false && _wcsicmp(pwchQName, L"Section") == 0) { LPWSTR pArea = NULL; if (GetAttributeValue(pAttributes, L"Area", &pArea)) { m_bInSection = (_wcsicmp(m_bstrSecArea, L"All") == 0 || _wcsicmp(pArea, m_bstrSecArea) == 0); // // $undone:shawnwu, put some header information, currently, hard coded for SCE's INF file // if (_wcsicmp(L"Sce_Core", pArea) == 0) { WriteContent(L"[Unicode]", NULL); WriteContent(L"Unicode", L"yes"); WriteContent(L"[Version]", NULL); WriteContent(L"$CHICAGO$", NULL); WriteContent(L"Revision", L"1"); WriteContent(L"\r\n", NULL); WriteContent(L"[System Access]", NULL); } WriteContent(L"\r\n", NULL); } delete [] pArea; } // // if not in our section, don't bother to continue // if (m_bInSection == false) { return S_OK; } if (m_bInElement == false && _wcsicmp(pwchQName, m_bstrElement) == 0) { m_bInElement = true; // // $undone:shawnwu, consider writing some element comments? // } if (m_bInElement == false) { return S_OK; } int iAttribCount = 0; pAttributes->getLength(&iAttribCount); LPWSTR pszPropName = NULL; LPWSTR pszPropValue = NULL; if (GetAttributeValue(pAttributes, L"Name", &pszPropName)) { // // In real time, we will do something with the (name, value) pair // since we are just testing here, write it to the file // if (GetAttributeValue(pAttributes, L"Value", &pszPropValue)) { WriteContent(pszPropName, pszPropValue); } delete [] pszPropName; pszPropName = NULL; delete [] pszPropValue; pszPropValue = NULL; } return S_OK; } /* Routine Description: Name: CXMLContent::endElement Functionality: Analyze the elements. We may decide that this is the end of our parsing need depending on our settings. Virtual: Yes. Arguments: pwchNamespaceUri - The namespace URI. cchNamespaceUri - The length for the namespace URI. pwchLocalName - The local name string. cchLocalName - The length of the local name. pwchQName - The QName (with prefix) or, if QNames are not available, an empty string. cchQName - The length of the QName. Return Value: Success: S_OK; Failure: E_FAIL (this causes the parser not to continue parsing). Notes: See MSDN ISAXContentHandler::endElement for detail. We must maintain our handler to stay compatible with MSDN's specification. */ STDMETHODIMP CXMLContent::endElement ( IN const wchar_t * pwchNamespaceUri, IN int cchNamespaceUri, IN const wchar_t * pwchLocalName, IN int cchLocalName, IN const wchar_t * pwchQName, IN int cchQName ) { // // if we have seen the section ended, we are done. // if (m_bInSection && _wcsicmp(pwchQName, L"Section") == 0) { m_bFinished = m_bSingleArea; m_bInSection = false; } if (m_bInElement && _wcsicmp(pwchQName, m_bstrElement) == 0) { m_bInElement = false; } return S_OK; } STDMETHODIMP CXMLContent::startDocument() { m_bFinished = false; m_bInElement = false; m_bInSection = false; m_dwTotalElements = 0; return S_OK; } STDMETHODIMP CXMLContent::endDocument () { LPCWSTR pszOutFile = m_bstrOutputFile; if (pszOutFile && *pszOutFile != L'\0') { // // testing code. // WCHAR pszValue[100]; swprintf(pszValue, L"%d", m_dwTotalElements); WriteContent(L"\r\nTotal Elements parsed: ", pszValue); } return S_OK; } STDMETHODIMP CXMLContent::putDocumentLocator ( IN ISAXLocator *pLocator ) { return S_OK; } STDMETHODIMP CXMLContent::startPrefixMapping ( IN const wchar_t * pwchPrefix, IN int cchPrefix, IN const wchar_t * pwchUri, IN int cchUri ) { return S_OK; } STDMETHODIMP CXMLContent::endPrefixMapping ( IN const wchar_t * pwchPrefix, IN int cchPrefix ) { return S_OK; } STDMETHODIMP CXMLContent::characters ( IN const wchar_t * pwchChars, IN int cchChars ) { return S_OK; } STDMETHODIMP CXMLContent::ignorableWhitespace ( IN const wchar_t * pwchChars, IN int cchChars ) { return S_OK; } STDMETHODIMP CXMLContent::processingInstruction ( IN const wchar_t * pwchTarget, IN int cchTarget, IN const wchar_t * pwchData, IN int cchData ) { return S_OK; } STDMETHODIMP CXMLContent::skippedEntity ( IN const wchar_t * pwchName, IN int cchName ) { return S_OK; } /* Routine Description: Name: CXMLContent::GetAttributeValue Functionality: Private helper. Given the attribute's name, we will return the attribute's value. Virtual: No. Arguments: pAttributes - COM interface to the attribute object. pszTestName - The name of the attributes we want the value of. ppszAttrVal - Receives the attribute's value if found. Return Value: true if the named attribute is found; false otherwise. Notes: Caller is responsible for releasing the memory allocated to the out parameter. */ bool CXMLContent::GetAttributeValue ( IN ISAXAttributes * pAttributes, IN LPCWSTR pszAttrName, OUT LPWSTR * ppszAttrVal ) { // // caller is responsible for passing valid parameters // *ppszAttrVal = NULL; int iAttribCount = 0; pAttributes->getLength(&iAttribCount); const wchar_t * pszName; const wchar_t * pszValue; int iNameLen; int iValLen; for ( int i = 0; i < iAttribCount; i++ ) { HRESULT hr = pAttributes->getLocalName(i, &pszName, &iNameLen); if (SUCCEEDED(hr) && wcsncmp(pszAttrName, pszName, iNameLen) == 0) { hr = pAttributes->getValue(i, &pszValue, &iValLen); if (SUCCEEDED(hr)) { *ppszAttrVal = new WCHAR[iValLen + 1]; if (*ppszAttrVal != NULL) { wcscpy(*ppszAttrVal, pszValue); return true; } else { return false; } } } } return false; } /* Routine Description: Name: CXMLContent::GetAttributeValue Functionality: Private helper. Given the index, we will return the attribute's name and its value. Virtual: No. Arguments: pAttributes - COM interface to the attribute object. iIndex - The index of the attribute we want. ppszAttrName - Receives the name of the attributes we want. ppszAttrVal - Receives the attribute's value if found. Return Value: true if the named attribute is found; false otherwise. Notes: Caller is responsible for releasing the memory allocated to both out parameters. */ bool CXMLContent::GetAttributeValue ( IN ISAXAttributes * pAttributes, IN int iIndex, OUT LPWSTR * ppszAttrName, OUT LPWSTR * ppszAttrVal ) { // // caller is responsible for passing valid parameters // *ppszAttrName = NULL; *ppszAttrVal = NULL; const wchar_t * pszName; const wchar_t * pszValue; int iNameLen; int iValLen; HRESULT hr = pAttributes->getLocalName(iIndex, &pszName, &iNameLen); if (SUCCEEDED(hr) && iNameLen > 0) { hr = pAttributes->getValue(iIndex, &pszValue, &iValLen); if (SUCCEEDED(hr) && iValLen > 0) { *ppszAttrName = new WCHAR[iNameLen + 1]; *ppszAttrVal = new WCHAR[iValLen + 1]; if (*ppszAttrName != NULL && *ppszAttrVal != NULL) { wcsncpy(*ppszAttrName, pszName, iNameLen); (*ppszAttrName)[iNameLen] = L'\0'; wcsncpy(*ppszAttrVal, pszValue, iValLen); (*ppszAttrVal)[iValLen] = L'\0'; return true; } else { return false; } } } return false; } /* Routine Description: Name: CXMLContent::WriteContent Functionality: Testing function. This determines which section area this reader is interested in and which element of the section this reader will process. Virtual: No. Arguments: pszSecArea - The Area attribute of the section the reader will process. pszElement - The name of the element the reader will process. bOneAreaOnly- Whether we will only process one area. Return Value: None. Notes: */ void CXMLContent::SetSection ( IN LPCWSTR pszSecArea, IN LPCWSTR pszElement, IN bool bOneAreaOnly ) { m_bstrSecArea = pszSecArea; m_bstrElement = pszElement; m_bSingleArea = bOneAreaOnly; } /* Routine Description: Name: CXMLContent::WriteContent Functionality: Private helper for testing (for now). Given the name and value pair, we will write = into the output file. Virtual: No. Arguments: pszName - The name of the pair. pszValue - The value of the pair. Can be NULL. In that case, we will only write the pszName as a separate line. Return Value: None. Notes: */ void CXMLContent::WriteContent ( IN LPCWSTR pszName, IN LPCWSTR pszValue ) { if (m_hOutFile == NULL) { m_hOutFile = ::CreateFile (m_bstrOutputFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); } if (m_hOutFile != NULL) { DWORD dwBytesWritten = 0; ::WriteFile (m_hOutFile, (LPCVOID) pszName, wcslen(pszName) * sizeof(WCHAR), &dwBytesWritten, NULL ); if (pszValue != NULL) { ::WriteFile (m_hOutFile, (LPCVOID) L"=", sizeof(WCHAR), &dwBytesWritten, NULL ); ::WriteFile (m_hOutFile, (LPCVOID) pszValue, wcslen(pszValue) * sizeof(WCHAR), &dwBytesWritten, NULL ); } // // a new line // ::WriteFile (m_hOutFile, (LPCVOID) L"\r\n", 2 * sizeof(WCHAR), &dwBytesWritten, NULL ); } }