1

这是我第一次使用 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 架构(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.

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

感谢您花时间查看我的问题,非常感谢您的帮助,

保罗。

4

3 回答 3

0

如果我错了,有人纠正我,我相信 RapidXML 只会给你一些字符串形式的值,因为它的就地解析性质。类模板可能用于处理 char 与宽 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 并需要一种快速方法从节点中获取整数、双精度数或其他内容的人有所帮助。它当然可以扩展到其他类型,我现在只有我需要的类型,但你明白了它的要点。

于 2013-10-24T15:37:53.297 回答
0

我猜您想访问“属性”值,所以请执行以下操作...

cout << "我的第一个节点的名称是:" << doc.first_node()->name() << "\n";

xml_node<> *node = doc.first_node("foobar");

cout << "节点 foobar 有值 " << node->value() << "\n";

for (xml_attribute<> *attr = node->first_attribute(); attr; attr = attr->next_attribute())

{ cout << "节点 foobar 具有属性 " << attr->name() << " ";

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

}

还可以看看 rapidXML 教程...

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

于 2013-02-26T05:12:05.533 回答
0

很难说“价值的解释取决于节点的类型”这句话是什么意思。如果函数返回Ch pointer,它将总是返回这样的指针或导致运行时异常,如果库开发人员提供了这样的功能。自然,当您尝试将 a 乘以Ch*int 时,您会得到编译时错误。

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

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

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

于 2013-02-26T05:29:54.700 回答