2

OPC XML-DA 仕様を介してデータにアクセスする SOAP クライアントを開発しようとしています

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 を意味します。

4

2 に答える 2

1

@Tisho、ご意見ありがとうございます。

OPC Foundationによって提供されたWSDLには、value要素のタイプを指定する機能がなかったことがわかりました。私たちの解決策は、s:anyTypeのタイプを追加することでした。これにより、次のようなポリモーフィックタイプを使用できるようになりまし た
。xsd_unsignedInt xsd _string xsd__anyType

xsd__anyTypeから継承されたすべての型と、仮想のsoap_type関数が含まれているため、任意の型を使用して値に格納できます。次に、gSOAPはsoap_typeを魔法のように使用して、変数がどの型であるかを判断します。

OPC Foundationの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.
};
于 2012-06-28T14:58:13.223 に答える
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; 

この問題を解決する別の方法は、<Value>要素の代わりに生のxmlをシリアル化することです...またはxs:anyTypeを拡張するがxs:typeを定義するxs:elementを考えます。実際にはgSoapはクールな製品です。 、しかしそれを最大限に活用するには、それをハックする方法を学ぶ必要があります。

于 2012-06-27T18:55:25.920 に答える