C ++:使用Mini-XML从XML文件加载长字符串时遇到问题 [英] C++: Trouble loading long string from XML file using Mini-XML

查看:202
本文介绍了C ++:使用Mini-XML从XML文件加载长字符串时遇到问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用Mini-XML库来解析和XML文件。



我可以加载每个元素和属性,但我有麻烦加载一个长字符串。



这是代码的相关部分:

  //将XML文件加载到XmlO中
void load(wxString filenam){
//首先,将wxString转换为std :: string以保证安全性(char *是transient),然后转换为const char *
std :: string tmp_filenam = std :: string(filenam.mb_str());
const char * tmp_filenam2 = tmp_filenam.c_str();
//获取指向文件的指针
fp = fopen(tmp_filenam2,r);
//加载树
tree = mxmlLoadFile(NULL,fp,MXML_TEXT_CALLBACK);

//关闭文件(be nice!)
fclose(fp);

// Load< Systems> node
Asset_elem = mxmlWalkNext(tree,tree,MXML_DESCEND_FIRST);

//开始加载< asset>元素

//临时元素
mxml_node_t * node; //节点保存
mxml_node_t * subnode_pos; // pos nodes的子节点
mxml_node_t * subnode_GFX; // GFX节点的子节点
mxml_node_t * subnode_pres; //存在节点的子节点
mxml_node_t * subnode_gen; //一般节点的子节点
mxml_node_t * subnode_serv; //服务节点的子节点
mxml_node_t * subnode; // Subnode
const char * name_tmp; //资源名称的字符串
const char * tmp_str; //任何字符串:P
float x_pos; // X_pos Float
float y_pos; // Y_pos Float
const char * gfx_space;
const char * gfx_ext;
const char * pres_fac;
float pres_val;
int pres_range;
const char * plan_class;
int population;
bool land;
bool refuel;
bool bar;
bool tasks;
bool commodity;
bool outfits;
bool shipyard;
const char * descrip;
const char * bar_descrip;

//加载第一个资产
node = mxmlFindElement(Asset_elem,tree,asset,NULL,NULL,MXML_DESCEND);
//开始加载剩余的ssys元素(但如果第一个元素为NULL,则失败)
int i = 1;
while(node!= NULL){
//加载名称attrib
name_tmp = mxmlElementGetAttr(node,name);

//标记分支节点
// Pos元素
subnode_pos = mxmlFindElement(node,Asset_elem,pos,NULL,NULL,MXML_DESCEND);
// GFX Element
subnode_GFX = mxmlFindElement(node,Asset_elem,GFX,NULL,NULL,MXML_DESCEND);
//存在元素
subnode_pres = mxmlFindElement(node,Asset_elem,presence,NULL,NULL,MXML_DESCEND);
//一般元素
subnode_gen = mxmlFindElement(node,Asset_elem,general,NULL,NULL,MXML_DESCEND);
// Services子元素
subnode_serv = mxmlFindElement(subnode_gen,Asset_elem,services,NULL,NULL,MXML_DESCEND);

/ *********加载工作的例程******** /

//获取描述

const char * tmp_str;
mxml_node_t * temp_sub_node;
temp_sub_node = mxmlFindElement(subnode_gen,subnode_gen,description,NULL,NULL,MXML_DESCEND);
if(temp_sub_node!= NULL){
tmp_str = temp_sub_node-> child-> value.text.string;
}
else {
tmp_str = NULL;
}
delete tmp_str;
delete temp_sub_node;

这里是我需要解析的一个元素:

 < asset name =Ammu> 
< pos>
< x> 90.000000< / x>
< y> 2490.000000< / y>
< / pos>
< GFX>
< space> A00.png< / space>
< exterior> lava.png< / exterior>
< / GFX>
< presence>
< faction> Empire< / faction>
< value> 100.000000< / value>
< range> 2< / range>
< / presence>
< general>
< class> A< / class>
< population> 60000< / population>
< services>
< land />
< refuel />
< bar />
< missions />
< commod />
< outfits />
< / services>
< commodities>
< goods>食物< / commodity>
< commodity> Ore< / commodity>
< commodity>工业品< / commodity>
< / commodities>
< description> Ammu是一个通常平静的行星,一旦人习惯了不断轰鸣的熔岩流。熔岩爆发通常在地下航天港感觉到,但它似乎没有阶段的当地人安慰你。< / description>
< bar> Ammu太空港酒吧,由于其寒冷的温度,被称为散热器,与车站的其余部分相比。虽然主要是因为他们的温度知道,这不是说他们不能鞭打一个平均泛银Gargle Blaster。< / bar>
< / general>
< tech>
< item>基本套装1< / item>
< / tech>
< / asset>

我只能从描述标签获取第一个单词。



为什么?



编辑1:我试图切换到std :: string,但MiniXML库返回一个const char *,显然不能持有这么长的字符串。



任何建议?



编辑2:我将回调改为OPAQUE它会忽略空白,但现在它只是返回NULL。



编辑3:我现在改变了方法获取value.opaque而不是value.text.string。这使得描述标签工作很好,但是bar标签仍然崩溃,当我尝试加载到一个const char *。我试图从xml文件中删除引号等,看看是否是造成它,但它没有帮助。



编辑4:我甚至删除除了一个asset对象,然后是bar元素,它仍然崩溃。这是绝对奇怪!



编辑5:好吧,我孤立的问题代码片:

  tmp_str = temp_sub_node-> child-> value.opaque; 

但是,我已经集成到一个方法中,我使用的描述元素它直接在它之前),并且工作正常。什么是错的?



编辑6:奇怪的是,当我将搜索字符串更改为bar时,它会正常失败(即返回NULL)。只有当我把它改为bar(我需要的元素),它崩溃。这是保留的关键字还是mini xml不喜欢的东西?



编辑7:最后!弄清楚了。我将MXML_DESCEND更改为MXML_DESCEND_FIRST,工作正常。为什么?终于解脱了。

解决方案

您需要替换:
tree = mxmlLoadFile(NULL,fp,MXML_TEXT_CALLBACK);

由:



tree = mxmlLoadFile(NULL,fp,MXML_OPAQUE_CALLBACK);



这是你尝试过的吗?



我认为你还需要读取值



tmp_str = temp_sub_node-> child-> value.opaque;


I'm using the Mini-XML library to parse and XML file.

I am able to load just about every element and attribute, but I am having trouble loading a long string.

Here is the relevant part of the code:

//Load XML file into XmlO
    void load(wxString filenam){
        //First, convert wxString to std::string for safety (char* is transient), then to const char*
        std::string tmp_filenam = std::string(filenam.mb_str());
        const char* tmp_filenam2 = tmp_filenam.c_str();
        //Get pointer to file
        fp = fopen(tmp_filenam2,"r");
        //Load tree
        tree = mxmlLoadFile(NULL, fp, MXML_TEXT_CALLBACK);

        //Close file (be nice!)
        fclose(fp);

        //Load <Systems> node
        Asset_elem = mxmlWalkNext(tree, tree, MXML_DESCEND_FIRST);

        //Start loading <asset> elements

        //Temporary Elements
        mxml_node_t *node; //Node to save
        mxml_node_t *subnode_pos; //Subnode for pos nodes
        mxml_node_t *subnode_GFX; //Subnode for GFX nodes
        mxml_node_t *subnode_pres; //Subnode for presence nodes
        mxml_node_t *subnode_gen; //Subnode for general nodes
        mxml_node_t *subnode_serv; //Subnode for services nodes
        mxml_node_t *subnode; //Subnode
        const char* name_tmp; //String for names of asset
        const char* tmp_str; //String for anything :P
        float x_pos; //X_pos Float
        float y_pos; //Y_pos Float
        const char* gfx_space;
        const char* gfx_ext;
        const char* pres_fac;
        float pres_val;
        int pres_range;
        const char* plan_class;
        int population;
        bool land;
        bool refuel;
        bool bar;
        bool missions;
        bool commodity;
        bool outfits;
        bool shipyard;
        const char* descrip;
        const char* bar_descrip;

        //Load first asset
        node = mxmlFindElement(Asset_elem, tree, "asset", NULL, NULL, MXML_DESCEND);
        //Start loading the rest of the ssys elements (but fail if first element is NULL)
        int i = 1;
        while (node != NULL){
            //Load name attrib
            name_tmp = mxmlElementGetAttr(node, "name");

            //Mark Branching nodes
            //Pos Element
            subnode_pos = mxmlFindElement(node, Asset_elem, "pos", NULL, NULL, MXML_DESCEND);
            //GFX Element
            subnode_GFX = mxmlFindElement(node, Asset_elem, "GFX", NULL, NULL, MXML_DESCEND);
            //Presence Element
            subnode_pres = mxmlFindElement(node, Asset_elem, "presence", NULL, NULL, MXML_DESCEND);
            //General Element
            subnode_gen = mxmlFindElement(node, Asset_elem, "general", NULL, NULL, MXML_DESCEND);
            //Services Sub-element
            subnode_serv = mxmlFindElement(subnode_gen, Asset_elem, "services", NULL, NULL, MXML_DESCEND);

/*********Loading routines that work********/

            //Get Descriptions

            const char * tmp_str;
            mxml_node_t *temp_sub_node;
            temp_sub_node = mxmlFindElement(subnode_gen, subnode_gen, "description", NULL, NULL, MXML_DESCEND);
            if(temp_sub_node != NULL){
                tmp_str = temp_sub_node->child->value.text.string;
            }
            else{
                tmp_str = NULL;
            }
        delete tmp_str;
        delete temp_sub_node;

Here is one element that I need to parse:

<asset name="Ammu">
  <pos>
   <x>90.000000</x>
   <y>2490.000000</y>
  </pos>
  <GFX>
   <space>A00.png</space>
   <exterior>lava.png</exterior>
  </GFX>
  <presence>
   <faction>Empire</faction>
   <value>100.000000</value>
   <range>2</range>
  </presence>
  <general>
   <class>A</class>
   <population>60000</population>
   <services>
    <land/>
    <refuel/>
    <bar/>
    <missions/>
    <commodity/>
    <outfits/>
   </services>
   <commodities>
    <commodity>Food</commodity>
    <commodity>Ore</commodity>
    <commodity>Industrial Goods</commodity>
   </commodities>
   <description>Ammu is a generally calm planet, once one is accustomed to the constant rumbling of the lava flows. Lava eruptions are often felt in the subterranean spaceport, but the way it doesn't seem to phase the locals reassures you.</description>
   <bar>The Ammu Spaceport Bar, known as "The Heatsink" due to its frigid temperatures, in contrast to the rest of the station. While primarily known for their temperature, that's not to say they can't whip up a mean Pan-Galactic Gargle Blaster.</bar>
  </general>
  <tech>
   <item>Basic Outfits 1</item>
  </tech>
 </asset>

I am only getting the first word from the description tag.

Why?

EDIT 1: I tried switching over to std::string, but the MiniXML library is returning a const char*, which apparently cannot hold such a long string.

Any suggestions?

EDIT 2: I changed the callback to OPAQUE so that it would ignore whitespaces, but now it just returns NULL.

EDIT 3: I now changed the methods to acquire value.opaque instead of value.text.string. This makes the "description" tag work great, but the "bar" tag still crashes when I try to load it into a const char*. I tried removing quotes and the like from the xml file to see if that was causing it, but it didn't help.

EDIT 4: I even removed all but one "asset" object, and then its "bar" element, and it still crashes. This is absolutely bizarre!

EDIT 5: Okay, I isolated the problem piece of code:

tmp_str = temp_sub_node->child->value.opaque;

However, I have this integrated into a method, the same method I am using for the description element (which directly precedes it), and that works fine. What is wrong?

EDIT 6: Oddly enough, when I change the search string to "bar ", it fails gracefully (i.e. returns NULL). It's only when I change it to "bar" (the element I need) that it crashes. Is this a reserved keyword or something that mini xml doesn't like?!

EDIT 7: FINALLY! Figured it out. I changed MXML_DESCEND to MXML_DESCEND_FIRST, and it works fine. WHEW!!!! What a relief. Thanks guys!

解决方案

You need to replace: tree = mxmlLoadFile(NULL, fp, MXML_TEXT_CALLBACK);

By:

tree = mxmlLoadFile(NULL, fp, MXML_OPAQUE_CALLBACK);

Is that what you tried?

I think you also need to read value like

tmp_str = temp_sub_node->child->value.opaque;

这篇关于C ++:使用Mini-XML从XML文件加载长字符串时遇到问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆