加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

庞果英雄会——xml字符串文件的解析

发布时间:2020-12-16 06:00:20 所属栏目:百科 来源:网络整理
导读:不知道为什么提交后总是失败, 本机编译通过。 总是使用用例失败。 #include iostream#include string#include listusing namespace std;struct XMLAttribute { string sName; // 名称 string sText; // 内容 XMLAttribute* pNext; // 弟属性 XMLAttribute*

不知道为什么提交后总是失败, 本机编译通过。 总是使用用例失败。

#include <iostream>
#include <string>
#include <list>
using namespace std;

struct XMLAttribute {
    string sName; // 名称
    string sText; // 内容
    XMLAttribute* pNext; // 弟属性
    XMLAttribute* pPre; // 兄属性
};

struct XMLNode {
    int nFloor; // 层数
    int nNum; // 该层第几个节点
    int nAttCount; // 属性个数
    int nChildCount; // 孩子节点个数
    string sName; // 名称
    XMLAttribute* pAttList;
    XMLNode* pParentNode; // 父节点指针
    XMLNode* pChildNode; // 孩子节点指针
    XMLNode* pPreBrother; // 兄节点指针
    XMLNode* pNextBrother; // 弟节点指针
};

void addNodeAttribute(XMLNode* pNode,XMLAttribute* pAtt) {
    //printf("%s%s","addNodeAttribute start: ",pNode->sName.c_str());
    XMLAttribute* pTempAtt = pNode->pAttList;
    if (!pTempAtt) {
        pNode->pAttList = pAtt;
    } else {
        while (pTempAtt->pNext) {
            pTempAtt = pTempAtt->pNext;
        }
        pTempAtt->pNext = pAtt;
        pAtt->pPre = pTempAtt;
    }

    pNode->nAttCount++;
    //printf("%s%d","addNodeAttribute end: ",pNode->nAttCount);
}

void addChildNode(XMLNode* pNode,XMLNode* pChildNode) {
    //printf("%s%s %s","addChildNode start: ",pNode->sName.c_str(),pChildNode->sName.c_str());
    XMLNode* pTempNode = pNode->pChildNode;
    if (!pTempNode) {
        pNode->pChildNode = pChildNode;
        pChildNode->nFloor = pNode->nFloor + 1;
        pChildNode->nNum = 1;
    } else {
        while (pTempNode->pNextBrother) {
            pTempNode = pTempNode->pNextBrother;
        }
        pTempNode->pNextBrother = pChildNode;
        pChildNode->pPreBrother = pTempNode;
        pChildNode->nFloor = pNode->nFloor + 1;
        pChildNode->nNum = pTempNode->nNum + 1;
    }
    pChildNode->pParentNode = pNode;
    pNode->nChildCount++;
    //printf("%s%d","addChildNode end: ",pNode->nChildCount);
}

void freeNodeAttributes(XMLNode* pNode) {
    //printf("%s%s","freeNodeAttributes start: ",pNode->sName.c_str());
    XMLAttribute* pTempAtt = pNode->pAttList;

    // 遍历删除
    while (pTempAtt) {
        XMLAttribute* pDelAtt = pTempAtt;
        pTempAtt = pTempAtt->pNext;
        //printf("%s%s %s","free XMLAttribute: ",pDelAtt->sName.c_str(),pDelAtt->sText.c_str());
        delete pDelAtt;
        pNode->nAttCount--;
    }
    pNode->pAttList = NULL;
    //printf("%s","freeNodeAttributes end");
}

// 释放节点内存,不释放兄弟节点,只对兄弟节点做双向链接
void freeNode(XMLNode* pNode) {
    // 首先处理兄弟节点链表,脱离兄弟链表
    if (pNode->pNextBrother) { // 存在弟节点
        if (pNode->pPreBrother) { // 存在兄节点
            pNode->pPreBrother->pNextBrother = pNode->pNextBrother;
            pNode->pNextBrother->pPreBrother = pNode->pPreBrother;
        } else if (pNode->pParentNode) { // 存在父节点
            pNode->pParentNode->pChildNode = pNode->pNextBrother;
        }
    }
    // 处理父节点
    if (pNode->pParentNode) {
        pNode->pParentNode->nChildCount--;
        if (pNode->pParentNode->nChildCount == 0) {
            pNode->pParentNode->pChildNode = NULL;
        }
    }

    pNode->pParentNode = NULL;

    // 通过栈遍历删除字节点
    list<XMLNode*> pNodesList;
    pNodesList.push_front(pNode);

    while (pNodesList.size()) {
        XMLNode* pTempNode = pNodesList.front();
        //printf("%s%s%d","cur node: ",pTempNode->sName.c_str(),pTempNode->nChildCount);

        if (!pTempNode->pChildNode) { // 无子节点出栈操作并删除
            // 父节点操作
            if (pTempNode->pParentNode) {
                pTempNode->pParentNode->nChildCount--;
                if (pTempNode->pParentNode->nChildCount == 0) {
                    pTempNode->pParentNode->pChildNode = NULL;
                }
            }

            pNodesList.pop_front(); // 从栈移除
            freeNodeAttributes(pTempNode);
            //printf("%s%s","free node: ",pTempNode->sName.c_str());
            delete pTempNode;
            pTempNode = NULL;
        }
        if (pTempNode) {
            // 子节点入栈
            XMLNode* pChildNode = pTempNode->pChildNode;
            while (pChildNode) {
                pNodesList.push_front(pChildNode);
                pChildNode = pChildNode->pNextBrother;
            }
        }
    }
}

string trimLeft(string& str) {
    string tempStr = str;
    string::size_type nLeftPos = 0;
    while (str.at(nLeftPos) == ' ' && nLeftPos < str.size()) {
        nLeftPos++;
    }
    tempStr = str.substr(nLeftPos);
    return tempStr;
}

string trimRight(string& str) {
    string tempStr = str;
    string::size_type nRightPos = str.size() - 1;
    int nCount = 0;
    while (str.at(nRightPos) == ' ' && nRightPos > 0) {
        nRightPos--;
        nCount++;
    }
    if (nCount) {
        tempStr = str.substr(0,str.size() - nCount);
    }
    return tempStr;
}

string strTrim(string& str) {
    string tempStr = str;
    tempStr = trimLeft(tempStr);
    tempStr = trimRight(tempStr);
    return tempStr;
}

enum NodeStatus {
    NodeError,NodeStart,NodeFinished,AttFinished
};

NodeStatus parsingSubstringToNode(string str,XMLNode* pNode) {
    NodeStatus status = NodeError;
    //printf("%s%s","parsingSubstringToNode start: ",str.c_str());
    if (str.at(0) == '<' && str.at(str.size() - 1) == '>') {
        if (str.at(1) == '/' && str.at(str.size() - 2) != '/') {
            status = NodeFinished;
            pNode->sName = str.substr(2,str.size() - 3);
            pNode->sName = strTrim(pNode->sName);
            //printf("%s",pNode->sName.c_str());
        } else if (str.at(str.size() - 2) == '/') {
            status = AttFinished;
            str = str.substr(1,str.size() - 2);

            //printf("%s%s","Att: ",str.c_str());
            string::size_type nLeftPos = 0;
            string::size_type nRightPos = str.find("=");

            // 查找属性
            while (nRightPos != string::npos) {
                //printf("%s",str.c_str());
                XMLAttribute* pAtt = new XMLAttribute;
                pAtt->pNext = NULL;
                pAtt->pPre = NULL;
                pAtt->sName = "";
                pAtt->sText = "";
                addNodeAttribute(pNode,pAtt);

                pAtt->sName = str.substr(nLeftPos,nRightPos);
                pAtt->sName = strTrim(pAtt->sName);
                str = str.substr(nRightPos + 1);
                nRightPos = str.find(""");
                if (nRightPos != string::npos) {
                    str = str.substr(nRightPos + 1);
                    nRightPos = str.find(""");
                    if (nRightPos != string::npos) {
                        pAtt->sText = str.substr(nLeftPos,nRightPos);
                        pAtt->sText = strTrim(pAtt->sText);
                        str = str.substr(nRightPos + 1);
                    }
                }
                nRightPos = str.find("=");
            }
        } else {
            status = NodeStart;
            pNode->sName = str.substr(1,str.size() - 2);
        }
    }
    //printf("%s","parsingSubstringToNode end");
    return status;
}

XMLNode* BuildTree(string& in) {
    XMLNode* pRootNode = NULL;
    list<XMLNode*> nodeList;
    string xmlNodeLeft = "<";
    string xmlNodeRight = ">";
    in = strTrim(in);
    while (in.size()) {
        XMLNode* pNode = new XMLNode;
        pNode->sName = "";
        pNode->nAttCount = 0;
        pNode->nChildCount = 0;
        pNode->nFloor = 0;
        pNode->nNum = 0;
        pNode->pAttList = NULL;
        pNode->pChildNode = NULL;
        pNode->pNextBrother = NULL;
        pNode->pParentNode = NULL;
        pNode->pPreBrother = NULL;
        string::size_type nLeftPos = 0;
        string::size_type nRightPos = in.find(xmlNodeRight);
        XMLNode* pTempNode = nodeList.front();
        if (in.at(nLeftPos) == '<' && nRightPos != string::npos) {
            string tempStr = in.substr(nLeftPos,nRightPos - nLeftPos + 1);

            NodeStatus status = parsingSubstringToNode(tempStr,pNode);
            switch (status) {
                case NodeStart: {
                    if (nodeList.size() > 0) {

                        addChildNode(pTempNode,pNode);
                    } else {
                        pRootNode = pNode;
                        pRootNode->nFloor = 0;
                    }
                    nodeList.push_front(pNode);
                    break;
                }
                case NodeFinished: {
                    if (nodeList.size() > 0) {
                        if (pTempNode->sName != pNode->sName) {
                            freeNode(pRootNode);
                            pRootNode = NULL;
                            return pRootNode;
                        } else {
                            nodeList.pop_front();
                            //printf("%s%s","NodeFinished: ",pNode->sName.c_str());
                            freeNode(pNode);
                            //printf("%s","NodeFinished");
                        }
                    }
                    break;
                }
                case AttFinished: {
                    if (nodeList.size() == 0) {
                        freeNode(pRootNode);
                        pRootNode = NULL;
                        return pRootNode;
                    } else {
                        // 赋值当前节点的属性
                        pTempNode->nAttCount = pNode->nAttCount;
                        pTempNode->pAttList = pNode->pAttList;
                        pNode->nAttCount = 0;
                        pNode->pAttList = NULL;
                        freeNode(pNode);
                    }
                    break;
                }
            }
            if (status == NodeError) {
                freeNode(pRootNode);
                pRootNode = NULL;
                return pRootNode;
            }
            if (nRightPos + 1 < in.size()) {
                in = in.substr(nRightPos + 1);
                in = trimLeft(in);
            } else {
                in = "";
            }
        } else {
            freeNode(pRootNode);
            pRootNode = NULL;
            return pRootNode;
        }
    }
    return pRootNode;
}

string getTreeString(XMLNode* pNode) {
    string str = "";
    string sNewLine = "rn";
    string sTab = "t";
    // 输出XML解析字符串
    // 通过栈遍历
    list<XMLNode*> pNodesList;
    pNodesList.push_front(pNode);
    while (pNodesList.size()) {
        XMLNode* pTempNode = pNodesList.front();
        pNodesList.pop_front();
        // 输出节点名
        for (int i = 0; i < pTempNode->nFloor; i++) {
            str += sTab;
        }
        str += pTempNode->sName;
        if (pTempNode->nFloor > 0) {
            char sNum[10];
            sprintf(sNum,"%d",pTempNode->nNum);
            str += " " + string(sNum);
        }
        str += sNewLine;
        // 输出属性
        XMLAttribute* pTempAtt = pTempNode->pAttList;
        while (pTempAtt) {
            for (int i = 0; i < pTempNode->nFloor + 1; i++) {
                str += sTab;
            }
            str += pTempAtt->sName + ":" + pTempAtt->sText + sNewLine;
            pTempAtt = pTempAtt->pNext;
        }
        // 字节点入栈
        XMLNode* pChildNode = pTempNode->pChildNode;
        // 首先逆序
        while (pChildNode && pChildNode->pNextBrother) {
            pChildNode = pChildNode->pNextBrother;
        }
        while (pChildNode) {
            pNodesList.push_front(pChildNode);
            pChildNode = pChildNode->pPreBrother;
        }
    }
    return str;
}

string ParsingXML(string str)
{
    //printf("%s","ParsingXML start");
    string result = "";
    string in = str;
    string xmlVersionLeft = "<?";
    string xmlVersionRight = "?>";

    // 首先查找XML版本并移除
    string::size_type nLeftPos = in.find(xmlVersionLeft);
    string::size_type nRightPos = 0;
    if (nLeftPos != string::npos) {
        nRightPos = in.find(xmlVersionRight);
        if (nRightPos == string::npos) {
            result = "Invalid XML string.";
            return result;
        } else {
            nRightPos += xmlVersionRight.size();
            in = in.substr(nRightPos);
        }
    }

    XMLNode* pRootNode = BuildTree(in);

    result = getTreeString(pRootNode);
    // 清理树
    freeNode(pRootNode);
    //printf("%s","ParsingXML end");
    return result;
}
//start 提示:自动阅卷起始唯一标识,请勿删除或增加。

int main()
{   
    string in = "<?xml version="1.0" ?><Books><Book><Name = "The C++ Programming Language" Author="Bjarne Stroustrup" /></Book><Book><Name = "Effective C++" Author = "Scott Meyers" /></Book></Books>";
    string out = ParsingXML(in);
    printf("%s",out); 
    return 0;
} 
//end //提示:自动阅卷结束唯一标识,请勿删除或增加。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读