C ++:使用Mini-XML从XML文件加载长字符串时遇到问题

时间:2010-10-20 04:29:44

标签: c++ xml callback xml-parsing mini-xml

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

我能够加载几乎所有元素和属性,但是我在加载长字符串时遇到了问题。

以下是代码的相关部分:

//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;

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

<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>

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

为什么?

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

有什么建议吗?

编辑2:我将回调更改为OPAQUE,以便忽略空格,但现在它只返回NULL。

编辑3:我现在改变了方法来获取value.opaque而不是value.text.string。这使得“description”标签工作得很好,但是当我尝试将它加载到const char *时,“bar”标签仍会崩溃。我尝试从xml文件中删除引号等,看看是否导致它,但它没有帮助。

编辑4:我甚至删除了除了一个“资产”对象之外的所有对象,然后删除了它的“bar”元素,它仍然崩溃了。这绝对是奇怪的!

编辑5:好的,我隔离了问题代码:

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

但是,我把它集成到一个方法中,我使用的方法与描述元素(直接在它之前)相同,并且工作正常。有什么问题?

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

编辑7:最后!弄清楚了。我将MXML_DESCEND更改为MXML_DESCEND_FIRST,它运行正常。噢!!!!终于解脱了。谢谢你们!

2 个答案:

答案 0 :(得分:2)

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

人:

tree = mxmlLoadFile(NULL,fp,MXML_OPAQUE_CALLBACK);

这是你试过的吗?

我认为你还需要读取像

这样的值

tmp_str = temp_sub_node-&gt; child-&gt; value.opaque;

答案 1 :(得分:0)

如果您正在使用C ++,那么对于字符串处理“string”可以使用STL类。它可以加载任意数量的字符,直到内存限制。