2012-06-27 79 views
2

我試圖開發一個SOAP客戶端將在OPC XML-DA規範訪問數據:HeregSOAP的與OPC XML-DA添加屬性

我使用gSOAP的提供的工具來生成gSOAP的來自OPC Foundations WSDL的頭文件。 (相關部分如下)

我似乎無法得到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。

+0

你如何在代碼中設置元素的值新gSOAP的? – Tisho

+0

實際上,是xsd:anyType類型的,我不知道它將如何具有另一個類型定義。對於我來說,所需的輸出看起來並不那麼有效......您能解釋爲什麼要輸出到以指定的格式? – Tisho

+0

在測試中,我的應用程序只能與一些xml-opc-da服務器通信。我比較了來自我的應用程序的數據包和來自OPC基金會的演示客戶端......只有數據包之間的變化是它們具有xsi:type =「xsd:unsignedint」作爲值標記的屬性。 – TechplexEngineer

回答

1

@Tisho,thanks for你的意見。

事實證明,OPC基金會提供的WSDL缺少在值元素上指定類型。我們的解決方案是增加一個S型:anyType的,這使我們能夠使用多態類型,如:
xsd_ 無符號整型
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> 

這裏是生成的頭

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. 
}; 
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,而不是< value>元素......還是覺得有些XS的:擴展xs:anyType的元素,但定義了一個xs:type .. 其實gSoap是一個很酷的產品,但爲了獲得最好的它,你需要學習如何破解它..