65.9K
CodeProject 正在变化。 阅读更多。
Home

Schemeer,一个半 XML 和 JSON 处理程序

emptyStarIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

0/5 (0投票)

2012年10月25日

CPOL

2分钟阅读

viewsIcon

17248

downloadIcon

322

这是一个可以通过修改配置文件来处理 XML 文档或 JSON 的库。

引言

本文介绍了一个可以处理任何字符串树结构的应用,例如 XML 文档或 JSON 文档。我的应用需要一个模式文件和一个配置文件来定义目标文档结构。 

使用代码

我将输入文档抽象成一个由树节点组合而成的树结构。每个节点包含一个模式短语,每个短语由单词组合而成。单词是一个字符串向量。输入文档的每个字符在保存到单词中之前都有一个输入类型。输入类型包括: 

//
// The input object struct
//
enum ObjectType{
    NORMAL_WORD,
    KEY_WORD,
    INVALID_WORD,
    SEPARATE_LETTER,
    SPECIAL_LETTER,
    IGNORE_LETTER,
    NORMAL_LETTER,
    INVALID_LETTER,
    SCHEME_PHRASE
};  

关键字、无效单词、特殊字符、忽略字符、无效字符等等。这些字符和单词在应用程序初始化阶段输入的配置文件中定义。它们被保存在一个 Dictionary 类中。 

//The init function

bool Dictionary::init(std::string configFile){
 
    FILE *file = NULL;
    fopen_s(&file,configFile.c_str(),"r");
    if (file == NULL) return false;

    insertWords(file,KEY_WORD);
    insertLetters(file,SPECIAL_LETTER);
    insertLetters(file,SEPARATE_LETTER);
    insertLetters(file,IGNORE_LETTER);
    insertLetters(file,INVALID_LETTER);

    fclose(file);
    return true;
} 

配置文件的每一行都是一种输入对象类型,它们之间用 ',' 分隔。在过滤输入字符并将它们构建成单词之后,使用文件分析类来分析输入字符串并将它们组织成树模型。文件分析类使用 Scheme 类来匹配输入文档。匹配方程在模式文件中定义。

//Init Scheme class
void Scheme::init(std::string config){
    if (dictionary == NULL) return;
    FILE *file = NULL;
    fopen_s(&file,config.c_str(),"r");
    while(file != NULL && !feof(file)){
        std::string sentence;
        readSentence(file,sentence);
        if (sentence.empty() == true) continue;
        SchemePhrase equation;
        unsigned int offset = 0;
        analyzeSentence(sentence,offset,&equation);
        equations.push_back(equation);
    }
    if (file != NULL) fclose(file);
}  
//Analyze the  input object into tree elements</span> 
void FileAnalysis::analyze(){
    std::vector<InputObject*> elements;
    while(true){
        InputObject* object = fileReaders->getNextObject();
        if (object == NULL) break;
        elements.push_back(object);
    }
    std::vector<Memo> &process = scheme->match(elements);
    TreeNode *curNode = tree->getRoot();
    for(unsigned int p = 0; p < process.size(); ++p){
        Memo &m = process[p];
        if (m.operation->getType() == SCHEME_PHRASE){
            SchemePhrase * phrase = dynamic_cast<SchemePhrase*>(m.operation);
            if (phrase->getOperation() == UPCHILD){
                curNode = curNode->getFather();
            }else if (phrase->getOperation() == DOWNCHILD){
                curNode = curNode->getLastChild();
            }
        }else if (m.operation->getType() == NORMAL_WORD){
            curNode->makeChild(dynamic_cast<Word*>(m.operation)->getContent(),
                dynamic_cast<Word*>(m.object)->getContent());
        }
    }
}

树节点使用组件设计模式。它们中的每一个都有一个值和一个名称参数,并且具有指向其子节点的指针,这些子节点是相同类型。 

class BaseNode
{
public:
    BaseNode(void);
    ~BaseNode(void);


    void setName(std::string n){ name = n; }
    void setValue(std::string v){ value = v;}

    std::string getName(){return name;}
    std::string getValue(){return value;}
private:
    std::string name;
    std::string value;
};
class TreeNode :
    public BaseNode
{
public:
    TreeNode(TreeNode *father = NULL,std::string name="", std::string value = "");
    virtual ~TreeNode(void);

    TreeNode* getNode(std::string name, std::string value = "");

    void addNode(TreeNode node){elements.push_back(node);}
    TreeNode* makeChild(std::string name, std::string value = "");
    TreeNode* getFather();
    TreeNode* getLastChild();

    TreeNode* getElement(int i){return &elements[i];}
    unsigned int size(){return elements.size();}

    std::vector<TreeNode*> getNodes(std::string name, std::string value = "");
    std::string get(std::string name);
    std::vector<std::string> gets(std::string name);

    void clear();
private:
    TreeNode *father;
    std::vector<TreeNode> elements;
}; 

处理完输入文档后,可以通过名称值获取树的节点。

std::vector<TreeNode*> TreeNode::getNodes(std::string name, std::string value){
    std::vector<TreeNode *> result;
    for(unsigned int i = 0; i < elements.size(); ++i){
        if (elements[i].getName() == name && (value == "" || elements[i].getValue() == value)){
            result.push_back(&(elements[i]));
        }
    }
    return result;
} 

示例

初始化模式文件和配置文件

ModelTree tree;
Dictionary dic;
Scheme sch(&dic);
FileAnalysis analysis;
TreeNode * root;

analysis.setDictionary(&dic);
analysis.setScheme(&sch);
analysis.setTree(&tree);

dic.init("config\\config.txt");
sch.init("config\\scheme.txt");
analysis.setFile("input.txt");
analysis.analyze(); 

处理输入文档并打印它们: 

root = tree.getRoot();
printNode(root,0); 

然后处理 JSON 文档。输入配置

meta;
44;125;93;123;91;34;58;
32;9;10;
0;1;2;3;4;5;6;7;8;11;12;13;14;15;16;17;18;19;20;21;22;23;24;25;26;27;28;29;30;31;127;
;

输入模式: 

;{"element":\d ["value"|\[ self [, self]* \]]1 \u [,"element":\d ["value"|\[ self [, self]* \]]1 \u]* }

输入文件

{ "programmers": [
{ "firstName": "Brett", "lastName":"McLaughlin", "email": "be@gmail.com" },
{ "firstName": "Jason", "lastName":"Hunter", "email": "abc@gmail.com" },
{ "firstName": "Elliotte", "lastName":"Harold", "email": "ell@163.com" }
],
"authors": [
{ "firstName": "Isaac", "lastName": "Asimov", "genre": "sciencefiction" },
{ "firstName": "Tad", "lastName": "Williams", "genre": "fantasy" },
{ "firstName": "Frank", "lastName": "Peretti", "genre": "christianfiction" }
],
"musicians": [
{ "firstName": "Eric", "lastName": "Clapton", "instrument": "guitar" },
{ "firstName": "Sergei", "lastName": "Rachmaninoff", "instrument": "piano" }
] } 

输出

然后处理 XMLdocument。 

输入配置

meta;
60;61;62;63;92;34;47;
32;9;10;
0;1;2;3;4;5;6;7;8;11;12;13;14;15;16;17;18;19;20;21;22;23;24;25;26;27;28;29;30;31;127;
;

输入模式: 

;<element\d [attribute[="\dvalue\u"]1]* >[value|self]*\u</element>
;<element\d [attribute[="\dvalue\u"]1]* \u/>

输入文件

<book title="facebook" >
<auther><lxdfigo name="lxd" >
<age value="16" />
</lxdfigo></auther>
<price value="216.0" />
<date value="2012-2-3" />
</book>
<book2 title="facebook" >
<auther><lxdfigo name="lxd" >
<age value="16" />
</lxdfigo></auther>
<price value="216.0" />
<date value="2012-2-3" />
</book2>
<book title="facebook" >
<auther><lxdfigo name="lxd" >
<age value="16" />
</lxdfigo></auther>
<price value="216.0" />
<date value="2012-2-3" />
</book>
<book2 title="facebook" >
<auther><lxdfigo name="lxd" >
<age value="16" />
</lxdfigo></auther>
<price value="216.0" />
<date value="2012-2-3" />
</book2> 

输出

© . All rights reserved.