使用C ++从XML文件返回除char *之外的数据类型的错误

时间:2013-02-26 04:58:10

标签: c++ xml xsd rapidxml

这是我第一次使用XML而且我正在尝试使用C ++从XML文件返回一个整数(实际上想要返回一个双精度但还没有那么远)。我正在使用RAPIDXML和以下实现:

所有文件都在同一目录中。

XML(firstxml.xml):

<?xml version="1.0"?>
<test xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xsi:noNamespaceSchemaLocation="firstxsd.xsd">
    <A>10</A>
    <B>Hello</B>
</test>

XML-Schema(firstxsd.xsd):

<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="test">
    <xs:complexType>
      <xs:sequence>
        <xs:element type="xs:integer" name="A"/>
        <xs:element type="xs:string" name="B"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

C ++(test.cxx):

#include <iostream>
#include <sstream>
#include <fstream>
#include "rapidxml-1.13/rapidxml.hpp"
#include "rapidxml-1.13/rapidxml_print.hpp"
#include <string>
#include <stdio.h>
#include <vector>

int main(int argc, char* argv[])
  {
    std::ifstream file ("firstxml.xml");
      if (file.is_open())
        {
          file.seekg(0,std::ios::end);
          int size = file.tellg();
          file.seekg(0,std::ios::beg);

          char* buffer = new char [size];

          file.read (buffer, size);
          file.close();

          rapidxml::xml_document<> doc;
          doc.parse<0>(buffer);
          rapidxml::xml_node<> *node = doc.first_node()->first_node();

          //Line which results in error
          std::cout << node->value()*10 << std::endl;

          delete[] buffer;
        }
  }

错误:

test.cxx:52:31: error: invalid operands of types ‘char*’ and ‘int’ to binary ‘operator*’

从我在线阅读的教程中,我相信我正在构建文件,因此从节点A解析到C ++文件中的值应该是一个整数。我注意到的一件事是在RAPIDXML手册中,value()的规范如下:

Ch* value() const;

Description: Gets value of node. Interpretation of value depends on type of node. Note that value will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse. Use value_size() function to determine length of the value.

Returns: Value of node, or empty string if node has no value.

所以函数定义说它总是返回一个字符指针,但是“值的解释取决于节点的类型”意味着它返回一个依赖于类型的值。

感谢您抽出宝贵时间查看我的问题,非常感谢任何帮助,

保罗。

3 个答案:

答案 0 :(得分:0)

我想您想要访问“属性”值,所以请执行类似......

的操作

cout&lt;&lt; “我的第一个节点的名称是:”&lt;&lt; doc.first_node() - &gt; name()&lt;&lt; “\ n” 个;

xml_node&LT;&GT; * node = doc.first_node(“foobar”);

cout&lt;&lt; “节点foobar具有价值”&lt;&lt; node-&gt; value()&lt;&lt; “\ n” 个;

for(xml_attribute&lt;&gt; * attr = node-&gt; first_attribute();      ATTR; attr = attr-&gt; next_attribute())

{     cout&lt;&lt; “节点foobar具有属性”&lt;&lt; attr-&gt; name()&lt;&lt; “”;

cout << "with value " << attr->value() << "\n";

}

还看一下rapidXML教程......

http://rapidxml.sourceforge.net/manual.html很简单!

答案 1 :(得分:0)

很难说短语“价值的解释取决于节点的类型”是什么意思。如果函数返回Ch pointer,它将始终返回此指针或导致运行时异常,如果库开发人员提供此类功能。当然,当您尝试将Ch*乘以int时,会出现编译时错误。

函数返回依赖于调用上下文的类型的唯一方法是使用一些特殊的用户定义的返回类型(VARIANT或类似的东西)。在我看来,Ch只是库的基本字符类型的伪语(charwchar_t)。

因此,通过“解释......”通知开发人员可能意味着用户必须根据节点类型(依次取决于用户定义的架构)对字符串进行正确解释。

要将数字的C字符串表示转换为相应的类型,您可以使用标准C库中的函数,例如atoi()(转换为int),atof()(加倍)等等上。

答案 2 :(得分:0)

如果我错了,有人会纠正我,我相信RapidXML只会因为其就地解析性质而将值作为某种形式的字符串给出。类模板可能用于处理char vs wide char或类似的东西,我不知道,我只使用char。

我在处理提取值时所做的是向rapidxml_utils.hpp添加一个帮助器类(可能真的把它放在任何地方但在那里有意义),并使用一些静态函数将xml节点或属性解析为值(或者默认值,如果它不解析)。

这些助手让我做了以下的事情:

    int Height = xml_helper::GetNodeInt(cur_node->first_node("Height"), 48);
    int Width = xml_helper::GetNodeInt(cur_node->first_attribute("Width"), 128);

在你的情况下,你可以使用我的助手类:

      //Line which results in error (altered to use my helper class, if node absent or not parse as integer uses zero)
      std::cout << xml_helper::GetNodeInt(node, 0)*10 << std::endl;

我的帮助程序类看起来像这样(我使用sscanf来获得某种程度的验证):

class xml_helper
{
public:
    // a couple little helpers, lets you do this:
    // int Height = xml_helper::GetNodeInt(cur_node->first_node("Height"), 48);
    // int Width = xml_helper::GetNodeInt(cur_node->first_node("Width"), 128);
    static int GetNodeInt(rapidxml::xml_base<>* node, int DefaultValue)
    {
        int temp;
        try
        {
            if (node == 0) return DefaultValue;
            if (sscanf(node->value(), "%d", &temp) != 1) return DefaultValue;
            return temp;
            //return atoi(node->value());
        }
        catch (...) { return DefaultValue; }
    }

    static unsigned int GetNodeUInt(rapidxml::xml_base<>* node, unsigned int DefaultValue)
    {
        unsigned int temp;
        try
        {
            if (node == 0) return DefaultValue;
            if (sscanf(node->value(), "%u", &temp) != 1) return DefaultValue;
            return temp;
            //return strtoul(node->value(), NULL, 0);
        }
        catch (...) { return DefaultValue; }
    }

    static long long GetNodeLL(rapidxml::xml_base<>* node, long long DefaultValue)
    {
        long long temp;
        try
        {
            if (node == 0) return DefaultValue;
            if (sscanf(node->value(), "%lld", &temp) != 1) return DefaultValue; //C99 covers %lld
            return temp;
            //return strtoll(node->value(), NULL, 0); //C++11, could use _strtoi64 in VS until then?
        }
        catch (...) { return DefaultValue; }
    }

    static double GetNodeDouble(rapidxml::xml_base<>* node, double DefaultValue)
    {
        double temp;
        try
        {
            if (node == 0) return DefaultValue;
            if (sscanf(node->value(), "%lf", &temp) != 1) return DefaultValue; // could use strtod
            return temp;
        }
        catch (...) { return DefaultValue; }
    }

    static std::string GetNodeStr(rapidxml::xml_base<>* node, std::string DefaultValue)
    {
        try
        {
            if (node == 0) return DefaultValue;
            return node->value();
        }
        catch (...) { return DefaultValue; }
    }
};

希望这可能对您或使用rapidxml的其他人有所帮助,并且需要快速获取整数,双精度或节点以外的任何其他内容。它当然可以扩展到其他类型,我现在只有我目前需要的类型,但你得到了它的要点。