gsoap xs:choice渲染重复的父元素

时间:2017-10-19 09:50:44

标签: xsd gsoap

我有以下xsd片段:

    <xs:element name="MESSAGE">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="HEADER"/>
        <xs:element ref="BODY" minOccurs="1" maxOccurs="1"/>
      </xs:sequence>
      <xs:attribute name="VERSION" type="xs:unsignedInt" use="required"/>
    </xs:complexType>
  </xs:element>

...

<xs:element name="BODY">
    <xs:complexType>
      <xs:choice maxOccurs="2">
        <xs:element ref="LANE" minOccurs="0" maxOccurs="1"/>
        <xs:element ref="DEVICE" minOccurs="0" maxOccurs="unbounded"/>
        <xs:element ref="TRIP" minOccurs="0" maxOccurs="1"/>
        <xs:element ref="CASH_DISPOSAL" minOccurs="0" maxOccurs="1"/>
        <xs:element ref="ISSUE" minOccurs="0" maxOccurs="1"/>
        <xs:element ref="SHIFT" minOccurs="0" maxOccurs="1"/>
        <xs:element ref="SALE_RECHARGE" minOccurs="0" maxOccurs="1"/>
        <xs:element ref="LIFE" minOccurs="0" maxOc`enter code here`curs="1"/>
        <xs:element ref="OBSERVATION" minOccurs="0" maxOccurs="1"/>
        <xs:element ref="SURVEY_RESPONSE" minOccurs="0" maxOccurs="1"/>
        <xs:element ref="BLOCK_USER" minOccurs="0" maxOccurs="1"/>
        <xs:element ref="ACTION" minOccurs="0" maxOccurs="1"/>
        <xs:element ref="SPECIALACTION" minOccurs="0" maxOccurs="1"/>
        <xs:element ref="TEXT" minOccurs="0" maxOccurs="1"/>
        <xs:element ref="RESEND" minOccurs="0" maxOccurs="1"/>
        <xs:element ref="TRIP_RESEND" minOccurs="0" maxOccurs="1"/>
        <xs:element ref="DISPLAY" minOccurs="0" maxOccurs="1"/>
        <xs:element ref="DEBT_CANCELLATION" minOccurs="0"/>
      </xs:choice>
    </xs:complexType>
  </xs:element>

...

这是由gsoap生成的soapStub:

#ifndef SOAP_TYPE_union_BODY
#define SOAP_TYPE_union_BODY (88)
/* union serializable only when used as a member of a struct or class with a union variant selector */
union union_BODY
{
        #define SOAP_UNION_union_BODY_LANE_ (1) /**< union variant selector value for member LANE_ */
        LANE *LANE_;
        #define SOAP_UNION_union_BODY_DEVICE_   (2) /**< union variant selector value for member DEVICE_ */
        std::vector<std::shared_ptr<DEVICE> > *DEVICE_;
        #define SOAP_UNION_union_BODY_TRIP_ (3) /**< union variant selector value for member TRIP_ */
        TRIP *TRIP_;
        #define SOAP_UNION_union_BODY_CASH_USCOREDISPOSAL_  (4) /**< union variant selector value for member CASH_USCOREDISPOSAL_ */
        CASH_USCOREDISPOSAL *CASH_USCOREDISPOSAL_;
        #define SOAP_UNION_union_BODY_ISSUE_    (5) /**< union variant selector value for member ISSUE_ */
        ISSUE *ISSUE_;
        #define SOAP_UNION_union_BODY_SHIFT_    (6) /**< union variant selector value for member SHIFT_ */
        SHIFT *SHIFT_;
        #define SOAP_UNION_union_BODY_SALE_USCORERECHARGE_  (7) /**< union variant selector value for member SALE_USCORERECHARGE_ */
        SALE_USCORERECHARGE *SALE_USCORERECHARGE_;
        #define SOAP_UNION_union_BODY_LIFE_ (8) /**< union variant selector value for member LIFE_ */
        LIFE *LIFE_;
        #define SOAP_UNION_union_BODY_OBSERVATION_  (9) /**< union variant selector value for member OBSERVATION_ */
        OBSERVATION *OBSERVATION_;
        #define SOAP_UNION_union_BODY_SURVEY_USCORERESPONSE_    (10)    /**< union variant selector value for member SURVEY_USCORERESPONSE_ */
        SURVEY_USCORERESPONSE *SURVEY_USCORERESPONSE_;
        #define SOAP_UNION_union_BODY_BLOCK_USCOREUSER_ (11)    /**< union variant selector value for member BLOCK_USCOREUSER_ */
        BLOCK_USCOREUSER *BLOCK_USCOREUSER_;
        #define SOAP_UNION_union_BODY_ACTION_   (12)    /**< union variant selector value for member ACTION_ */
        ACTION *ACTION_;
        #define SOAP_UNION_union_BODY_SPECIALACTION_    (13)    /**< union variant selector value for member SPECIALACTION_ */
        SPECIALACTION *SPECIALACTION_;
        #define SOAP_UNION_union_BODY_TEXT_ (14)    /**< union variant selector value for member TEXT_ */
        TEXT *TEXT_;
        #define SOAP_UNION_union_BODY_RESEND_   (15)    /**< union variant selector value for member RESEND_ */
        RESEND *RESEND_;
        #define SOAP_UNION_union_BODY_TRIP_USCORERESEND_    (16)    /**< union variant selector value for member TRIP_USCORERESEND_ */
        TRIP_USCORERESEND *TRIP_USCORERESEND_;
        #define SOAP_UNION_union_BODY_DISPLAY_  (17)    /**< union variant selector value for member DISPLAY_ */
        DISPLAY *DISPLAY_;
        #define SOAP_UNION_union_BODY_DEBT_USCORECANCELLATION_  (18)    /**< union variant selector value for member DEBT_USCORECANCELLATION_ */
        DEBT_USCORECANCELLATION *DEBT_USCORECANCELLATION_;
};
#endif

/* D:\dd\projects\Deoban\source\Actros\developed\libs\upperLevelInterface\sep\messages.h:422 */
#ifndef SOAP_TYPE__union_BODY
#define SOAP_TYPE__union_BODY (67)
/* Choice: */
class SOAP_CMAC _union_BODY {
      public:
        /// Union with union union_BODY variant selector __union_BODY set to one of: SOAP_UNION_union_BODY_LANE_ SOAP_UNION_union_BODY_DEVICE_ SOAP_UNION_union_BODY_TRIP_ SOAP_UNION_union_BODY_CASH_USCOREDISPOSAL_ SOAP_UNION_union_BODY_ISSUE_ SOAP_UNION_union_BODY_SHIFT_ SOAP_UNION_union_BODY_SALE_USCORERECHARGE_ SOAP_UNION_union_BODY_LIFE_ SOAP_UNION_union_BODY_OBSERVATION_ SOAP_UNION_union_BODY_SURVEY_USCORERESPONSE_ SOAP_UNION_union_BODY_BLOCK_USCOREUSER_ SOAP_UNION_union_BODY_ACTION_ SOAP_UNION_union_BODY_SPECIALACTION_ SOAP_UNION_union_BODY_TEXT_ SOAP_UNION_union_BODY_RESEND_ SOAP_UNION_union_BODY_TRIP_USCORERESEND_ SOAP_UNION_union_BODY_DISPLAY_ SOAP_UNION_union_BODY_DEBT_USCORECANCELLATION_
        int __union_BODY;
        union union_BODY _BODY;
      public:
        /// Return unique type id SOAP_TYPE__union_BODY
        virtual int soap_type(void) const { return SOAP_TYPE__union_BODY; }
        /// (Re)set members to default values
        virtual void soap_default(struct soap*);
        /// Serialize object to prepare for SOAP 1.1/1.2 encoded output (or with SOAP_XML_GRAPH) by analyzing its (cyclic) structures
        virtual void soap_serialize(struct soap*) const;
        /// Output object in XML, compliant with SOAP 1.1 encoding style, return error code or SOAP_OK
        virtual int soap_put(struct soap*, const char *tag, const char *type) const;
        /// Output object in XML, with tag and optional id attribute and xsi:type, return error code or SOAP_OK
        virtual int soap_out(struct soap*, const char *tag, int id, const char *type) const;
        /// Get object from XML, compliant with SOAP 1.1 encoding style, return pointer to object or NULL on error
        virtual void *soap_get(struct soap*, const char *tag, const char *type);
        /// Get object from XML, with matching tag and type (NULL matches any tag and type), return pointer to object or NULL on error
        virtual void *soap_in(struct soap*, const char *tag, const char *type);
        /// Return a new object of type _union_BODY, default initialized and not managed by a soap context
        virtual _union_BODY *soap_alloc(void) const { return SOAP_NEW(_union_BODY); }
      public:
        /// Constructor with initializations
        _union_BODY()
        {
          __union_BODY = 0;
        }
        virtual ~_union_BODY() { }
        /// Friend allocator used by soap_new__union_BODY(struct soap*, int)
        friend SOAP_FMAC1 _union_BODY * SOAP_FMAC2 soap_instantiate__union_BODY(struct soap*, int, const char*, const char*, size_t*);
};
#endif

/* D:\dd\projects\Deoban\source\Actros\developed\libs\upperLevelInterface\sep\messages.h:170 */
#ifndef SOAP_TYPE_BODY
#define SOAP_TYPE_BODY (21)
/* complex XSD type 'BODY': */
class SOAP_CMAC BODY {
      public:
        /// Sequence of 0 to 2 elements 'BODY' of XSD type 'union-BODY' stored in dynamic array _BODY of length __size_BODY
        int __size_BODY;
        _union_BODY *_BODY;
        /// Context that manages this object
        struct soap *soap;
      public:
        /// Return unique type id SOAP_TYPE_BODY
        virtual int soap_type(void) const { return SOAP_TYPE_BODY; }
        /// (Re)set members to default values
        virtual void soap_default(struct soap*);
        /// Serialize object to prepare for SOAP 1.1/1.2 encoded output (or with SOAP_XML_GRAPH) by analyzing its (cyclic) structures
        virtual void soap_serialize(struct soap*) const;
        /// Output object in XML, compliant with SOAP 1.1 encoding style, return error code or SOAP_OK
        virtual int soap_put(struct soap*, const char *tag, const char *type) const;
        /// Output object in XML, with tag and optional id attribute and xsi:type, return error code or SOAP_OK
        virtual int soap_out(struct soap*, const char *tag, int id, const char *type) const;
        /// Get object from XML, compliant with SOAP 1.1 encoding style, return pointer to object or NULL on error
        virtual void *soap_get(struct soap*, const char *tag, const char *type);
        /// Get object from XML, with matching tag and type (NULL matches any tag and type), return pointer to object or NULL on error
        virtual void *soap_in(struct soap*, const char *tag, const char *type);
        /// Return a new object of type BODY, default initialized and not managed by a soap context
        virtual BODY *soap_alloc(void) const { return SOAP_NEW(BODY); }
      public:
        /// Constructor with initializations
        BODY()
        {
          __size_BODY = 0;
          _BODY = NULL;
          soap = (struct soap *)0;
        }
        virtual ~BODY() { }
        /// Friend allocator used by soap_new_BODY(struct soap*, int)
        friend SOAP_FMAC1 BODY * SOAP_FMAC2 soap_instantiate_BODY(struct soap*, int, const char*, const char*, size_t*);
};
#endif

我构建了如下消息:

MESSAGE soapMSG;
    HEADER soapHeader;
    BODY soapBody;
    LANE soapLane;

    ...

soapMSG.BODY_ = std::make_shared<BODY>(); // here i use a maping pointer to sharedptr

        soapMSG.BODY_->_BODY = new ((_union_BODY *)soap_malloc(ctx, 2 * sizeof(_unionBody))) _union_BODY[2];

        soapMSG.BODY_->__size_BODY = 2;

        soapMSG.BODY_->_BODY[0].__union_BODY = SOAP_UNION_union_BODY_LANE_;

        soapMSG.BODY_->_BODY[0]._BODY.LANE_ = &soapLane;

 ...

问题是: 当xsd包含xs:choice时,gsoap会生成一个通过动态数组使用的联合,问题是每个_union_Body gsoap都会使用包含的父元素呈现它

    <MESSAGE xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" VERSION="0">
        <HEADER SOCIETY="0" CONCESSION="0" FROM="456" TO="123" DATETIME="1970-01-01 01:00:00" SEQUENCE="0" CODE="8" LOCAL="0" MAINTENANCE="0" CHECKSUM="">
        </HEADER>
        <BODY>
            <BODY>
                <LANE STATUS="0" COLLECTOR="" SHIFT_NUMBER="0" BEGIN_DATETIME="2017-10-19 10:04:58" FUNCTION="1" WORK_MODE="2"></LANE>
            </BODY>
...
        </BODY>
    </MESSAGE>

我该如何避免这种情况?

提前谢谢!!

1 个答案:

答案 0 :(得分:0)

我找到了解决方案: 来自Genivia Doc “ 成员成为隐藏的XML元素,即当其名称以双下划线开头时,不会以XML格式呈现。这使得对数据成员集合进行排序成为可能,基本上通过形成一系列可以选择或重复的元素。“ 然后我修改了gsoap从

生成的.h
/// @brief Top-level root element "":BODY
/// @brief "":BODY is a complexType.
///
/// class BODY operations:
/// - BODY* soap_new_BODY(soap*) allocate and default initialize
/// - BODY* soap_new_BODY(soap*, int num) allocate array and default initialize values
/// - BODY* soap_new_req_BODY(soap*, ...) allocate, set required members
/// - BODY* soap_new_set_BODY(soap*, ...) allocate, set all public members
/// - BODY::soap_default(soap*) default initialize members
/// - int soap_read_BODY(soap*, BODY*) deserialize from a stream
/// - int soap_write_BODY(soap*, BODY*) serialize to a stream
/// - BODY* BODY::soap_dup(soap*) returns deep copy of BODY, copies the (cyclic) graph structure when a context is provided, or (cycle-pruned) tree structure with soap_set_mode(soap, SOAP_XML_TREE) (use soapcpp2 -Ec)
/// - BODY::soap_del() deep deletes BODY data members, use only after BODY::soap_dup(NULL) (use soapcpp2 -Ed)
class BODY
{ public:
//  BEGIN CHOICE <xs:choice maxOccurs="2">
   $int                                  __size_BODY                    0:2;
    class ___union_BODY
    {
   $int                                  __union_BODY                  ;    ///< Union union_BODY selector: set to SOAP_UNION_union_BODY_<fieldname>
/// Union for choice in BODY.
    union union_BODY
    {
/// Element reference ":""":LANE.
    LANE*                                LANE_                          0;  ///< Optional element.
/// Vector of std::shared_ptr<DEVICE>  element refs of length 0..unbounded.
    std::vector<std::shared_ptr<DEVICE> > *DEVICE_                        0;
/// Element reference ":""":TRIP.
    TRIP*                                TRIP_                          0;  ///< Optional element.
/// Element reference ":""":CASH_DISPOSAL.
    CASH_USCOREDISPOSAL*                 CASH_USCOREDISPOSAL_           0;  ///< Optional element.
/// Element reference ":""":ISSUE.
    ISSUE*                               ISSUE_                         0;  ///< Optional element.
/// Element reference ":""":SHIFT.
    SHIFT*                               SHIFT_                         0;  ///< Optional element.
/// Element reference ":""":SALE_RECHARGE.
    SALE_USCORERECHARGE*                 SALE_USCORERECHARGE_           0;  ///< Optional element.
/// Element reference ":""":LIFE.
    LIFE*                                LIFE_                          0;  ///< Optional element.
/// Element reference ":""":OBSERVATION.
    OBSERVATION*                         OBSERVATION_                   0;  ///< Optional element.
/// Element reference ":""":SURVEY_RESPONSE.
    SURVEY_USCORERESPONSE*               SURVEY_USCORERESPONSE_         0;  ///< Optional element.
/// Element reference ":""":BLOCK_USER.
    BLOCK_USCOREUSER*                    BLOCK_USCOREUSER_              0;  ///< Optional element.
/// Element reference ":""":ACTION.
    ACTION*                              ACTION_                        0;  ///< Optional element.
/// Element reference ":""":SPECIALACTION.
    SPECIALACTION*                       SPECIALACTION_                 0;  ///< Optional element.
/// Element reference ":""":TEXT.
    TEXT*                                TEXT_                          0;  ///< Optional element.
/// Element reference ":""":RESEND.
    RESEND*                              RESEND_                        0;  ///< Optional element.
/// Element reference ":""":TRIP_RESEND.
    TRIP_USCORERESEND*                   TRIP_USCORERESEND_             0;  ///< Optional element.
/// Element reference ":""":DISPLAY.
    DISPLAY*                             DISPLAY_                       0;  ///< Optional element.
/// Element reference ":""":DEBT_CANCELLATION.
    DEBT_USCORECANCELLATION*             DEBT_USCORECANCELLATION_       0;  ///< Optional element.
    }                                    _BODY                         ;
    }                                   *___BODY                         ;
//  END OF CHOICE
/// A handle to the soap struct context that manages this instance when instantiated by a context or NULL otherwise (automatically set).
    struct soap                         *soap                          ;
};

为:

let arr1 = [
    { id: "abdc4051", date: "2017-01-24" },
    { id: "abdc4052", date: "2017-01-22" }
];

let arr2 = [
    { id: "abdc4051", name: "ab" },
    { id: "abdc4052", name: "abc" }
];

let arr3 = [];

arr1.forEach((itm, i) => {
  arr3.push(Object.assign({}, itm, arr2[i]));
});

console.log(arr3);

请注意我已将类_unionody_BODY重命名为___unión_BODY,并将变量名_BODY重命名为___ BODY

非常感谢你。