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

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

#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 = "\r\n";
    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 //提示:自动阅卷结束唯一标识,请勿删除或增加。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值