【问题标题】:C++: Trouble loading long string from XML file using Mini-XMLC++:使用 Mini-XML 从 XML 文件加载长字符串时遇到问题
【发布时间】:2011-04-27 20:21:39
【问题描述】:

我正在使用 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:我什至删除了除一个“资产”对象之外的所有对象,然后删除了它的“栏”元素,但它仍然崩溃。这绝对是奇怪的!

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

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

但是,我已将其集成到一个方法中,与我用于描述元素(直接位于它之前)的方法相同,并且效果很好。怎么了?

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

编辑 7:终于!弄清楚了。我将 MXML_DESCEND 更改为 MXML_DESCEND_FIRST,它工作正常。哇!!!!终于解脱了。谢谢大家!

【问题讨论】:

  • 您是否尝试过遍历描述节点的所有子节点,以查看它是否将每个单词都存储为子节点?仅仅基于对文档的快速浏览,看起来 MiniXML 确实喜欢关心空格,所以默认的 TEXT 处理可能会将您的字符串拆分为多个子项。
  • 嗯,可能有用。我试试看。
  • 该死,现在它在加载时崩溃。每当我真正开始弄乱节点指针时,它就会这样做。

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


【解决方案1】:

您需要更换: 树 = mxmlLoadFile(NULL, fp, MXML_TEXT_CALLBACK);

作者:

tree = mxmlLoadFile(NULL, fp, MXML_OPAQUE_CALLBACK);

你试过了吗?

我认为你还需要像

一样阅读价值

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

【讨论】:

  • 一些赏金将会如约而至:)。
【解决方案2】:

如果您使用 C++,则可以使用“字符串”STL 类来处理字符串。它可以加载任意数量的字符,直到内存限制。

【讨论】:

  • const char* 有内存以外的限制吗?
猜你喜欢
  • 1970-01-01
  • 2015-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多