gSOAP - 到 C 结构的 XML 数据(也由 gSOAP 生成)

Posted

技术标签:

【中文标题】gSOAP - 到 C 结构的 XML 数据(也由 gSOAP 生成)【英文标题】:gSOAP - XML data to C struct (generated by gSOAP also) 【发布时间】:2013-11-03 01:11:54 【问题描述】:

我对使用 gSOAP 解析 XML 有一些疑问。 如果有人有这方面的经验,请给我一些帮助。谢谢:D

我以前从不了解 XML,现在我需要将 XML 解析为 C 中的结构。然后我找到了一些使用 gSOAP 数据绑定的建议。是的!它可以帮助我生成一个包含来自 XSD(XML 模式)的结构的头文件。但是现在,我也不知道如何处理 struct 或 XML 文件。我需要自动将 XML 数据放入结构中(我的意思是,如果 XSD 更改,代码也不必更改)。与我的问题有关的 gSOAP 有什么我不知道的吗?或者我必须自己编码才能输入数据?感谢您的关心和时间。

干杯!

----加法----

这就是我所做的,我在 Linux 的终端中工作: 我有一个名为 try.xsd 的 XSD 文件

<?xml version="1.0" encoding="utf-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name='Root'>
        <xs:complexType>
        <xs:sequence>
            <xs:element name='Customers'>
                <xs:complexType>
                    <xs:sequence>
                        <xs:element name='Customer' type='xs:string' minOccurs='0' maxOccurs='unbounded' />
                        <xs:element name='Order' type='xs:string' minOccurs='0' maxOccurs='unbounded' />
                    </xs:sequence>
                    <xs:attribute name='customerid' use='required' type='xs:integer'/>
                </xs:complexType>
        </xs:element>
        </xs:sequence>
    </xs:complexType>
</xs:element>
</xs:schema>

然后我对这个 XSD 文件使用 gSOAP:

我用 wsdl2h 生成了 try.h 文件

wsdl2h -c -a -o try.h -t typemap.dat try.xsd

然后我生成了其余文件:ns1.nsmap、soapC.c soapH.H soapClient.c soapServer.c soapStub.h by

soapcpp2 -c -t -L -I "/home/celia/Documents/gsoap-2.7/gsoap/import" try.h

然后制作.c 文件并包含soapH.h 和ns1.nsmap。还将 stdsoap2.h 和 stdsoap2.c 包含在您的文件夹中(您可以在 gSOAP 包中找到它们)。

在soapStub.h文件中,构建了结构体:

....
struct _ns1__Root_Customers

    int __sizeCustomer;     /* sequence of elements <Customer> */
    char **Customer;        /* optional element of type xsd:string */
    int __sizeOrder;        /* sequence of elements <Order> */
    char **Order;               /* optional element of type xsd:string */
    char *customerid;       /* required attribute of type xsd:integer */


struct _ns1__Root

    struct _ns1__Root_Customers Customers;        /* required element of type s-s-rf1:Akar-Customers */

....

所以现在,我很困惑如何编写使 XML 数据自动转到此结构的代码,而无需手动“Customers->customerid = node->children->content”。所以,如果 XSD 发生变化,我也不必更改代码。

【问题讨论】:

【参考方案1】:

在 C 中没有序列化/反序列化对象(不像在 C++ 或 c# 中),其中有填充结构的类。 您必须自己编写代码,借助“read”和“memcpy”函数。 这就是我所做的,我有同样的问题,但现在也许有一些我不知道的新东西。

【讨论】:

非常感谢您提供的信息!我总是使用 C++ 而不是 C。它会变成自动的吗?我的意思是如果我有 struct idInfo int id ;我可以自动将 5 放入结构吗?如何从结构中检测到名称“id”与 XML 元素中的名称“id”相同。对不起,如果我问了很多。这个问题最近真的很困扰我。谢谢! 成为自动的,你的意思是用 C 编写一个序列化对象,它可以采用空的 strutc 和参数中的 xml 文件名。我不知道如何知道 C 代码中的变量名。 嗯...关于将 XML 元素命名为结构的成员是由 gSOAP 完成的,但是将特定元素的值放入与元素名称同名的结构成员中实际上是问题所在。【参考方案2】:

您可以在 C++ 中使用 gSOAP 执行以下操作,方法是使用字符串流填充结构:

struct _ns1__Root_Customers customers;
struct soap *ctx = soap_new();
istringstream in;
in.str("<in><Customer>a</Customer><Order>b</Order><customerid>123</customerid></in>");
ctx->is = in;
soap_read__ns1__Root_Customers(ctx, &customers);
soap_free(ctx); // does not dealloc 'customers' data (soap_end(ctx) before soap_free() will)

在 C 中,您可以使用 FILE* fd 将源设置为从 ctx-&gt;recvfd = fd 读取。从 C 字符串读取数据有一个技巧,它涉及重新定义 ::frecv() 回调以从该字符串读取数据并将内容复制到引擎从中读取的内部缓冲区。这需要更多的工作来重新定义回调。

编辑:要回答您问题的第二部分,有一种方法可以使用您想要的任何名称声明结构成员,这是一个很少记录的功能:

struct _ns1__Root_Customers
 …
  char *whateveryouwant `customerid`;

其中成员名称后的 是限定或非限定XML 标记名称(谨慎使用)。

【讨论】:

啊,实际上,它要求我永远不会自己写元素的名称,所以如果我更改XSD(包括元素的名称和属性的名称),我不必更改代码.但是要访问结构成员,我应该知道成员名称。所以,我仍然需要手动编写名称。

以上是关于gSOAP - 到 C 结构的 XML 数据(也由 gSOAP 生成)的主要内容,如果未能解决你的问题,请参考以下文章

使用gSOAP工具生成onvif框架代码

SOAP嵌入式linux下的应用

gsoap使用总结

gSOAP 空答案

C语言通过gSoap调用天气预报的Webservice发布的服务(未实现动态调用,手动输入调用)

C语言通过gSoap调用自定义的Webservice发布的服务(未实现动态调用,手动输入调用)