C++解析四种不同格式的XML文件
说明
这里引用了TinyXML的开源的XML解析库,下载地址:https://sourceforge.net/projects/tinyxml/
data.h
#include "vector"
struct PrdSNInfo
{
CString PrdSN;
CString SubBoardId;
PrdSNInfo()
{
PrdSN = _T("");
SubBoardId = _T("");
}
};
typedef std::vector<PrdSNInfo> VEC_PrdSNInfo;
typedef VEC_PrdSNInfo::iterator VEC_PrdSNInfo_ITR;
struct OutPrdNoInfo
{
CString OutPrdNo;
CString ProductName;
OutPrdNoInfo()
{
OutPrdNo = _T("");
ProductName = _T("");
}
};
typedef std::vector<OutPrdNoInfo> VEC_OutPrdNoInfo;
typedef VEC_OutPrdNoInfo::iterator VEC_OutPrdNoInfo_ITR;
struct PlanInfo
{
CString PlanID;
CString PlanNo;
CString OutPrdNo;
CString OutPrdVer;
CString ProductName;
CString Line;
CString QTY;
CString StartTime;
PlanInfo()
{
PlanID = _T("");
PlanNo = _T("");
OutPrdNo = _T("");
OutPrdVer = _T("");
ProductName = _T("");
Line = _T("");
QTY = _T("");
StartTime = _T("");
}
};
typedef std::vector<PlanInfo> VEC_PlanInfo;
typedef VEC_PlanInfo::iterator VEC_PlanInfo_ITR;
struct ReturnParameter
{
CString Result;
CString ErrorCode;
CString ErrorMessage;
VEC_PrdSNInfo vec_PrdSNInfo;
VEC_OutPrdNoInfo vec_OutPrdNoInfo;
VEC_PlanInfo vec_PlanInfo;
ReturnParameter()
{
Reset();
}
void Reset()
{
Result = _T("");
ErrorCode = _T("");
ErrorMessage = _T("");
vec_PrdSNInfo.clear();
vec_OutPrdNoInfo.clear();
vec_PlanInfo.clear();
}
};
XMLAnalysisDlg.h
// XMLAnalysisDlg.h : 头文件
//
#pragma once
#include "tinystr.h"
#include "tinyxml.h"
#include "afx.h"
#include "data.h"
#include <string>
#include <iostream>
using namespace std;
// CXMLAnalysisDlg 对话框
class CXMLAnalysisDlg : public CDialog
{
// 构造
public:
CXMLAnalysisDlg(CWnd* pParent = NULL); // 标准构造函数
// 对话框数据
enum { IDD = IDD_XMLANALYSIS_DIALOG };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
// 实现
protected:
HICON m_hIcon;
// 生成的消息映射函数
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
void XMLAnalysisFromFile(string path);
void XMLAnalysisFromString(char* str);
void XMLAnalysis(TiXmlDocument* myDocument);
void ShowResult();
char* Cstring2Char(const CString& strConvert);
public:
PrdSNInfo m_PrdSNInfo;
OutPrdNoInfo m_OutPrdNoInfo;
PlanInfo m_PlanInfo;
ReturnParameter m_ReturnParameter;
public:
afx_msg void OnBnClickedOk();
public:
CString m_strXML;
public:
CString m_strResult;
public:
afx_msg void OnBnClickedOk2();
public:
CString m_Result;
public:
CString m_ErrorCode;
public:
CString m_ErrorMessage;
};
XMLAnalysisDlg.cpp
// XMLAnalysisDlg.cpp : 实现文件
//
#include "stdafx.h"
#include "XMLAnalysis.h"
#include "XMLAnalysisDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// 用于应用程序“关于”菜单项的 CAboutDlg 对话框
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// 对话框数据
enum { IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
// 实现
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()
// CXMLAnalysisDlg 对话框
CXMLAnalysisDlg::CXMLAnalysisDlg(CWnd* pParent /*=NULL*/)
: CDialog(CXMLAnalysisDlg::IDD, pParent)
, m_strXML(_T(""))
, m_strResult(_T(""))
, m_Result(_T(""))
, m_ErrorCode(_T(""))
, m_ErrorMessage(_T(""))
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CXMLAnalysisDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Text(pDX, IDC_EDIT1, m_strXML);
DDX_Text(pDX, IDC_EDIT15, m_Result);
DDX_Text(pDX, IDC_EDIT3, m_ErrorCode);
DDX_Text(pDX, IDC_EDIT4, m_ErrorMessage);
}
BEGIN_MESSAGE_MAP(CXMLAnalysisDlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
ON_BN_CLICKED(IDOK, &CXMLAnalysisDlg::OnBnClickedOk)
ON_BN_CLICKED(IDOK2, &CXMLAnalysisDlg::OnBnClickedOk2)
END_MESSAGE_MAP()
// CXMLAnalysisDlg 消息处理程序
BOOL CXMLAnalysisDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// 将“关于...”菜单项添加到系统菜单中。
// IDM_ABOUTBOX 必须在系统命令范围内。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
// TODO: 在此添加额外的初始化代码
CEdit *p_Edit;
p_Edit = (CEdit*)GetDlgItem(IDC_EDIT_STRING);
p_Edit->SetLimitText(UINT_MAX); //设置Edit Control容纳最大字符数
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
void CXMLAnalysisDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。
void CXMLAnalysisDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// 使图标在工作矩形中居中
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
//当用户拖动最小化窗口时系统调用此函数取得光标显示。
//
HCURSOR CXMLAnalysisDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CXMLAnalysisDlg::XMLAnalysisFromFile(string path)
{
//创建文件对象
TiXmlDocument * myDocument = new TiXmlDocument();
//加载文件数据
myDocument->LoadFile(path.c_str());
XMLAnalysis(myDocument);
}
void CXMLAnalysisDlg::XMLAnalysisFromString(char* str)
{
TiXmlDocument* myDocument = new TiXmlDocument();
myDocument->Parse(str);
XMLAnalysis(myDocument);
}
void CXMLAnalysisDlg::XMLAnalysis(TiXmlDocument* myDocument)
{
//获取根节点数据
TiXmlElement *root = myDocument->RootElement();
m_ReturnParameter.Reset();
TiXmlElement* elemResult = root->FirstChildElement("Result");
if (elemResult!=NULL)
{
m_ReturnParameter.Result = elemResult->GetText();
}
TiXmlElement* elemErrorCode = root->FirstChildElement("ErrorCode");
if (elemErrorCode!=NULL)
{
m_ReturnParameter.ErrorCode = elemErrorCode->GetText();
}
TiXmlElement* elemErrorMessage = root->FirstChildElement("ErrorMessage");
if (elemErrorMessage!=NULL)
{
m_ReturnParameter.ErrorMessage = elemErrorMessage->GetText();
}
/*<?xml version="1.0" encoding="UTF-8"?>
<ReturnParameter>
<Result>PASS</Result>
<ErrorCode></ErrorCode>
<ErrorMessage></ErrorMessage>
<PrdSNInfo>
<PrdSNs>
<PrdSN>SN0000000001</PrdSN>
<SubBoardId>1</SubBoardId>
</PrdSNs>
<PrdSNs>
<PrdSN>SN0000000002</PrdSN>
<SubBoardId>2</SubBoardId>
</PrdSNs>
<PrdSNs>
<PrdSN>SN0000000003</PrdSN>
<SubBoardId>3</SubBoardId>
</PrdSNs>
<PrdSNs>
<PrdSN>SN0000000004</PrdSN>
<SubBoardId>4</SubBoardId>
</PrdSNs>
</PrdSNInfo>
</ReturnParameter>*/
TiXmlElement* elemPrdSN = root->FirstChildElement("PrdSNInfo");
if (elemPrdSN!=NULL)
{
for(TiXmlElement* elem = elemPrdSN->FirstChildElement(); elem != NULL; elem = elem->NextSiblingElement())
{
const char* strPrdSN = elem->FirstChildElement("PrdSN")->GetText();
m_PrdSNInfo.PrdSN = strPrdSN;
const char* strSubBoardId = elem->FirstChildElement("SubBoardId")->GetText();
m_PrdSNInfo.SubBoardId = strSubBoardId;
m_ReturnParameter.vec_PrdSNInfo.push_back(m_PrdSNInfo);
}
}
/*<?xml version="1.0" encoding="UTF-8"?>
<ReturnParameter>
<Result>PASS</Result>
<ErrorCode />
<ErrorMessage />
<OutPrdNoList>
<OutPrdNoInfo>
<OutPrdNo>PN00001</OutPrdNo>
<ProductName>X1 Borad</ProductName>
</OutPrdNoInfo>
<OutPrdNoInfo>
<OutPrdNo>PN00002</OutPrdNo>
<ProductName>X2 Borad</ProductName>
</OutPrdNoInfo>
</OutPrdNoList>
</ReturnParameter>*/
TiXmlElement* elemOutPrdNo = root->FirstChildElement("OutPrdNoList");
if (elemOutPrdNo!=NULL)
{
for(TiXmlElement* em = elemOutPrdNo->FirstChildElement(); em != NULL; em = em->NextSiblingElement())
{
const char* strOutPrdNo = em->FirstChildElement("OutPrdNo")->GetText();
m_OutPrdNoInfo.OutPrdNo = strOutPrdNo;
const char* strProductName = em->FirstChildElement("ProductName")->GetText();
m_OutPrdNoInfo.ProductName = strProductName;
m_ReturnParameter.vec_OutPrdNoInfo.push_back(m_OutPrdNoInfo);
}
}
/*<?xml version="1.0" encoding="UTF-8"?>
<ReturnParameter>
<Result>PASS</Result>
<ErrorCode />
<ErrorMessage />
<PlanNoList>
<PlanInfo>
<PlanID>190410023132-ff07df12-3b63-44e4-aede</PlanID>
<PlanNo>WO000001</PlanNo>
<OutPrdNo>PN00001</OutPrdNo>
<OutPrdVer>01</OutPrdVer>
<ProductName>X1</ProductName>
<Line>SMT-01</Line>
<QTY>10000</QTY>
<StartTime>2019-04-10 10:10:10</StartTime>
</PlanInfo>
<PlanInfo>
<PlanID>190412002313-ff07df12-3b63-44e4-aedf</PlanID>
<PlanNo>WO000002</PlanNo>
<OutPrdNo>PN00001</OutPrdNo>
<OutPrdVer>01</OutPrdVer>
<ProductName>X1</ProductName>
<Line>SMT-01</Line>
<QTY>5000</QTY>
<StartTime>2019-04-12 08:10:10</StartTime>
</PlanInfo>
</PlanNoList>
</ReturnParameter>*/
TiXmlElement* elemPlan = root->FirstChildElement("PlanNoList");
if (elemPlan!=NULL)
{
for(TiXmlElement* em = elemPlan->FirstChildElement(); em != NULL; em = em->NextSiblingElement())
{
const char* strPlanID = em->FirstChildElement("PlanID")->GetText();
m_PlanInfo.PlanID = strPlanID;
const char* strPlanNo = em->FirstChildElement("PlanNo")->GetText();
m_PlanInfo.PlanNo = strPlanNo;
const char* strOutPrdNo = em->FirstChildElement("OutPrdNo")->GetText();
m_PlanInfo.OutPrdNo = strOutPrdNo;
const char* strOutPrdVer = em->FirstChildElement("OutPrdVer")->GetText();
m_PlanInfo.OutPrdVer = strOutPrdVer;
const char* strProductName = em->FirstChildElement("ProductName")->GetText();
m_PlanInfo.ProductName = strProductName;
const char* strLine = em->FirstChildElement("Line")->GetText();
m_PlanInfo.Line = strLine;
const char* strQTY = em->FirstChildElement("QTY")->GetText();
m_PlanInfo.QTY = strQTY;
const char* strStartTime = em->FirstChildElement("StartTime")->GetText();
m_PlanInfo.StartTime = strStartTime;
m_ReturnParameter.vec_PlanInfo.push_back(m_PlanInfo);
}
}
/*<?xml version="1.0" encoding="UTF-8"?>
<ReturnParameter>
<Result>PASS</Result>
<ErrorCode />
<ErrorMessage />
<PrdSNs>
<PrdSN>SN0000000001</PrdSN>
<PrdSN>SN0000000002</PrdSN>
<PrdSN>SN0000000003</PrdSN>
<PrdSN>SN0000000004</PrdSN>
</PrdSNs>
</ReturnParameter>*/
TiXmlElement* elemPrdSNs = root->FirstChildElement("PrdSNs");
if (elemPrdSNs!=NULL)
{
for(TiXmlElement* elem = elemPrdSNs->FirstChildElement(); elem != NULL; elem = elem->NextSiblingElement())
{
const char* strPrdSN = elem->GetText();
m_PrdSNInfo.PrdSN = strPrdSN;
m_ReturnParameter.vec_PrdSNInfo.push_back(m_PrdSNInfo);
}
}
delete myDocument;
}
void CXMLAnalysisDlg::OnBnClickedOk()
{
// TODO: 在此添加控件通知处理程序代码
CString strFilePath;
string path;
CString strFilter = _T("(*.xml)|*.xml||");
CFileDialog dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, strFilter);
dlg.m_ofn.lpstrTitle = _T("请选择一个XML文件");
if(dlg.DoModal() == IDOK)
{
strFilePath = dlg.GetPathName();
path=CW2A(strFilePath.GetString());
XMLAnalysisFromFile(path);
ShowResult();
}
else
return ;
}
void CXMLAnalysisDlg::ShowResult()
{
m_Result = _T("");
m_ErrorCode = _T("");
m_ErrorMessage = _T("");
m_Result.Format(_T("Result=%s"),m_ReturnParameter.Result);
m_ErrorCode.Format(_T("ErrorCode=%s"),m_ReturnParameter.ErrorCode);
m_ErrorMessage.Format(_T("ErrorMessage=%s"),m_ReturnParameter.ErrorMessage);
UpdateData(FALSE);
}
void CXMLAnalysisDlg::OnBnClickedOk2()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);
char* str=Cstring2Char(m_strXML);
XMLAnalysisFromString(str);
ShowResult();
delete []str;
str=NULL;
}
char* CXMLAnalysisDlg::Cstring2Char(const CString& strConvert)
{
long nAnsiCount = 0;
//先计算该宽字符串所对应ANSI字符串的长度,包括字符串结束符
nAnsiCount = WideCharToMultiByte(CP_ACP,0,strConvert,-1,NULL,0,NULL,NULL);
if (nAnsiCount<1) return NULL;
char* pChar = new char[nAnsiCount]; //申请空间
memset(pChar,0,nAnsiCount);
WideCharToMultiByte(CP_ACP,0,strConvert,-1,pChar,nAnsiCount,NULL,NULL);//转换字符
return pChar;
}