📄 xml.cpp
字号:
#include "xml.h"
#define C_SPACE _T(' ')
#define C_LMARK _T('<')
#define C_RMARK _T('>')
#define C_LF 0x0a
#define C_CR 0x0d
#define C_TAB _T('\t')
#define S_SPACE _T(" ")
#define S_LMARK _T("<")
#define S_RMARK _T(">")
#define S_ENDL _T("\n")
#define S_TAB _T("\t")
#define S_EMPTY _T("")
CIn_XML::CIn_XML()
{
m_isOpen = FALSE;
}
CIn_XML::~CIn_XML()
{
Close();
}
void CIn_XML::Open(const CString xmlFile, int &nOpened, CString rootName)
{
nOpened = m_root.Open(xmlFile, rootName);
m_isOpen = nOpened;
}
int CIn_XML::Is_open()
{
return m_isOpen;
}
void CIn_XML::Close()
{
m_table.RemoveAll();
m_root.Close();
}
void CIn_XML::WriteNode(CXmlNode &Node, COut_XML *pOutXML)
{
if (Node.m_subNodes.GetSize()) {
pOutXML->PutHead(Node.m_nodeName);
for (int i=0; i<Node.m_subNodes.GetSize(); i++) {
WriteNode(Node.m_subNodes[i], pOutXML);
}
pOutXML->PutTail(Node.m_nodeName);
}
pOutXML->PutItem(Node.m_nodeName, Node.m_nodeValue);
}
BOOL CIn_XML::SaveTo(const CString xmlFile)
{
COut_XML *pOutXML;
BOOL bOpened;
pOutXML=new COut_XML;
pOutXML->Open(xmlFile, bOpened);
if (!bOpened) {
delete pOutXML;
return FALSE;
}
for (int i=0; i<m_root.m_subNodes.GetSize(); i++){
WriteNode(m_root.m_subNodes[i], pOutXML);
}
delete pOutXML;
return TRUE;
}
int CIn_XML::FindRecords(const CString infoType, const CString recordType, int &RecordsCount)
{
RecordsCount = FindRecords(infoType, recordType);
return RecordsCount;
}
int CIn_XML::FindRecords(const CString infoType, int &RecordsCount)
{
RecordsCount = FindRecords(infoType);
return RecordsCount;
}
int CIn_XML::FindRecords(const CString infoType, const CString recordType)
{
m_table.RemoveAll();
m_root.GetNodesTable(m_table, infoType, recordType);
return m_table.GetSize();
}
int CIn_XML::FindRecords(const CString infoType)
{
m_table.RemoveAll();
m_root.GetNodesTable(m_table, infoType);
return m_table.GetSize();
}
int CIn_XML::GetRecordsCount(int &RecordsCount)
{
RecordsCount = m_table.GetSize();
return RecordsCount;
}
CString CIn_XML::GetRecordPath(int recordNo, LPTSTR RecordPath)
{
CString Path = GetRecordPath(recordNo);
_tcscpy(RecordPath, (LPCTSTR)Path);
return Path;
}
CString CIn_XML::GetRecordPath(int recordNo)
{
if ((recordNo>=0) && (recordNo<m_table.GetSize())) {
return m_table[recordNo].m_path;
}
else {
return S_EMPTY;
}
}
CString CIn_XML::GetPath(int recordNo)
{
return GetRecordPath(recordNo);
}
CString CIn_XML::GetItemValue(int recordNo, const CString itemName, LPTSTR ItemValue)
{
CString Value = GetItemValue(recordNo, itemName);
_tcscpy(ItemValue, (LPCTSTR)Value);
return Value;
}
CString CIn_XML::GetItemValue(int recordNo, const CString itemName)
{
if ((recordNo>=0) && (recordNo<m_table.GetSize())) {
if (itemName==_T("_FILE_"))
return m_table[recordNo].m_pNode->m_nodeValue;
else
return m_table[recordNo].m_pNode->GetFldValue(itemName);
}
else {
return S_EMPTY;
}
}
CString CIn_XML::GetFile(int recordNo)
{
return GetItemValue(recordNo, "_FILE_");
}
int CIn_XML::GetInfoTable(CStringTable &InfoTable)
{
InfoTable.RemoveAll();
int n=m_root.m_subNodes.GetSize();
for (int i=0; i<n; i++) {
InfoTable.Add(CString(m_root.m_subNodes[i].m_nodeName));
}
return n;
}
CXmlNode::CXmlNode()
{
m_nodeName = S_EMPTY;
m_nodeValue = S_EMPTY;
}
CXmlNode::CXmlNode(CString name, CString value)
{
m_nodeName = name;
m_nodeValue = value;
}
void CXmlNode::CopyFrom(const CXmlNode& other)
{
RemoveAll();
m_nodeName = other.m_nodeName;
m_nodeValue = other.m_nodeValue;
for (int i=0; i<other.m_subNodes.GetSize(); i++) {
m_subNodes.Add(other.m_subNodes[i]);
}
}
CXmlNode::CXmlNode(const CXmlNode& other)
{
CopyFrom(other);
}
CXmlNode& CXmlNode::operator = (const CXmlNode& other)
{
CopyFrom(other);
return *this;
}
void CXmlNode::RemoveAll( )
{
for (int i=0; i<m_subNodes.GetSize(); i++) {
m_subNodes[i].RemoveAll();
}
m_subNodes.RemoveAll();
m_nodeName = S_EMPTY;
m_nodeValue = S_EMPTY;
}
CXmlNode::~CXmlNode()
{
RemoveAll();
}
CInFile::CInFile(CString fileName)
{
m_hFile = CreateFile( fileName , GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
m_bEof = !isOpen();
m_line = S_EMPTY;
}
CInFile::~CInFile()
{
CloseHandle(m_hFile);
m_hFile = INVALID_HANDLE_VALUE;
}
BOOL CInFile::isOpen()
{
return (m_hFile!=INVALID_HANDLE_VALUE);
}
BOOL CInFile::eof()
{
return (m_line.IsEmpty() && (m_bEof));
}
#define LINESIZE 256
void CInFile::getline()
{
TCHAR buf[LINESIZE+1];
DWORD n;
BOOL bResult;
while ( ((m_line.Find(S_LMARK)<0) || (m_line.Find(S_RMARK)<0)) && (!eof()))
{
bResult = ReadFile(m_hFile, &buf, sizeof(buf)-sizeof(TCHAR), &n, NULL) ;
// Check for end of file.
n=n / sizeof(TCHAR);
m_bEof = (bResult && n==0);
buf[n] = 0;
WORD *p=(WORD *)buf;
if (*p==0xFEFF)
m_line = m_line + (buf+1);
else
m_line = m_line + buf;
}
if ((m_line.Find(S_LMARK)<0) || (m_line.Find(S_RMARK)<0))
m_line = S_EMPTY;
}
CString CInFile::getItem()
{
getline();
if (eof())
return S_EMPTY;
TCHAR *p, *q, *buf;
TCHAR a[]=_T("\n");
buf=m_line.GetBuffer(m_line.GetLength());
// skip any space before "<"
p = buf;
while ((*p!=C_LMARK) && ((*p==C_SPACE)||(*p==C_CR)||(*p==C_LF)||(*p==C_TAB)))
p++;
if (*p!=C_LMARK) p=buf;
if (*p==C_LMARK) {
q=p;
while (*p!=C_RMARK) p++;
} else {
while ((*p==C_CR)||(*p==C_CR)) p++;
q=p;
while (*p!=C_LMARK) p++;
p--;
while ((*p==C_SPACE)||(*p==C_CR)||(*p==C_LF)||(*p==C_TAB)) p--;
}
m_line.ReleaseBuffer();
CString item=m_line.Mid(q-buf, p-q+1);
m_line.Delete(0, p-buf+1);
TRACE(_T("%s\n"), item);
return item;
}
BOOL CXmlNode::Open(CString filename, CString rootName)
{
CInFile inFile(filename);
rootName=S_LMARK+rootName+S_RMARK;
CString item;
if (inFile.isOpen()) {
do {
item = inFile.getItem();
} while (item!=rootName);
return LoadXMLNode(inFile, item);
}
return FALSE;
}
#define ITEM_HEAD _T('H')
#define ITEM_DATA _T('D')
#define ITEM_TAIL _T('T')
TCHAR getItemType(CString &item)
{
if (item.Left(2)==_T("</"))
return ITEM_TAIL;
if (item.Left(1)==_T("<"))
return ITEM_HEAD;
return ITEM_DATA;
}
CString trimFlag(CString item)
{
if (item[0]==_T('<')) {
item.Delete(0);
if (item[0]==_T('/')) item.Delete(0);
item.Delete(item.GetLength()-1);
}
return item;
}
BOOL CXmlNode::LoadXMLNode(CInFile& inFile, CString head)
{
int i;
CString item;
TCHAR itemType;
if (m_nodeName.IsEmpty()) m_nodeName=trimFlag(head);
else {
i = m_subNodes.Add(CXmlNode());
m_subNodes[i].LoadXMLNode(inFile, head);
}
while (!inFile.eof()) {
item = inFile.getItem();
itemType = getItemType(item);
if (itemType==ITEM_HEAD) {
i = m_subNodes.Add(CXmlNode());
m_subNodes[i].LoadXMLNode(inFile, item);
}
else if (itemType==ITEM_DATA) {
m_nodeValue = item;
}
else if (itemType==ITEM_TAIL) {
return TRUE;
}
}
return TRUE;
}
void CXmlNode::FindNodes(CXmlFindTable& table, CString what, CString path, int level)
{
if (what.IsEmpty() && ((m_nodeName==_T("_RECORD_")) || (m_nodeName==_T("_FILE_"))))
table.Add(CFindItem(path, this));
else if (m_nodeName==what)
table.Add(CFindItem(path, this));
else {
if (level!=0) {
if (path.IsEmpty()) path=m_nodeName;
else path = path + _T("\\") + m_nodeName;
}
for (int i=0; i<m_subNodes.GetSize(); i++)
{
m_subNodes[i].FindNodes(table, what, path, level+1);
}
}
}
CXmlNode* CXmlNode::Locate(CString what)
{
int i;
if (m_nodeName==what) {
return this;
}
else {
for (i=0; i<m_subNodes.GetSize(); i++) {
if (m_subNodes[i].m_nodeName==what)
return &m_subNodes[i];
}
for (i=0; i<m_subNodes.GetSize(); i++) {
CXmlNode* node;
node = m_subNodes[i].Locate(what);
if (node!=NULL) return node;
}
}
return NULL;
}
CString CXmlNode::GetFldValue(const CString fldName)
{
CString fldValue=S_EMPTY;
for (int i=0; i<m_subNodes.GetSize(); i++) {
if (m_subNodes[i].m_nodeName==fldName) {
fldValue = m_subNodes[i].m_nodeValue;
break;
}
}
return fldValue;
}
void CXmlNode::GetNodesTable(CXmlFindTable& table, const CString infoType, const CString recType)
{
CXmlNode *node;
table.RemoveAll();
node = Locate(infoType);
if (node) node->FindNodes(table, recType, S_EMPTY, 0);
}
void CXmlNode::GetNodesTable(CXmlFindTable& table, const CString infoType)
{
CXmlNode *node;
table.RemoveAll();
node = Locate(infoType);
if (node) {
node->FindNodes(table, S_EMPTY, S_EMPTY, 0);
}
}
void CXmlNode::Close()
{
RemoveAll();
}
COut_XML::COut_XML()
{
m_level = 0;
}
COut_XML::~COut_XML()
{
Close();
}
void COut_XML::WriteLn(const CString s)
{
if (m_hFile!=INVALID_HANDLE_VALUE) {
DWORD n;
CString list = s + _T("\n");
WriteFile(m_hFile, (LPCTSTR) list, sizeof(TCHAR)*list.GetLength(), &n, NULL);
}
}
void COut_XML::Open(const CString xmlFileName, int &nOpened, CString rootName)
{
m_hFile = CreateFile( xmlFileName,
GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
m_level = 0;
m_rootName = rootName;
if (m_hFile!=INVALID_HANDLE_VALUE)
{
WriteLn(_T("<?xml version=\"1.0\" encoding=\"GB2312\" standalone=\"yes\"?>"));
WriteLn(_T("<")+m_rootName+_T(">"));
m_level++;
}
nOpened = (m_hFile!=INVALID_HANDLE_VALUE);
}
int COut_XML::Is_open()
{
return (m_hFile!=INVALID_HANDLE_VALUE);
}
void COut_XML::Close()
{
DWORD n;
if (Is_open()) {
m_level--;
CString list=_T("</")+m_rootName+_T(">\n");
WriteFile(m_hFile, (LPCTSTR) list, sizeof(TCHAR)*list.GetLength(), &n,NULL);
CloseHandle( m_hFile );
m_hFile = INVALID_HANDLE_VALUE;
}
}
void COut_XML::PutHead(const CString name)
{
if (Is_open()) {
WriteLn(tab() + _T("<") + name +_T(">"));
m_level++;
}
}
void COut_XML::PutTail(const CString name)
{
if (Is_open()) {
m_level--;
WriteLn(tab() + _T("</") + name +_T(">"));
}
}
void COut_XML::PutItem(const CString name, const CString value)
{
if ((Is_open()) && (!value.IsEmpty())) {
WriteLn(tab() + _T("<") + name + _T(">") + value + _T("</") + name + _T(">"));
}
}
CString COut_XML::tab()
{
CString s=_T("");
for (int i=0; i<m_level; i++) s+=_T(" ");
return s;
}
void COut_XML::PutRecordHead()
{
PutHead(_T("_RECORD_"));
}
void COut_XML::PutRecordTail()
{
PutTail(_T("_RECORD_"));
}
void COut_XML::PutFile(const CString fileName)
{
PutItem(_T("_FILE_"), fileName);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -