【问题标题】:gSOAP with OPC XML-DA add attribute带有 OPC XML-DA 添加属性的 gSOAP
【发布时间】:2012-06-27 13:31:26
【问题描述】:

我正在尝试开发一个可以通过 OPC XML-DA 规范访问数据的 soap 客户端:Here

我使用 gSOAP 提供的工具从 OPC Foundations WSDL 生成 gSOAP 头文件。 (以下相关部分)

我似乎无法让 gSOAP 正确地向标签添加属性。 (见下面的输出部分)。是否有内置方法可以做到这一点,或者是否需要修改 WSDL/gSOAP 标头?

WSDL 提取:

<s:complexType name="ItemValue">
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="DiagnosticInfo" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" name="Value" />
<s:element minOccurs="0" maxOccurs="1" name="Quality" type="s0:OPCQuality" />
</s:sequence>
<s:attribute name="ValueTypeQualifier" type="s:QName" />
<s:attribute name="ItemPath" type="s:string" />
<s:attribute name="ItemName" type="s:string" />
<s:attribute name="ClientItemHandle" type="s:string" />
<s:attribute name="Timestamp" type="s:dateTime" />
<s:attribute name="ResultID" type="s:QName" />
</s:complexType>

生成的 gSOAP 标头

class ns1__ItemValue
{ public:
/// Element DiagnosticInfo of type xs:string.
    char*                                DiagnosticInfo                 0;  ///< Optional element.
/// Element 'Value' has no type or ref: assuming XML content.
    _XML                                 Value                          0;  ///< Optional element.
/// Element Quality of type "http://opcfoundation.org/webservices/XMLDA/1.0/":OPCQuality.
    ns1__OPCQuality*                     Quality                        0;  ///< Optional element.
/// Attribute ValueTypeQualifier of type xs:QName.
   @_QName                               ValueTypeQualifier             0;  ///< Optional attribute.
/// Attribute ItemPath of type xs:string.
   @char*                                ItemPath                       0;  ///< Optional attribute.
/// Attribute ItemName of type xs:string.
   @char*                                ItemName                       0;  ///< Optional attribute.
/// Attribute ClientItemHandle of type xs:string.
   @char*                                ClientItemHandle               0;  ///< Optional attribute.
/// Attribute Timestamp of type xs:dateTime.
   @time_t*                              Timestamp                      0;  ///< Optional attribute.
/// Attribute ResultID of type xs:QName.
   @_QName                               ResultID                       0;  ///< Optional attribute.
/// A handle to the soap struct that manages this instance (automatically set)
    struct soap                         *soap                          ;
};

生成的代码

class SOAP_CMAC ns1__ItemValue
{
public:
    char *DiagnosticInfo;   /* optional element of type xsd:string */
    char *Value;    /* optional element of type xsd:anyType */
    class ns1__OPCQuality *Quality; /* optional element of type ns1:OPCQuality */
    char *ValueTypeQualifier;   /* optional attribute */
    char *ItemPath; /* optional attribute */
    char *ItemName; /* optional attribute */
    char *ClientItemHandle; /* optional attribute */
    time_t *Timestamp;  /* optional attribute */
    char *ResultID; /* optional attribute */
    struct soap *soap;  /* transient */
public:
    virtual int soap_type() const { return 18; } /* = unique id SOAP_TYPE_ns1__ItemValue */
    virtual void soap_default(struct soap*);
    virtual void soap_serialize(struct soap*) const;
    virtual int soap_put(struct soap*, const char*, const char*) const;
    virtual int soap_out(struct soap*, const char*, int, const char*) const;
    virtual void *soap_get(struct soap*, const char*, const char*);
    virtual void *soap_in(struct soap*, const char*, const char*);
             ns1__ItemValue() : DiagnosticInfo(NULL), Value(NULL), Quality(NULL), ValueTypeQualifier(NULL), ItemPath(NULL), ItemName(NULL), ClientItemHandle(NULL), Timestamp(NULL), ResultID(NULL), soap(NULL) { }
    virtual ~ns1__ItemValue() { }
};

输出

<ns1:Items
    ClientItemHandle="Channel1.Device1"
    ItemName="Channel_1.Device_1.Tag_1"
    ValueTypeQualifier="xsd:unsignedInt">
    <Value
        xmlns="http://opcfoundation.org/webservices/XMLDA/1.0/">
        5
    </Value>
</ns1:Items>

需要的输出

<ns1:Items
    ClientItemHandle="Channel1.Device1"
    ItemName="Channel_1.Device_1.Tag_1"
    ValueTypeQualifier="xsd:unsignedInt">
    <Value
        xmlns="http://opcfoundation.org/webservices/XMLDA/1.0/"
        xsi:Type="xsd:unsignedInt">
        5
    </Value>
</ns1:Items>

输出是指生成并通过线路发送到远程服务器的 XML。

【问题讨论】:

  • 如何在代码中设置元素的值?
  • 事实上, 是 xsd:anyType 类型,我看不出它会如何定义另一种类型。对我来说,所需的输出似乎不太有效……可以你解释一下为什么你希望输出是指定的格式?
  • 在测试中,我的应用程序只会与一些 xml-opc-da 服务器通信。我比较了来自我的应用程序的数据包和来自 OPC 基金会的演示客户端......数据包之间的唯一变化是它们将 xsi:type="xsd:unsignedint" 作为值标签的属性。
  • 我们尝试在运行预构建步骤时将 -t 添加到 soapcpp2.exe,但这似乎只是将类型信息添加到复杂类型而不是原始类型。
  • 糟糕。我错过了你的第一个问题。我们有一个对 ItemValue 的引用,因此只需传入一个字符数组即可。 ItemValueRef->Value = "0";

标签: c++ xml wsdl gsoap opc


【解决方案1】:

这里有一些可能会有所帮助的东西。我现在无法测试它,所以这只是一个建议。查看“无效指针”:http://www.cs.fsu.edu/~engelen/soapdoc2.html#tth_sEc11.9

struct myStruct 
{ 
   int __type; // the SOAP_TYPE pointed to by p 
   void *p; 
};

据我了解,这用于序列化任何内容,并指定其类型。 因此,用此结构替换 Value 元素的 _XML 类型可能会起作用。 然后你只需要将 __type 属性设置为相应的值:

struct ns1_Value {
   int __type; // the SOAP_TYPE pointed to by p 
   void *p; 
}
struct ns1_Value value; 
int n; 
value.p = &n; 
value.__type = SOAP_TYPE_int; 

解决问题的另一种方法可能是序列化原始 xml 而不是 元素... 实际上 gSoap 是一个很酷的产品,但要充分利用它,您需要学习如何破解它..

【讨论】:

    【解决方案2】:

    @Tisho,感谢您的意见。

    事实证明,OPC Foundation 提供的 WSDL 缺少在 value 元素上指定类型。我们的解决方案是添加一个 s:anyType 类型,这允许我们使用多态类型,例如:
    xsd_unsignedInt
    xsd
    _string
    xsd__anyType

    由于所有类型都继承自 xsd__anyType,并且包含了一个虚拟 soap_type 函数,我们可以使用任何类型,并将它们存储在值中,然后 gSOAP 神奇地使用 soap_type 来确定 var 是什么类型。

    修改了 OPC 基金会的 WSDL 的相关部分:

    <s:complexType name="ItemValue">
      <s:sequence>
        <s:element minOccurs="0" maxOccurs="1" name="DiagnosticInfo" type="s:string"/>
        <s:element minOccurs="0" maxOccurs="1" name="Value" type="s:anyType"/> <!-- Here -->
        <s:element minOccurs="0" maxOccurs="1" name="Quality" type="s0:OPCQuality"/>
      </s:sequence>
      <s:attribute name="ValueTypeQualifier" type="s:QName"/>
      <s:attribute name="ItemPath" type="s:string"/>
      <s:attribute name="ItemName" type="s:string"/>
      <s:attribute name="ClientItemHandle" type="s:string"/>
      <s:attribute name="Timestamp" type="s:dateTime"/>
      <s:attribute name="ResultID" type="s:QName"/>
    </s:complexType>
    

    这是新的 gSOAP 生成的标头

    class ns1__ItemValue : public xsd__anyType
    { public:
    /// Element DiagnosticInfo of type xs:string.
        char*                                DiagnosticInfo                 0;  ///< Optional element.
    /// Element Value of type xs:anyType.
        xsd__anyType*                        Value                          0;  ///< Optional element.
    /// Element Quality of type "http://opcfoundation.org/webservices/XMLDA/1.0/":OPCQuality.
        ns1__OPCQuality*                     Quality                        0;  ///< Optional element.
    /// Attribute ValueTypeQualifier of type xs:QName.
       @_QName                               ValueTypeQualifier             0;  ///< Optional attribute.
    /// Attribute ItemPath of type xs:string.
       @char*                                ItemPath                       0;  ///< Optional attribute.
    /// Attribute ItemName of type xs:string.
       @char*                                ItemName                       0;  ///< Optional attribute.
    /// Attribute ClientItemHandle of type xs:string.
       @char*                                ClientItemHandle               0;  ///< Optional attribute.
    /// Attribute Timestamp of type xs:dateTime.
       @time_t*                              Timestamp                      0;  ///< Optional attribute.
    /// Attribute ResultID of type xs:QName.
       @_QName                               ResultID                       0;  ///< Optional attribute.
    };
    

    【讨论】:

      猜你喜欢
      • 2021-01-07
      • 2016-09-29
      • 1970-01-01
      • 1970-01-01
      • 2020-04-08
      • 1970-01-01
      • 2021-08-04
      • 2013-06-01
      • 1970-01-01
      相关资源
      最近更新 更多