📄 dom.h
字号:
/*dom.hgSOAP DOM interfacegSOAP XML Web services toolsCopyright (C) 2001-2005, Robert van Engelen, Genivia, Inc. All Rights Reserved.This part of the software is released under one of the following licenses:GPL, the gSOAP public license, or Genivia's license for commercial use.--------------------------------------------------------------------------------gSOAP public license.The contents of this file are subject to the gSOAP Public License Version 1.3(the "License"); you may not use this file except in compliance with theLicense. You may obtain a copy of the License athttp://www.cs.fsu.edu/~engelen/soaplicense.htmlSoftware distributed under the License is distributed on an "AS IS" basis,WITHOUT WARRANTY OF ANY KIND, either express or implied. See the Licensefor the specific language governing rights and limitations under the License.The Initial Developer of the Original Code is Robert A. van Engelen.Copyright (C) 2000-2004 Robert A. van Engelen, Genivia inc. All Rights Reserved.--------------------------------------------------------------------------------GPL license.This program is free software; you can redistribute it and/or modify it underthe terms of the GNU General Public License as published by the Free SoftwareFoundation; either version 2 of the License, or (at your option) any laterversion.This program is distributed in the hope that it will be useful, but WITHOUT ANYWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR APARTICULAR PURPOSE. See the GNU General Public License for more details.You should have received a copy of the GNU General Public License along withthis program; if not, write to the Free Software Foundation, Inc., 59 TemplePlace, Suite 330, Boston, MA 02111-1307 USAAuthor contact information:engelen@genivia.com / engelen@acm.org--------------------------------------------------------------------------------A commercial use license is available from Genivia, Inc., contact@genivia.com--------------------------------------------------------------------------------*//**@mainpage The gSOAP level-2 DOM parserThe gSOAP level-2 DOM parser features "smart" XML namespace handling and can beused to mix gSOAP XML serializers with plain XML parsing. The DOM parser isalso an essential component of the wsse plugin to verify digital signatures.The DOM parser is not a stand-alone application. The DOM parser is integratedwith the SOAP engine to populate a node set and to render a node set in XML.Two files are needed to work with DOM node sets:- dom.h to use a DOM node set in a gSOAP header file with service definitions.- dom.cpp (or dom.c) to be linked with your application code.@section dom_1 Declaring DOM Node Sets in a gSOAP Header FileTo use the DOM node set with the data structures defined in a gSOAP headerfile, import the dom.h file into your header file:@code #import "dom.h"@endcodeBy importing dom.h two special data types @ref xsd__anyType and @refxsd__anyAttribute are available representing a hierarchical DOM node set ofelements and attributes, respectively. The DOM node element and attribute datastructures can be used within structs, classes, STL containers, and asarguments of service operations. For example:@code #import "dom.h" #import "wsu.h" class ns__myProduct { public: @char* wsu__Id; @xsd__anyAttribute atts; _wsu__Timestamp* wsu__Timestamp; char* name; int SKU; double price; xsd__anyType* elts; ns__myProduct(); ~ns__myProduct(); };@endcodeIt is important to declare the @ref xsd__anyType at the end of the struct orclass, since the DOM parser consumes any XML element (the field name, 'elts' inthis case, is irrelavant). Thus, the other fields must be defined first toensure they are populated first before the DOM node set is populated with anynon-previously matched XML element. Likewise, the @ref xsd__anyAttribute membershould be placed after the other attributes.Note that we also imported wsu.h as an example to show how to add a wsu:Idattribute to a struct or class if we want to digitally sign instances, and howto add a standardized wsu:Timestamp element to record creation and expirationtimes.To compile, run soapcpp2 (with -Iimport) and compile your code by linkingdom.cpp (or dom.c for C). Note that the DOM data structures are declared instdsoap2.h, while the DOM operations are defined in dom.cpp (or dom.c for C).Methods to populate and traverse DOM node sets will be explained later. First,let's take a look at parsing and generating XML documents.@section dom_2 Parsing and Generating XMLThe following examples assume that the soapcpp2 compiler was used on a headerfile (just the dom.h file will do) and the generated soapC.cpp or (soapC.c forC) code was compiled and linked with dom.cpp (or dom.c for C), stdsoap2.cpp (orstdsoap2.c) and the example application code. The generated namespace tableshould also be used, since the namespace bindings are relevant for consumingand producing XML for DOM node sets. Therefore, each of the example codesin this documentation is assumed to start with the following two includes:@code #include "soapH.h" // generated by soapcpp2 #include "ns.nsmap" // a namespace table with the XML namespace used@endcodeThe C++ std::iostream operators are overloaded to parse XML octet streams intonode sets and to emit XML from node sets:@code soap_dom_element dom; dom.soap = soap_new1(SOAP_DOM_TREE | SOAP_C_UTFSTRING); cin >> dom; // parse XML if (dom.soap->error) ... // parse error cout << dom; // display XML if (dom.soap->error) ... // output error soap_destroy(dom.soap); soap_end(dom.soap); soap_done(dom.soap); free(dom.soap);@endcodeIn the example above we copied an XML document from stdin to stdout.In C we use the DOM "serializers" to accomplish this as follows:@code soap_dom_element dom; dom.soap = soap_new1(SOAP_DOM_TREE | SOAP_C_UTFSTRING); dom.soap->recvfd = stdin; if (soap_begin_recv(dom.soap) || NULL != soap_in_xsd__anyType(dom.soap, NULL, &dom, NULL) || soap_end_recv(dom.soap)) ... // parse error dom.soap->sendfd = stdout; if (soap_begin_send(dom.soap) || soap_out_xsd__anyType(dom.soap, NULL, 0, &dom, NULL) || soap_end_send(dom.soap)) ... // output error soap_end(dom.soap); soap_done(dom.soap); free(dom.soap);@endcodeThe SOAP_DOM_NODE flag is used to instruct the parser to populate a DOM nodeset with deserialized C and C++ data structures using the data type'sdeserializers that were generated with soapcpp2 from a header file with thedata type declarations. Suppose for example that the following header file wasused (in fact, this declaration appears in wsu.h):@code typedef struct _wsu__Timestamp { @char* wsu__Id; char* Created; char* Expires; } _wsu__Timestamp;@endcodeNote that the leading underscore of the type name indicates an XML elementdefinition (rather than a complexType definition), so the name of the data typeis relevant when comparing XML element tags to C/C++ data types by thedeserializers.When an XML document is parsed with one or more <wsu:Timestamp> elements, theDOM will be automatically populated with the _wsu__Timestamp objects. Supposethe XML document root is a <wsu:Timestamp>, then the root node of the DOM is a_wsu__Timestamp object:@code soap_dom_element dom; dom.soap = soap_new1(SOAP_DOM_NODE); cin >> dom; // parse XML if (dom.soap->error) ... // parse error if (dom.type == SOAP_TYPE__wsu__Timestamp) { _wsu__Timestamp *t = (_wsu__Timestamp*)dom.node; cout << "Start " << (t->Created ? t->Created : "") << " till " << (t->Expires ? t->Expires : "") << endl; }@endcodeNote that the soapcpp2 compiler generates a unique type identification constantSOAP_TYPE_X for each data type X, which is used to determine the node's type inthe example above.When objects occur deeper within the DOM node set then the DOM tree should betraversed. This subject will be discussed next.@section dom_3 Traversing a DOM Node SetThe DOM node set is traversed with a C++ iterator or with the C functions @refsoap_dom_next_element and @ref soap_dom_next_attribute. For example, to walkthe node set visiting nodes in the same order as they appeared in the document,use:@code soap_dom_element dom; dom.soap = soap_new1(SOAP_DOM_TREE | SOAP_C_UTFSTRING); ... for (soap_dom_element::iterator iter = dom.begin(); iter != dom.end(); ++iter) for (soap_dom_attribute::iterator attr = (*iter).atts.begin(); attr != (*iter).atts.end(); ++attr) ...@endcodeIn C code, use:@code soap_dom_element dom, *iter; soap_dom_attribute *attr; dom.soap = soap_new1(SOAP_DOM_TREE | SOAP_C_UTFSTRING); ... for (iter = &dom; iter; iter = soap_dom_next_element(iter)) for (attr = iter->atts; attr; attr = soap_dom_next_attribute(attr)) ...@endcodeThe @ref soap_dom_element and @ref soap_dom_attribute structs form essentiallylinked lists, so it would not be too difficult to write your own tree walkers:- @ref soap_dom_element::prnt points to the parent soap_dom_element node.- @ref soap_dom_element::elts points to the linked list of child element nodes.- @ref soap_dom_element::atts points to the linked list of attribute nodes.The linked lists of sibling elements nodes and attribute nodes are respectively:- @ref soap_dom_element::next points to the next sibling element node.- @ref soap_dom_attribute::next points to the next attribute in the attribute list of an element node.Note that for a root node, the @ref soap_dom_element::prnt and @refsoap_dom_element::next are both NULL.Tag names of elements and attributes are stored in @ref soap_dom_element::nameand @ref soap_dom_attribute::name strings, respectively. The names are UTF-8encoded.XML namespace bindings are explicitly propagated throughout the DOM node setfor those elements and attributes that are namespace qualified (either with anamespace prefix or when they occur in a xmlns default namespace scope). Thenamespaces are stored in the @ref soap_dom_element::nstr and @refsoap_dom_attribute::nstr strings. The following example shows how to traverse aDOM node set and print the elements with their namespace URIs when present:@code soap_dom_element dom; dom.soap = soap_new1(SOAP_DOM_TREE | SOAP_C_UTFSTRING); cin >> dom; for (soap_dom_element::iterator iter = dom.begin(); iter != dom.end(); ++iter) { cout << "Element " << (*iter).name; if ((*iter).nstr) cout << " has namespace " << (*iter).nstr; cout << endl; } soap_destroy(dom.soap); soap_end(dom.soap); soap_done(dom.soap); free(dom.soap);@endcodeText content of a node is stored in the @ref soap_dom_element::data string inUTF-8 format. This string is populated if the SOAP_C_UTFSTRING flag was set.Otherwise the data content will be stored in the @ref soap_dom_element::widewide-character string.The following example prints those element nodes that have text content(in UTF-8 format):@code soap_dom_element dom; ... for (soap_dom_element::iterator iter = dom.begin(); iter != dom.end(); ++iter) { cout << "Element " << (*iter).name; if ((*iter).data) cout << " = " << (*iter).data; cout << endl; } ...@endcodeWhen a DOM node set contains deserialized objects (enabled with theSOAP_DOM_NODE flag), the @ref soap_dom_element::type and @refsoap_dom_element::node values are set:@code soap_dom_element dom; ... for (soap_dom_element::iterator iter = dom.begin(); iter != dom.end(); ++iter) { cout << "Element " << (*iter).name; if ((*iter).type) cout << "Element " << (*iter).name << " contains a deserialized object" << endl; cout << endl; } ...@endcode
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -