~alexharrington/xibo/pyclient-1.1.0a22

« back to all changes in this revision

Viewing changes to server/3rdparty/nuSoap/class.xmlschema.php

  • Committer: Alex Harrington
  • Date: 2009-12-31 11:38:50 UTC
  • Revision ID: alex@longhill.org.uk-20091231113850-bz5flhqq2gsw0qxf
Converted to 2.0 repo format and fixed lineendings

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
<?php
2
 
 
3
 
 
4
 
 
5
 
 
6
 
/**
7
 
* parses an XML Schema, allows access to it's data, other utility methods.
8
 
* imperfect, no validation... yet, but quite functional.
9
 
*
10
 
* @author   Dietrich Ayala <dietrich@ganx4.com>
11
 
* @author   Scott Nichol <snichol@users.sourceforge.net>
12
 
* @version  $Id: class.xmlschema.php,v 1.49 2007/11/06 14:17:53 snichol Exp $
13
 
* @access   public
14
 
*/
15
 
class nusoap_xmlschema extends nusoap_base  {
16
 
        
17
 
        // files
18
 
        var $schema = '';
19
 
        var $xml = '';
20
 
        // namespaces
21
 
        var $enclosingNamespaces;
22
 
        // schema info
23
 
        var $schemaInfo = array();
24
 
        var $schemaTargetNamespace = '';
25
 
        // types, elements, attributes defined by the schema
26
 
        var $attributes = array();
27
 
        var $complexTypes = array();
28
 
        var $complexTypeStack = array();
29
 
        var $currentComplexType = null;
30
 
        var $elements = array();
31
 
        var $elementStack = array();
32
 
        var $currentElement = null;
33
 
        var $simpleTypes = array();
34
 
        var $simpleTypeStack = array();
35
 
        var $currentSimpleType = null;
36
 
        // imports
37
 
        var $imports = array();
38
 
        // parser vars
39
 
        var $parser;
40
 
        var $position = 0;
41
 
        var $depth = 0;
42
 
        var $depth_array = array();
43
 
        var $message = array();
44
 
        var $defaultNamespace = array();
45
 
    
46
 
        /**
47
 
        * constructor
48
 
        *
49
 
        * @param    string $schema schema document URI
50
 
        * @param    string $xml xml document URI
51
 
        * @param        string $namespaces namespaces defined in enclosing XML
52
 
        * @access   public
53
 
        */
54
 
        function nusoap_xmlschema($schema='',$xml='',$namespaces=array()){
55
 
                parent::nusoap_base();
56
 
                $this->debug('nusoap_xmlschema class instantiated, inside constructor');
57
 
                // files
58
 
                $this->schema = $schema;
59
 
                $this->xml = $xml;
60
 
 
61
 
                // namespaces
62
 
                $this->enclosingNamespaces = $namespaces;
63
 
                $this->namespaces = array_merge($this->namespaces, $namespaces);
64
 
 
65
 
                // parse schema file
66
 
                if($schema != ''){
67
 
                        $this->debug('initial schema file: '.$schema);
68
 
                        $this->parseFile($schema, 'schema');
69
 
                }
70
 
 
71
 
                // parse xml file
72
 
                if($xml != ''){
73
 
                        $this->debug('initial xml file: '.$xml);
74
 
                        $this->parseFile($xml, 'xml');
75
 
                }
76
 
 
77
 
        }
78
 
 
79
 
    /**
80
 
    * parse an XML file
81
 
    *
82
 
    * @param string $xml path/URL to XML file
83
 
    * @param string $type (schema | xml)
84
 
        * @return boolean
85
 
    * @access public
86
 
    */
87
 
        function parseFile($xml,$type){
88
 
                // parse xml file
89
 
                if($xml != ""){
90
 
                        $xmlStr = @join("",@file($xml));
91
 
                        if($xmlStr == ""){
92
 
                                $msg = 'Error reading XML from '.$xml;
93
 
                                $this->setError($msg);
94
 
                                $this->debug($msg);
95
 
                        return false;
96
 
                        } else {
97
 
                                $this->debug("parsing $xml");
98
 
                                $this->parseString($xmlStr,$type);
99
 
                                $this->debug("done parsing $xml");
100
 
                        return true;
101
 
                        }
102
 
                }
103
 
                return false;
104
 
        }
105
 
 
106
 
        /**
107
 
        * parse an XML string
108
 
        *
109
 
        * @param    string $xml path or URL
110
 
    * @param    string $type (schema|xml)
111
 
        * @access   private
112
 
        */
113
 
        function parseString($xml,$type){
114
 
                // parse xml string
115
 
                if($xml != ""){
116
 
 
117
 
                // Create an XML parser.
118
 
                $this->parser = xml_parser_create();
119
 
                // Set the options for parsing the XML data.
120
 
                xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
121
 
 
122
 
                // Set the object for the parser.
123
 
                xml_set_object($this->parser, $this);
124
 
 
125
 
                // Set the element handlers for the parser.
126
 
                        if($type == "schema"){
127
 
                        xml_set_element_handler($this->parser, 'schemaStartElement','schemaEndElement');
128
 
                        xml_set_character_data_handler($this->parser,'schemaCharacterData');
129
 
                        } elseif($type == "xml"){
130
 
                                xml_set_element_handler($this->parser, 'xmlStartElement','xmlEndElement');
131
 
                        xml_set_character_data_handler($this->parser,'xmlCharacterData');
132
 
                        }
133
 
 
134
 
                    // Parse the XML file.
135
 
                    if(!xml_parse($this->parser,$xml,true)){
136
 
                        // Display an error message.
137
 
                                $errstr = sprintf('XML error parsing XML schema on line %d: %s',
138
 
                                xml_get_current_line_number($this->parser),
139
 
                                xml_error_string(xml_get_error_code($this->parser))
140
 
                                );
141
 
                                $this->debug($errstr);
142
 
                                $this->debug("XML payload:\n" . $xml);
143
 
                                $this->setError($errstr);
144
 
                }
145
 
            
146
 
                        xml_parser_free($this->parser);
147
 
                } else{
148
 
                        $this->debug('no xml passed to parseString()!!');
149
 
                        $this->setError('no xml passed to parseString()!!');
150
 
                }
151
 
        }
152
 
 
153
 
        /**
154
 
         * gets a type name for an unnamed type
155
 
         *
156
 
         * @param       string  Element name
157
 
         * @return      string  A type name for an unnamed type
158
 
         * @access      private
159
 
         */
160
 
        function CreateTypeName($ename) {
161
 
                $scope = '';
162
 
                for ($i = 0; $i < count($this->complexTypeStack); $i++) {
163
 
                        $scope .= $this->complexTypeStack[$i] . '_';
164
 
                }
165
 
                return $scope . $ename . '_ContainedType';
166
 
        }
167
 
        
168
 
        /**
169
 
        * start-element handler
170
 
        *
171
 
        * @param    string $parser XML parser object
172
 
        * @param    string $name element name
173
 
        * @param    string $attrs associative array of attributes
174
 
        * @access   private
175
 
        */
176
 
        function schemaStartElement($parser, $name, $attrs) {
177
 
                
178
 
                // position in the total number of elements, starting from 0
179
 
                $pos = $this->position++;
180
 
                $depth = $this->depth++;
181
 
                // set self as current value for this depth
182
 
                $this->depth_array[$depth] = $pos;
183
 
                $this->message[$pos] = array('cdata' => ''); 
184
 
                if ($depth > 0) {
185
 
                        $this->defaultNamespace[$pos] = $this->defaultNamespace[$this->depth_array[$depth - 1]];
186
 
                } else {
187
 
                        $this->defaultNamespace[$pos] = false;
188
 
                }
189
 
 
190
 
                // get element prefix
191
 
                if($prefix = $this->getPrefix($name)){
192
 
                        // get unqualified name
193
 
                        $name = $this->getLocalPart($name);
194
 
                } else {
195
 
                $prefix = '';
196
 
        }
197
 
                
198
 
        // loop thru attributes, expanding, and registering namespace declarations
199
 
        if(count($attrs) > 0){
200
 
                foreach($attrs as $k => $v){
201
 
                // if ns declarations, add to class level array of valid namespaces
202
 
                                if(ereg("^xmlns",$k)){
203
 
                        //$this->xdebug("$k: $v");
204
 
                        //$this->xdebug('ns_prefix: '.$this->getPrefix($k));
205
 
                        if($ns_prefix = substr(strrchr($k,':'),1)){
206
 
                                //$this->xdebug("Add namespace[$ns_prefix] = $v");
207
 
                                                $this->namespaces[$ns_prefix] = $v;
208
 
                                        } else {
209
 
                                                $this->defaultNamespace[$pos] = $v;
210
 
                                                if (! $this->getPrefixFromNamespace($v)) {
211
 
                                                        $this->namespaces['ns'.(count($this->namespaces)+1)] = $v;
212
 
                                                }
213
 
                                        }
214
 
                                        if($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema'){
215
 
                                                $this->XMLSchemaVersion = $v;
216
 
                                                $this->namespaces['xsi'] = $v.'-instance';
217
 
                                        }
218
 
                                }
219
 
                }
220
 
                foreach($attrs as $k => $v){
221
 
                // expand each attribute
222
 
                $k = strpos($k,':') ? $this->expandQname($k) : $k;
223
 
                $v = strpos($v,':') ? $this->expandQname($v) : $v;
224
 
                        $eAttrs[$k] = $v;
225
 
                }
226
 
                $attrs = $eAttrs;
227
 
        } else {
228
 
                $attrs = array();
229
 
        }
230
 
                // find status, register data
231
 
                switch($name){
232
 
                        case 'all':                     // (optional) compositor content for a complexType
233
 
                        case 'choice':
234
 
                        case 'group':
235
 
                        case 'sequence':
236
 
                                //$this->xdebug("compositor $name for currentComplexType: $this->currentComplexType and currentElement: $this->currentElement");
237
 
                                $this->complexTypes[$this->currentComplexType]['compositor'] = $name;
238
 
                                //if($name == 'all' || $name == 'sequence'){
239
 
                                //      $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
240
 
                                //}
241
 
                        break;
242
 
                        case 'attribute':       // complexType attribute
243
 
                //$this->xdebug("parsing attribute $attrs[name] $attrs[ref] of value: ".$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']);
244
 
                $this->xdebug("parsing attribute:");
245
 
                $this->appendDebug($this->varDump($attrs));
246
 
                                if (!isset($attrs['form'])) {
247
 
                                        $attrs['form'] = $this->schemaInfo['attributeFormDefault'];
248
 
                                }
249
 
                if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
250
 
                                        $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
251
 
                                        if (!strpos($v, ':')) {
252
 
                                                // no namespace in arrayType attribute value...
253
 
                                                if ($this->defaultNamespace[$pos]) {
254
 
                                                        // ...so use the default
255
 
                                                        $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'] = $this->defaultNamespace[$pos] . ':' . $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
256
 
                                                }
257
 
                                        }
258
 
                }
259
 
                if(isset($attrs['name'])){
260
 
                                        $this->attributes[$attrs['name']] = $attrs;
261
 
                                        $aname = $attrs['name'];
262
 
                                } elseif(isset($attrs['ref']) && $attrs['ref'] == 'http://schemas.xmlsoap.org/soap/encoding/:arrayType'){
263
 
                                        if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
264
 
                                $aname = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
265
 
                        } else {
266
 
                                $aname = '';
267
 
                        }
268
 
                                } elseif(isset($attrs['ref'])){
269
 
                                        $aname = $attrs['ref'];
270
 
                    $this->attributes[$attrs['ref']] = $attrs;
271
 
                                }
272
 
                
273
 
                                if($this->currentComplexType){  // This should *always* be
274
 
                                        $this->complexTypes[$this->currentComplexType]['attrs'][$aname] = $attrs;
275
 
                                }
276
 
                                // arrayType attribute
277
 
                                if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']) || $this->getLocalPart($aname) == 'arrayType'){
278
 
                                        $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
279
 
                        $prefix = $this->getPrefix($aname);
280
 
                                        if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])){
281
 
                                                $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
282
 
                                        } else {
283
 
                                                $v = '';
284
 
                                        }
285
 
                    if(strpos($v,'[,]')){
286
 
                        $this->complexTypes[$this->currentComplexType]['multidimensional'] = true;
287
 
                    }
288
 
                    $v = substr($v,0,strpos($v,'[')); // clip the []
289
 
                    if(!strpos($v,':') && isset($this->typemap[$this->XMLSchemaVersion][$v])){
290
 
                        $v = $this->XMLSchemaVersion.':'.$v;
291
 
                    }
292
 
                    $this->complexTypes[$this->currentComplexType]['arrayType'] = $v;
293
 
                                }
294
 
                        break;
295
 
                        case 'complexContent':  // (optional) content for a complexType
296
 
                        break;
297
 
                        case 'complexType':
298
 
                                array_push($this->complexTypeStack, $this->currentComplexType);
299
 
                                if(isset($attrs['name'])){
300
 
                                        // TODO: what is the scope of named complexTypes that appear
301
 
                                        //       nested within other c complexTypes?
302
 
                                        $this->xdebug('processing named complexType '.$attrs['name']);
303
 
                                        //$this->currentElement = false;
304
 
                                        $this->currentComplexType = $attrs['name'];
305
 
                                        $this->complexTypes[$this->currentComplexType] = $attrs;
306
 
                                        $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
307
 
                                        // This is for constructs like
308
 
                                        //           <complexType name="ListOfString" base="soap:Array">
309
 
                                        //                <sequence>
310
 
                                        //                    <element name="string" type="xsd:string"
311
 
                                        //                        minOccurs="0" maxOccurs="unbounded" />
312
 
                                        //                </sequence>
313
 
                                        //            </complexType>
314
 
                                        if(isset($attrs['base']) && ereg(':Array$',$attrs['base'])){
315
 
                                                $this->xdebug('complexType is unusual array');
316
 
                                                $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
317
 
                                        } else {
318
 
                                                $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
319
 
                                        }
320
 
                                } else {
321
 
                                        $name = $this->CreateTypeName($this->currentElement);
322
 
                                        $this->xdebug('processing unnamed complexType for element ' . $this->currentElement . ' named ' . $name);
323
 
                                        $this->currentComplexType = $name;
324
 
                                        //$this->currentElement = false;
325
 
                                        $this->complexTypes[$this->currentComplexType] = $attrs;
326
 
                                        $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
327
 
                                        // This is for constructs like
328
 
                                        //           <complexType name="ListOfString" base="soap:Array">
329
 
                                        //                <sequence>
330
 
                                        //                    <element name="string" type="xsd:string"
331
 
                                        //                        minOccurs="0" maxOccurs="unbounded" />
332
 
                                        //                </sequence>
333
 
                                        //            </complexType>
334
 
                                        if(isset($attrs['base']) && ereg(':Array$',$attrs['base'])){
335
 
                                                $this->xdebug('complexType is unusual array');
336
 
                                                $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
337
 
                                        } else {
338
 
                                                $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
339
 
                                        }
340
 
                                }
341
 
                        break;
342
 
                        case 'element':
343
 
                                array_push($this->elementStack, $this->currentElement);
344
 
                                if (!isset($attrs['form'])) {
345
 
                                        $attrs['form'] = $this->schemaInfo['elementFormDefault'];
346
 
                                }
347
 
                                if(isset($attrs['type'])){
348
 
                                        $this->xdebug("processing typed element ".$attrs['name']." of type ".$attrs['type']);
349
 
                                        if (! $this->getPrefix($attrs['type'])) {
350
 
                                                if ($this->defaultNamespace[$pos]) {
351
 
                                                        $attrs['type'] = $this->defaultNamespace[$pos] . ':' . $attrs['type'];
352
 
                                                        $this->xdebug('used default namespace to make type ' . $attrs['type']);
353
 
                                                }
354
 
                                        }
355
 
                                        // This is for constructs like
356
 
                                        //           <complexType name="ListOfString" base="soap:Array">
357
 
                                        //                <sequence>
358
 
                                        //                    <element name="string" type="xsd:string"
359
 
                                        //                        minOccurs="0" maxOccurs="unbounded" />
360
 
                                        //                </sequence>
361
 
                                        //            </complexType>
362
 
                                        if ($this->currentComplexType && $this->complexTypes[$this->currentComplexType]['phpType'] == 'array') {
363
 
                                                $this->xdebug('arrayType for unusual array is ' . $attrs['type']);
364
 
                                                $this->complexTypes[$this->currentComplexType]['arrayType'] = $attrs['type'];
365
 
                                        }
366
 
                                        $this->currentElement = $attrs['name'];
367
 
                                        $ename = $attrs['name'];
368
 
                                } elseif(isset($attrs['ref'])){
369
 
                                        $this->xdebug("processing element as ref to ".$attrs['ref']);
370
 
                                        $this->currentElement = "ref to ".$attrs['ref'];
371
 
                                        $ename = $this->getLocalPart($attrs['ref']);
372
 
                                } else {
373
 
                                        $type = $this->CreateTypeName($this->currentComplexType . '_' . $attrs['name']);
374
 
                                        $this->xdebug("processing untyped element " . $attrs['name'] . ' type ' . $type);
375
 
                                        $this->currentElement = $attrs['name'];
376
 
                                        $attrs['type'] = $this->schemaTargetNamespace . ':' . $type;
377
 
                                        $ename = $attrs['name'];
378
 
                                }
379
 
                                if (isset($ename) && $this->currentComplexType) {
380
 
                                        $this->xdebug("add element $ename to complexType $this->currentComplexType");
381
 
                                        $this->complexTypes[$this->currentComplexType]['elements'][$ename] = $attrs;
382
 
                                } elseif (!isset($attrs['ref'])) {
383
 
                                        $this->xdebug("add element $ename to elements array");
384
 
                                        $this->elements[ $attrs['name'] ] = $attrs;
385
 
                                        $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
386
 
                                }
387
 
                        break;
388
 
                        case 'enumeration':     //      restriction value list member
389
 
                                $this->xdebug('enumeration ' . $attrs['value']);
390
 
                                if ($this->currentSimpleType) {
391
 
                                        $this->simpleTypes[$this->currentSimpleType]['enumeration'][] = $attrs['value'];
392
 
                                } elseif ($this->currentComplexType) {
393
 
                                        $this->complexTypes[$this->currentComplexType]['enumeration'][] = $attrs['value'];
394
 
                                }
395
 
                        break;
396
 
                        case 'extension':       // simpleContent or complexContent type extension
397
 
                                $this->xdebug('extension ' . $attrs['base']);
398
 
                                if ($this->currentComplexType) {
399
 
                                        $this->complexTypes[$this->currentComplexType]['extensionBase'] = $attrs['base'];
400
 
                                }
401
 
                        break;
402
 
                        case 'import':
403
 
                            if (isset($attrs['schemaLocation'])) {
404
 
                                        //$this->xdebug('import namespace ' . $attrs['namespace'] . ' from ' . $attrs['schemaLocation']);
405
 
                    $this->imports[$attrs['namespace']][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
406
 
                                } else {
407
 
                                        //$this->xdebug('import namespace ' . $attrs['namespace']);
408
 
                    $this->imports[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
409
 
                                        if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
410
 
                                                $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
411
 
                                        }
412
 
                                }
413
 
                        break;
414
 
                        case 'list':    // simpleType value list
415
 
                        break;
416
 
                        case 'restriction':     // simpleType, simpleContent or complexContent value restriction
417
 
                                $this->xdebug('restriction ' . $attrs['base']);
418
 
                                if($this->currentSimpleType){
419
 
                                        $this->simpleTypes[$this->currentSimpleType]['type'] = $attrs['base'];
420
 
                                } elseif($this->currentComplexType){
421
 
                                        $this->complexTypes[$this->currentComplexType]['restrictionBase'] = $attrs['base'];
422
 
                                        if(strstr($attrs['base'],':') == ':Array'){
423
 
                                                $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
424
 
                                        }
425
 
                                }
426
 
                        break;
427
 
                        case 'schema':
428
 
                                $this->schemaInfo = $attrs;
429
 
                                $this->schemaInfo['schemaVersion'] = $this->getNamespaceFromPrefix($prefix);
430
 
                                if (isset($attrs['targetNamespace'])) {
431
 
                                        $this->schemaTargetNamespace = $attrs['targetNamespace'];
432
 
                                }
433
 
                                if (!isset($attrs['elementFormDefault'])) {
434
 
                                        $this->schemaInfo['elementFormDefault'] = 'unqualified';
435
 
                                }
436
 
                                if (!isset($attrs['attributeFormDefault'])) {
437
 
                                        $this->schemaInfo['attributeFormDefault'] = 'unqualified';
438
 
                                }
439
 
                        break;
440
 
                        case 'simpleContent':   // (optional) content for a complexType
441
 
                        break;
442
 
                        case 'simpleType':
443
 
                                array_push($this->simpleTypeStack, $this->currentSimpleType);
444
 
                                if(isset($attrs['name'])){
445
 
                                        $this->xdebug("processing simpleType for name " . $attrs['name']);
446
 
                                        $this->currentSimpleType = $attrs['name'];
447
 
                                        $this->simpleTypes[ $attrs['name'] ] = $attrs;
448
 
                                        $this->simpleTypes[ $attrs['name'] ]['typeClass'] = 'simpleType';
449
 
                                        $this->simpleTypes[ $attrs['name'] ]['phpType'] = 'scalar';
450
 
                                } else {
451
 
                                        $name = $this->CreateTypeName($this->currentComplexType . '_' . $this->currentElement);
452
 
                                        $this->xdebug('processing unnamed simpleType for element ' . $this->currentElement . ' named ' . $name);
453
 
                                        $this->currentSimpleType = $name;
454
 
                                        //$this->currentElement = false;
455
 
                                        $this->simpleTypes[$this->currentSimpleType] = $attrs;
456
 
                                        $this->simpleTypes[$this->currentSimpleType]['phpType'] = 'scalar';
457
 
                                }
458
 
                        break;
459
 
                        case 'union':   // simpleType type list
460
 
                        break;
461
 
                        default:
462
 
                                //$this->xdebug("do not have anything to do for element $name");
463
 
                }
464
 
        }
465
 
 
466
 
        /**
467
 
        * end-element handler
468
 
        *
469
 
        * @param    string $parser XML parser object
470
 
        * @param    string $name element name
471
 
        * @access   private
472
 
        */
473
 
        function schemaEndElement($parser, $name) {
474
 
                // bring depth down a notch
475
 
                $this->depth--;
476
 
                // position of current element is equal to the last value left in depth_array for my depth
477
 
                if(isset($this->depth_array[$this->depth])){
478
 
                $pos = $this->depth_array[$this->depth];
479
 
        }
480
 
                // get element prefix
481
 
                if ($prefix = $this->getPrefix($name)){
482
 
                        // get unqualified name
483
 
                        $name = $this->getLocalPart($name);
484
 
                } else {
485
 
                $prefix = '';
486
 
        }
487
 
                // move on...
488
 
                if($name == 'complexType'){
489
 
                        $this->xdebug('done processing complexType ' . ($this->currentComplexType ? $this->currentComplexType : '(unknown)'));
490
 
                        $this->currentComplexType = array_pop($this->complexTypeStack);
491
 
                        //$this->currentElement = false;
492
 
                }
493
 
                if($name == 'element'){
494
 
                        $this->xdebug('done processing element ' . ($this->currentElement ? $this->currentElement : '(unknown)'));
495
 
                        $this->currentElement = array_pop($this->elementStack);
496
 
                }
497
 
                if($name == 'simpleType'){
498
 
                        $this->xdebug('done processing simpleType ' . ($this->currentSimpleType ? $this->currentSimpleType : '(unknown)'));
499
 
                        $this->currentSimpleType = array_pop($this->simpleTypeStack);
500
 
                }
501
 
        }
502
 
 
503
 
        /**
504
 
        * element content handler
505
 
        *
506
 
        * @param    string $parser XML parser object
507
 
        * @param    string $data element content
508
 
        * @access   private
509
 
        */
510
 
        function schemaCharacterData($parser, $data){
511
 
                $pos = $this->depth_array[$this->depth - 1];
512
 
                $this->message[$pos]['cdata'] .= $data;
513
 
        }
514
 
 
515
 
        /**
516
 
        * serialize the schema
517
 
        *
518
 
        * @access   public
519
 
        */
520
 
        function serializeSchema(){
521
 
 
522
 
                $schemaPrefix = $this->getPrefixFromNamespace($this->XMLSchemaVersion);
523
 
                $xml = '';
524
 
                // imports
525
 
                if (sizeof($this->imports) > 0) {
526
 
                        foreach($this->imports as $ns => $list) {
527
 
                                foreach ($list as $ii) {
528
 
                                        if ($ii['location'] != '') {
529
 
                                                $xml .= " <$schemaPrefix:import location=\"" . $ii['location'] . '" namespace="' . $ns . "\" />\n";
530
 
                                        } else {
531
 
                                                $xml .= " <$schemaPrefix:import namespace=\"" . $ns . "\" />\n";
532
 
                                        }
533
 
                                }
534
 
                        } 
535
 
                } 
536
 
                // complex types
537
 
                foreach($this->complexTypes as $typeName => $attrs){
538
 
                        $contentStr = '';
539
 
                        // serialize child elements
540
 
                        if(isset($attrs['elements']) && (count($attrs['elements']) > 0)){
541
 
                                foreach($attrs['elements'] as $element => $eParts){
542
 
                                        if(isset($eParts['ref'])){
543
 
                                                $contentStr .= "   <$schemaPrefix:element ref=\"$element\"/>\n";
544
 
                                        } else {
545
 
                                                $contentStr .= "   <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "\"";
546
 
                                                foreach ($eParts as $aName => $aValue) {
547
 
                                                        // handle, e.g., abstract, default, form, minOccurs, maxOccurs, nillable
548
 
                                                        if ($aName != 'name' && $aName != 'type') {
549
 
                                                                $contentStr .= " $aName=\"$aValue\"";
550
 
                                                        }
551
 
                                                }
552
 
                                                $contentStr .= "/>\n";
553
 
                                        }
554
 
                                }
555
 
                                // compositor wraps elements
556
 
                                if (isset($attrs['compositor']) && ($attrs['compositor'] != '')) {
557
 
                                        $contentStr = "  <$schemaPrefix:$attrs[compositor]>\n".$contentStr."  </$schemaPrefix:$attrs[compositor]>\n";
558
 
                                }
559
 
                        }
560
 
                        // attributes
561
 
                        if(isset($attrs['attrs']) && (count($attrs['attrs']) >= 1)){
562
 
                                foreach($attrs['attrs'] as $attr => $aParts){
563
 
                                        $contentStr .= "    <$schemaPrefix:attribute";
564
 
                                        foreach ($aParts as $a => $v) {
565
 
                                                if ($a == 'ref' || $a == 'type') {
566
 
                                                        $contentStr .= " $a=\"".$this->contractQName($v).'"';
567
 
                                                } elseif ($a == 'http://schemas.xmlsoap.org/wsdl/:arrayType') {
568
 
                                                        $this->usedNamespaces['wsdl'] = $this->namespaces['wsdl'];
569
 
                                                        $contentStr .= ' wsdl:arrayType="'.$this->contractQName($v).'"';
570
 
                                                } else {
571
 
                                                        $contentStr .= " $a=\"$v\"";
572
 
                                                }
573
 
                                        }
574
 
                                        $contentStr .= "/>\n";
575
 
                                }
576
 
                        }
577
 
                        // if restriction
578
 
                        if (isset($attrs['restrictionBase']) && $attrs['restrictionBase'] != ''){
579
 
                                $contentStr = "   <$schemaPrefix:restriction base=\"".$this->contractQName($attrs['restrictionBase'])."\">\n".$contentStr."   </$schemaPrefix:restriction>\n";
580
 
                                // complex or simple content
581
 
                                if ((isset($attrs['elements']) && count($attrs['elements']) > 0) || (isset($attrs['attrs']) && count($attrs['attrs']) > 0)){
582
 
                                        $contentStr = "  <$schemaPrefix:complexContent>\n".$contentStr."  </$schemaPrefix:complexContent>\n";
583
 
                                }
584
 
                        }
585
 
                        // finalize complex type
586
 
                        if($contentStr != ''){
587
 
                                $contentStr = " <$schemaPrefix:complexType name=\"$typeName\">\n".$contentStr." </$schemaPrefix:complexType>\n";
588
 
                        } else {
589
 
                                $contentStr = " <$schemaPrefix:complexType name=\"$typeName\"/>\n";
590
 
                        }
591
 
                        $xml .= $contentStr;
592
 
                }
593
 
                // simple types
594
 
                if(isset($this->simpleTypes) && count($this->simpleTypes) > 0){
595
 
                        foreach($this->simpleTypes as $typeName => $eParts){
596
 
                                $xml .= " <$schemaPrefix:simpleType name=\"$typeName\">\n  <$schemaPrefix:restriction base=\"".$this->contractQName($eParts['type'])."\">\n";
597
 
                                if (isset($eParts['enumeration'])) {
598
 
                                        foreach ($eParts['enumeration'] as $e) {
599
 
                                                $xml .= "  <$schemaPrefix:enumeration value=\"$e\"/>\n";
600
 
                                        }
601
 
                                }
602
 
                                $xml .= "  </$schemaPrefix:restriction>\n </$schemaPrefix:simpleType>";
603
 
                        }
604
 
                }
605
 
                // elements
606
 
                if(isset($this->elements) && count($this->elements) > 0){
607
 
                        foreach($this->elements as $element => $eParts){
608
 
                                $xml .= " <$schemaPrefix:element name=\"$element\" type=\"".$this->contractQName($eParts['type'])."\"/>\n";
609
 
                        }
610
 
                }
611
 
                // attributes
612
 
                if(isset($this->attributes) && count($this->attributes) > 0){
613
 
                        foreach($this->attributes as $attr => $aParts){
614
 
                                $xml .= " <$schemaPrefix:attribute name=\"$attr\" type=\"".$this->contractQName($aParts['type'])."\"\n/>";
615
 
                        }
616
 
                }
617
 
                // finish 'er up
618
 
                $attr = '';
619
 
                foreach ($this->schemaInfo as $k => $v) {
620
 
                        if ($k == 'elementFormDefault' || $k == 'attributeFormDefault') {
621
 
                                $attr .= " $k=\"$v\"";
622
 
                        }
623
 
                }
624
 
                $el = "<$schemaPrefix:schema$attr targetNamespace=\"$this->schemaTargetNamespace\"\n";
625
 
                foreach (array_diff($this->usedNamespaces, $this->enclosingNamespaces) as $nsp => $ns) {
626
 
                        $el .= " xmlns:$nsp=\"$ns\"";
627
 
                }
628
 
                $xml = $el . ">\n".$xml."</$schemaPrefix:schema>\n";
629
 
                return $xml;
630
 
        }
631
 
 
632
 
        /**
633
 
        * adds debug data to the clas level debug string
634
 
        *
635
 
        * @param    string $string debug data
636
 
        * @access   private
637
 
        */
638
 
        function xdebug($string){
639
 
                $this->debug('<' . $this->schemaTargetNamespace . '> '.$string);
640
 
        }
641
 
 
642
 
    /**
643
 
    * get the PHP type of a user defined type in the schema
644
 
    * PHP type is kind of a misnomer since it actually returns 'struct' for assoc. arrays
645
 
    * returns false if no type exists, or not w/ the given namespace
646
 
    * else returns a string that is either a native php type, or 'struct'
647
 
    *
648
 
    * @param string $type name of defined type
649
 
    * @param string $ns namespace of type
650
 
    * @return mixed
651
 
    * @access public
652
 
    * @deprecated
653
 
    */
654
 
        function getPHPType($type,$ns){
655
 
                if(isset($this->typemap[$ns][$type])){
656
 
                        //print "found type '$type' and ns $ns in typemap<br>";
657
 
                        return $this->typemap[$ns][$type];
658
 
                } elseif(isset($this->complexTypes[$type])){
659
 
                        //print "getting type '$type' and ns $ns from complexTypes array<br>";
660
 
                        return $this->complexTypes[$type]['phpType'];
661
 
                }
662
 
                return false;
663
 
        }
664
 
 
665
 
        /**
666
 
    * returns an associative array of information about a given type
667
 
    * returns false if no type exists by the given name
668
 
    *
669
 
        *       For a complexType typeDef = array(
670
 
        *       'restrictionBase' => '',
671
 
        *       'phpType' => '',
672
 
        *       'compositor' => '(sequence|all)',
673
 
        *       'elements' => array(), // refs to elements array
674
 
        *       'attrs' => array() // refs to attributes array
675
 
        *       ... and so on (see addComplexType)
676
 
        *       )
677
 
        *
678
 
        *   For simpleType or element, the array has different keys.
679
 
    *
680
 
    * @param string $type
681
 
    * @return mixed
682
 
    * @access public
683
 
    * @see addComplexType
684
 
    * @see addSimpleType
685
 
    * @see addElement
686
 
    */
687
 
        function getTypeDef($type){
688
 
                //$this->debug("in getTypeDef for type $type");
689
 
                if (substr($type, -1) == '^') {
690
 
                        $is_element = 1;
691
 
                        $type = substr($type, 0, -1);
692
 
                } else {
693
 
                        $is_element = 0;
694
 
                }
695
 
 
696
 
                if((! $is_element) && isset($this->complexTypes[$type])){
697
 
                        $this->xdebug("in getTypeDef, found complexType $type");
698
 
                        return $this->complexTypes[$type];
699
 
                } elseif((! $is_element) && isset($this->simpleTypes[$type])){
700
 
                        $this->xdebug("in getTypeDef, found simpleType $type");
701
 
                        if (!isset($this->simpleTypes[$type]['phpType'])) {
702
 
                                // get info for type to tack onto the simple type
703
 
                                // TODO: can this ever really apply (i.e. what is a simpleType really?)
704
 
                                $uqType = substr($this->simpleTypes[$type]['type'], strrpos($this->simpleTypes[$type]['type'], ':') + 1);
705
 
                                $ns = substr($this->simpleTypes[$type]['type'], 0, strrpos($this->simpleTypes[$type]['type'], ':'));
706
 
                                $etype = $this->getTypeDef($uqType);
707
 
                                if ($etype) {
708
 
                                        $this->xdebug("in getTypeDef, found type for simpleType $type:");
709
 
                                        $this->xdebug($this->varDump($etype));
710
 
                                        if (isset($etype['phpType'])) {
711
 
                                                $this->simpleTypes[$type]['phpType'] = $etype['phpType'];
712
 
                                        }
713
 
                                        if (isset($etype['elements'])) {
714
 
                                                $this->simpleTypes[$type]['elements'] = $etype['elements'];
715
 
                                        }
716
 
                                }
717
 
                        }
718
 
                        return $this->simpleTypes[$type];
719
 
                } elseif(isset($this->elements[$type])){
720
 
                        $this->xdebug("in getTypeDef, found element $type");
721
 
                        if (!isset($this->elements[$type]['phpType'])) {
722
 
                                // get info for type to tack onto the element
723
 
                                $uqType = substr($this->elements[$type]['type'], strrpos($this->elements[$type]['type'], ':') + 1);
724
 
                                $ns = substr($this->elements[$type]['type'], 0, strrpos($this->elements[$type]['type'], ':'));
725
 
                                $etype = $this->getTypeDef($uqType);
726
 
                                if ($etype) {
727
 
                                        $this->xdebug("in getTypeDef, found type for element $type:");
728
 
                                        $this->xdebug($this->varDump($etype));
729
 
                                        if (isset($etype['phpType'])) {
730
 
                                                $this->elements[$type]['phpType'] = $etype['phpType'];
731
 
                                        }
732
 
                                        if (isset($etype['elements'])) {
733
 
                                                $this->elements[$type]['elements'] = $etype['elements'];
734
 
                                        }
735
 
                                } elseif ($ns == 'http://www.w3.org/2001/XMLSchema') {
736
 
                                        $this->xdebug("in getTypeDef, element $type is an XSD type");
737
 
                                        $this->elements[$type]['phpType'] = 'scalar';
738
 
                                }
739
 
                        }
740
 
                        return $this->elements[$type];
741
 
                } elseif(isset($this->attributes[$type])){
742
 
                        $this->xdebug("in getTypeDef, found attribute $type");
743
 
                        return $this->attributes[$type];
744
 
                } elseif (ereg('_ContainedType$', $type)) {
745
 
                        $this->xdebug("in getTypeDef, have an untyped element $type");
746
 
                        $typeDef['typeClass'] = 'simpleType';
747
 
                        $typeDef['phpType'] = 'scalar';
748
 
                        $typeDef['type'] = 'http://www.w3.org/2001/XMLSchema:string';
749
 
                        return $typeDef;
750
 
                }
751
 
                $this->xdebug("in getTypeDef, did not find $type");
752
 
                return false;
753
 
        }
754
 
 
755
 
        /**
756
 
    * returns a sample serialization of a given type, or false if no type by the given name
757
 
    *
758
 
    * @param string $type name of type
759
 
    * @return mixed
760
 
    * @access public
761
 
    * @deprecated
762
 
    */
763
 
    function serializeTypeDef($type){
764
 
        //print "in sTD() for type $type<br>";
765
 
        if($typeDef = $this->getTypeDef($type)){
766
 
                $str .= '<'.$type;
767
 
            if(is_array($typeDef['attrs'])){
768
 
                foreach($typeDef['attrs'] as $attName => $data){
769
 
                    $str .= " $attName=\"{type = ".$data['type']."}\"";
770
 
                }
771
 
            }
772
 
            $str .= " xmlns=\"".$this->schema['targetNamespace']."\"";
773
 
            if(count($typeDef['elements']) > 0){
774
 
                $str .= ">";
775
 
                foreach($typeDef['elements'] as $element => $eData){
776
 
                    $str .= $this->serializeTypeDef($element);
777
 
                }
778
 
                $str .= "</$type>";
779
 
            } elseif($typeDef['typeClass'] == 'element') {
780
 
                $str .= "></$type>";
781
 
            } else {
782
 
                $str .= "/>";
783
 
            }
784
 
                        return $str;
785
 
        }
786
 
        return false;
787
 
    }
788
 
 
789
 
    /**
790
 
    * returns HTML form elements that allow a user
791
 
    * to enter values for creating an instance of the given type.
792
 
    *
793
 
    * @param string $name name for type instance
794
 
    * @param string $type name of type
795
 
    * @return string
796
 
    * @access public
797
 
    * @deprecated
798
 
        */
799
 
        function typeToForm($name,$type){
800
 
                // get typedef
801
 
                if($typeDef = $this->getTypeDef($type)){
802
 
                        // if struct
803
 
                        if($typeDef['phpType'] == 'struct'){
804
 
                                $buffer .= '<table>';
805
 
                                foreach($typeDef['elements'] as $child => $childDef){
806
 
                                        $buffer .= "
807
 
                                        <tr><td align='right'>$childDef[name] (type: ".$this->getLocalPart($childDef['type'])."):</td>
808
 
                                        <td><input type='text' name='parameters[".$name."][$childDef[name]]'></td></tr>";
809
 
                                }
810
 
                                $buffer .= '</table>';
811
 
                        // if array
812
 
                        } elseif($typeDef['phpType'] == 'array'){
813
 
                                $buffer .= '<table>';
814
 
                                for($i=0;$i < 3; $i++){
815
 
                                        $buffer .= "
816
 
                                        <tr><td align='right'>array item (type: $typeDef[arrayType]):</td>
817
 
                                        <td><input type='text' name='parameters[".$name."][]'></td></tr>";
818
 
                                }
819
 
                                $buffer .= '</table>';
820
 
                        // if scalar
821
 
                        } else {
822
 
                                $buffer .= "<input type='text' name='parameters[$name]'>";
823
 
                        }
824
 
                } else {
825
 
                        $buffer .= "<input type='text' name='parameters[$name]'>";
826
 
                }
827
 
                return $buffer;
828
 
        }
829
 
        
830
 
        /**
831
 
        * adds a complex type to the schema
832
 
        * 
833
 
        * example: array
834
 
        * 
835
 
        * addType(
836
 
        *       'ArrayOfstring',
837
 
        *       'complexType',
838
 
        *       'array',
839
 
        *       '',
840
 
        *       'SOAP-ENC:Array',
841
 
        *       array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'string[]'),
842
 
        *       'xsd:string'
843
 
        * );
844
 
        * 
845
 
        * example: PHP associative array ( SOAP Struct )
846
 
        * 
847
 
        * addType(
848
 
        *       'SOAPStruct',
849
 
        *       'complexType',
850
 
        *       'struct',
851
 
        *       'all',
852
 
        *       array('myVar'=> array('name'=>'myVar','type'=>'string')
853
 
        * );
854
 
        * 
855
 
        * @param name
856
 
        * @param typeClass (complexType|simpleType|attribute)
857
 
        * @param phpType: currently supported are array and struct (php assoc array)
858
 
        * @param compositor (all|sequence|choice)
859
 
        * @param restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
860
 
        * @param elements = array ( name = array(name=>'',type=>'') )
861
 
        * @param attrs = array(
862
 
        *       array(
863
 
        *               'ref' => "http://schemas.xmlsoap.org/soap/encoding/:arrayType",
864
 
        *               "http://schemas.xmlsoap.org/wsdl/:arrayType" => "string[]"
865
 
        *       )
866
 
        * )
867
 
        * @param arrayType: namespace:name (http://www.w3.org/2001/XMLSchema:string)
868
 
        * @access public
869
 
        * @see getTypeDef
870
 
        */
871
 
        function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType=''){
872
 
                $this->complexTypes[$name] = array(
873
 
            'name'              => $name,
874
 
            'typeClass' => $typeClass,
875
 
            'phpType'   => $phpType,
876
 
                'compositor'=> $compositor,
877
 
            'restrictionBase' => $restrictionBase,
878
 
                'elements'      => $elements,
879
 
            'attrs'             => $attrs,
880
 
            'arrayType' => $arrayType
881
 
                );
882
 
                
883
 
                $this->xdebug("addComplexType $name:");
884
 
                $this->appendDebug($this->varDump($this->complexTypes[$name]));
885
 
        }
886
 
        
887
 
        /**
888
 
        * adds a simple type to the schema
889
 
        *
890
 
        * @param string $name
891
 
        * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
892
 
        * @param string $typeClass (should always be simpleType)
893
 
        * @param string $phpType (should always be scalar)
894
 
        * @param array $enumeration array of values
895
 
        * @access public
896
 
        * @see nusoap_xmlschema
897
 
        * @see getTypeDef
898
 
        */
899
 
        function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {
900
 
                $this->simpleTypes[$name] = array(
901
 
            'name'                      => $name,
902
 
            'typeClass'         => $typeClass,
903
 
            'phpType'           => $phpType,
904
 
            'type'                      => $restrictionBase,
905
 
            'enumeration'       => $enumeration
906
 
                );
907
 
                
908
 
                $this->xdebug("addSimpleType $name:");
909
 
                $this->appendDebug($this->varDump($this->simpleTypes[$name]));
910
 
        }
911
 
 
912
 
        /**
913
 
        * adds an element to the schema
914
 
        *
915
 
        * @param array $attrs attributes that must include name and type
916
 
        * @see nusoap_xmlschema
917
 
        * @access public
918
 
        */
919
 
        function addElement($attrs) {
920
 
                if (! $this->getPrefix($attrs['type'])) {
921
 
                        $attrs['type'] = $this->schemaTargetNamespace . ':' . $attrs['type'];
922
 
                }
923
 
                $this->elements[ $attrs['name'] ] = $attrs;
924
 
                $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
925
 
                
926
 
                $this->xdebug("addElement " . $attrs['name']);
927
 
                $this->appendDebug($this->varDump($this->elements[ $attrs['name'] ]));
928
 
        }
929
 
}
930
 
 
931
 
/**
932
 
 * Backward compatibility
933
 
 */
934
 
class XMLSchema extends nusoap_xmlschema {
935
 
}
936
 
 
937
 
 
 
1
<?php
 
2
 
 
3
 
 
4
 
 
5
 
 
6
/**
 
7
* parses an XML Schema, allows access to it's data, other utility methods.
 
8
* imperfect, no validation... yet, but quite functional.
 
9
*
 
10
* @author   Dietrich Ayala <dietrich@ganx4.com>
 
11
* @author   Scott Nichol <snichol@users.sourceforge.net>
 
12
* @version  $Id: class.xmlschema.php,v 1.49 2007/11/06 14:17:53 snichol Exp $
 
13
* @access   public
 
14
*/
 
15
class nusoap_xmlschema extends nusoap_base  {
 
16
        
 
17
        // files
 
18
        var $schema = '';
 
19
        var $xml = '';
 
20
        // namespaces
 
21
        var $enclosingNamespaces;
 
22
        // schema info
 
23
        var $schemaInfo = array();
 
24
        var $schemaTargetNamespace = '';
 
25
        // types, elements, attributes defined by the schema
 
26
        var $attributes = array();
 
27
        var $complexTypes = array();
 
28
        var $complexTypeStack = array();
 
29
        var $currentComplexType = null;
 
30
        var $elements = array();
 
31
        var $elementStack = array();
 
32
        var $currentElement = null;
 
33
        var $simpleTypes = array();
 
34
        var $simpleTypeStack = array();
 
35
        var $currentSimpleType = null;
 
36
        // imports
 
37
        var $imports = array();
 
38
        // parser vars
 
39
        var $parser;
 
40
        var $position = 0;
 
41
        var $depth = 0;
 
42
        var $depth_array = array();
 
43
        var $message = array();
 
44
        var $defaultNamespace = array();
 
45
    
 
46
        /**
 
47
        * constructor
 
48
        *
 
49
        * @param    string $schema schema document URI
 
50
        * @param    string $xml xml document URI
 
51
        * @param        string $namespaces namespaces defined in enclosing XML
 
52
        * @access   public
 
53
        */
 
54
        function nusoap_xmlschema($schema='',$xml='',$namespaces=array()){
 
55
                parent::nusoap_base();
 
56
                $this->debug('nusoap_xmlschema class instantiated, inside constructor');
 
57
                // files
 
58
                $this->schema = $schema;
 
59
                $this->xml = $xml;
 
60
 
 
61
                // namespaces
 
62
                $this->enclosingNamespaces = $namespaces;
 
63
                $this->namespaces = array_merge($this->namespaces, $namespaces);
 
64
 
 
65
                // parse schema file
 
66
                if($schema != ''){
 
67
                        $this->debug('initial schema file: '.$schema);
 
68
                        $this->parseFile($schema, 'schema');
 
69
                }
 
70
 
 
71
                // parse xml file
 
72
                if($xml != ''){
 
73
                        $this->debug('initial xml file: '.$xml);
 
74
                        $this->parseFile($xml, 'xml');
 
75
                }
 
76
 
 
77
        }
 
78
 
 
79
    /**
 
80
    * parse an XML file
 
81
    *
 
82
    * @param string $xml path/URL to XML file
 
83
    * @param string $type (schema | xml)
 
84
        * @return boolean
 
85
    * @access public
 
86
    */
 
87
        function parseFile($xml,$type){
 
88
                // parse xml file
 
89
                if($xml != ""){
 
90
                        $xmlStr = @join("",@file($xml));
 
91
                        if($xmlStr == ""){
 
92
                                $msg = 'Error reading XML from '.$xml;
 
93
                                $this->setError($msg);
 
94
                                $this->debug($msg);
 
95
                        return false;
 
96
                        } else {
 
97
                                $this->debug("parsing $xml");
 
98
                                $this->parseString($xmlStr,$type);
 
99
                                $this->debug("done parsing $xml");
 
100
                        return true;
 
101
                        }
 
102
                }
 
103
                return false;
 
104
        }
 
105
 
 
106
        /**
 
107
        * parse an XML string
 
108
        *
 
109
        * @param    string $xml path or URL
 
110
    * @param    string $type (schema|xml)
 
111
        * @access   private
 
112
        */
 
113
        function parseString($xml,$type){
 
114
                // parse xml string
 
115
                if($xml != ""){
 
116
 
 
117
                // Create an XML parser.
 
118
                $this->parser = xml_parser_create();
 
119
                // Set the options for parsing the XML data.
 
120
                xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
 
121
 
 
122
                // Set the object for the parser.
 
123
                xml_set_object($this->parser, $this);
 
124
 
 
125
                // Set the element handlers for the parser.
 
126
                        if($type == "schema"){
 
127
                        xml_set_element_handler($this->parser, 'schemaStartElement','schemaEndElement');
 
128
                        xml_set_character_data_handler($this->parser,'schemaCharacterData');
 
129
                        } elseif($type == "xml"){
 
130
                                xml_set_element_handler($this->parser, 'xmlStartElement','xmlEndElement');
 
131
                        xml_set_character_data_handler($this->parser,'xmlCharacterData');
 
132
                        }
 
133
 
 
134
                    // Parse the XML file.
 
135
                    if(!xml_parse($this->parser,$xml,true)){
 
136
                        // Display an error message.
 
137
                                $errstr = sprintf('XML error parsing XML schema on line %d: %s',
 
138
                                xml_get_current_line_number($this->parser),
 
139
                                xml_error_string(xml_get_error_code($this->parser))
 
140
                                );
 
141
                                $this->debug($errstr);
 
142
                                $this->debug("XML payload:\n" . $xml);
 
143
                                $this->setError($errstr);
 
144
                }
 
145
            
 
146
                        xml_parser_free($this->parser);
 
147
                } else{
 
148
                        $this->debug('no xml passed to parseString()!!');
 
149
                        $this->setError('no xml passed to parseString()!!');
 
150
                }
 
151
        }
 
152
 
 
153
        /**
 
154
         * gets a type name for an unnamed type
 
155
         *
 
156
         * @param       string  Element name
 
157
         * @return      string  A type name for an unnamed type
 
158
         * @access      private
 
159
         */
 
160
        function CreateTypeName($ename) {
 
161
                $scope = '';
 
162
                for ($i = 0; $i < count($this->complexTypeStack); $i++) {
 
163
                        $scope .= $this->complexTypeStack[$i] . '_';
 
164
                }
 
165
                return $scope . $ename . '_ContainedType';
 
166
        }
 
167
        
 
168
        /**
 
169
        * start-element handler
 
170
        *
 
171
        * @param    string $parser XML parser object
 
172
        * @param    string $name element name
 
173
        * @param    string $attrs associative array of attributes
 
174
        * @access   private
 
175
        */
 
176
        function schemaStartElement($parser, $name, $attrs) {
 
177
                
 
178
                // position in the total number of elements, starting from 0
 
179
                $pos = $this->position++;
 
180
                $depth = $this->depth++;
 
181
                // set self as current value for this depth
 
182
                $this->depth_array[$depth] = $pos;
 
183
                $this->message[$pos] = array('cdata' => ''); 
 
184
                if ($depth > 0) {
 
185
                        $this->defaultNamespace[$pos] = $this->defaultNamespace[$this->depth_array[$depth - 1]];
 
186
                } else {
 
187
                        $this->defaultNamespace[$pos] = false;
 
188
                }
 
189
 
 
190
                // get element prefix
 
191
                if($prefix = $this->getPrefix($name)){
 
192
                        // get unqualified name
 
193
                        $name = $this->getLocalPart($name);
 
194
                } else {
 
195
                $prefix = '';
 
196
        }
 
197
                
 
198
        // loop thru attributes, expanding, and registering namespace declarations
 
199
        if(count($attrs) > 0){
 
200
                foreach($attrs as $k => $v){
 
201
                // if ns declarations, add to class level array of valid namespaces
 
202
                                if(ereg("^xmlns",$k)){
 
203
                        //$this->xdebug("$k: $v");
 
204
                        //$this->xdebug('ns_prefix: '.$this->getPrefix($k));
 
205
                        if($ns_prefix = substr(strrchr($k,':'),1)){
 
206
                                //$this->xdebug("Add namespace[$ns_prefix] = $v");
 
207
                                                $this->namespaces[$ns_prefix] = $v;
 
208
                                        } else {
 
209
                                                $this->defaultNamespace[$pos] = $v;
 
210
                                                if (! $this->getPrefixFromNamespace($v)) {
 
211
                                                        $this->namespaces['ns'.(count($this->namespaces)+1)] = $v;
 
212
                                                }
 
213
                                        }
 
214
                                        if($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema'){
 
215
                                                $this->XMLSchemaVersion = $v;
 
216
                                                $this->namespaces['xsi'] = $v.'-instance';
 
217
                                        }
 
218
                                }
 
219
                }
 
220
                foreach($attrs as $k => $v){
 
221
                // expand each attribute
 
222
                $k = strpos($k,':') ? $this->expandQname($k) : $k;
 
223
                $v = strpos($v,':') ? $this->expandQname($v) : $v;
 
224
                        $eAttrs[$k] = $v;
 
225
                }
 
226
                $attrs = $eAttrs;
 
227
        } else {
 
228
                $attrs = array();
 
229
        }
 
230
                // find status, register data
 
231
                switch($name){
 
232
                        case 'all':                     // (optional) compositor content for a complexType
 
233
                        case 'choice':
 
234
                        case 'group':
 
235
                        case 'sequence':
 
236
                                //$this->xdebug("compositor $name for currentComplexType: $this->currentComplexType and currentElement: $this->currentElement");
 
237
                                $this->complexTypes[$this->currentComplexType]['compositor'] = $name;
 
238
                                //if($name == 'all' || $name == 'sequence'){
 
239
                                //      $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
 
240
                                //}
 
241
                        break;
 
242
                        case 'attribute':       // complexType attribute
 
243
                //$this->xdebug("parsing attribute $attrs[name] $attrs[ref] of value: ".$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']);
 
244
                $this->xdebug("parsing attribute:");
 
245
                $this->appendDebug($this->varDump($attrs));
 
246
                                if (!isset($attrs['form'])) {
 
247
                                        $attrs['form'] = $this->schemaInfo['attributeFormDefault'];
 
248
                                }
 
249
                if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
 
250
                                        $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
 
251
                                        if (!strpos($v, ':')) {
 
252
                                                // no namespace in arrayType attribute value...
 
253
                                                if ($this->defaultNamespace[$pos]) {
 
254
                                                        // ...so use the default
 
255
                                                        $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'] = $this->defaultNamespace[$pos] . ':' . $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
 
256
                                                }
 
257
                                        }
 
258
                }
 
259
                if(isset($attrs['name'])){
 
260
                                        $this->attributes[$attrs['name']] = $attrs;
 
261
                                        $aname = $attrs['name'];
 
262
                                } elseif(isset($attrs['ref']) && $attrs['ref'] == 'http://schemas.xmlsoap.org/soap/encoding/:arrayType'){
 
263
                                        if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
 
264
                                $aname = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
 
265
                        } else {
 
266
                                $aname = '';
 
267
                        }
 
268
                                } elseif(isset($attrs['ref'])){
 
269
                                        $aname = $attrs['ref'];
 
270
                    $this->attributes[$attrs['ref']] = $attrs;
 
271
                                }
 
272
                
 
273
                                if($this->currentComplexType){  // This should *always* be
 
274
                                        $this->complexTypes[$this->currentComplexType]['attrs'][$aname] = $attrs;
 
275
                                }
 
276
                                // arrayType attribute
 
277
                                if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']) || $this->getLocalPart($aname) == 'arrayType'){
 
278
                                        $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
 
279
                        $prefix = $this->getPrefix($aname);
 
280
                                        if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])){
 
281
                                                $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
 
282
                                        } else {
 
283
                                                $v = '';
 
284
                                        }
 
285
                    if(strpos($v,'[,]')){
 
286
                        $this->complexTypes[$this->currentComplexType]['multidimensional'] = true;
 
287
                    }
 
288
                    $v = substr($v,0,strpos($v,'[')); // clip the []
 
289
                    if(!strpos($v,':') && isset($this->typemap[$this->XMLSchemaVersion][$v])){
 
290
                        $v = $this->XMLSchemaVersion.':'.$v;
 
291
                    }
 
292
                    $this->complexTypes[$this->currentComplexType]['arrayType'] = $v;
 
293
                                }
 
294
                        break;
 
295
                        case 'complexContent':  // (optional) content for a complexType
 
296
                        break;
 
297
                        case 'complexType':
 
298
                                array_push($this->complexTypeStack, $this->currentComplexType);
 
299
                                if(isset($attrs['name'])){
 
300
                                        // TODO: what is the scope of named complexTypes that appear
 
301
                                        //       nested within other c complexTypes?
 
302
                                        $this->xdebug('processing named complexType '.$attrs['name']);
 
303
                                        //$this->currentElement = false;
 
304
                                        $this->currentComplexType = $attrs['name'];
 
305
                                        $this->complexTypes[$this->currentComplexType] = $attrs;
 
306
                                        $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
 
307
                                        // This is for constructs like
 
308
                                        //           <complexType name="ListOfString" base="soap:Array">
 
309
                                        //                <sequence>
 
310
                                        //                    <element name="string" type="xsd:string"
 
311
                                        //                        minOccurs="0" maxOccurs="unbounded" />
 
312
                                        //                </sequence>
 
313
                                        //            </complexType>
 
314
                                        if(isset($attrs['base']) && ereg(':Array$',$attrs['base'])){
 
315
                                                $this->xdebug('complexType is unusual array');
 
316
                                                $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
 
317
                                        } else {
 
318
                                                $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
 
319
                                        }
 
320
                                } else {
 
321
                                        $name = $this->CreateTypeName($this->currentElement);
 
322
                                        $this->xdebug('processing unnamed complexType for element ' . $this->currentElement . ' named ' . $name);
 
323
                                        $this->currentComplexType = $name;
 
324
                                        //$this->currentElement = false;
 
325
                                        $this->complexTypes[$this->currentComplexType] = $attrs;
 
326
                                        $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
 
327
                                        // This is for constructs like
 
328
                                        //           <complexType name="ListOfString" base="soap:Array">
 
329
                                        //                <sequence>
 
330
                                        //                    <element name="string" type="xsd:string"
 
331
                                        //                        minOccurs="0" maxOccurs="unbounded" />
 
332
                                        //                </sequence>
 
333
                                        //            </complexType>
 
334
                                        if(isset($attrs['base']) && ereg(':Array$',$attrs['base'])){
 
335
                                                $this->xdebug('complexType is unusual array');
 
336
                                                $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
 
337
                                        } else {
 
338
                                                $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
 
339
                                        }
 
340
                                }
 
341
                        break;
 
342
                        case 'element':
 
343
                                array_push($this->elementStack, $this->currentElement);
 
344
                                if (!isset($attrs['form'])) {
 
345
                                        $attrs['form'] = $this->schemaInfo['elementFormDefault'];
 
346
                                }
 
347
                                if(isset($attrs['type'])){
 
348
                                        $this->xdebug("processing typed element ".$attrs['name']." of type ".$attrs['type']);
 
349
                                        if (! $this->getPrefix($attrs['type'])) {
 
350
                                                if ($this->defaultNamespace[$pos]) {
 
351
                                                        $attrs['type'] = $this->defaultNamespace[$pos] . ':' . $attrs['type'];
 
352
                                                        $this->xdebug('used default namespace to make type ' . $attrs['type']);
 
353
                                                }
 
354
                                        }
 
355
                                        // This is for constructs like
 
356
                                        //           <complexType name="ListOfString" base="soap:Array">
 
357
                                        //                <sequence>
 
358
                                        //                    <element name="string" type="xsd:string"
 
359
                                        //                        minOccurs="0" maxOccurs="unbounded" />
 
360
                                        //                </sequence>
 
361
                                        //            </complexType>
 
362
                                        if ($this->currentComplexType && $this->complexTypes[$this->currentComplexType]['phpType'] == 'array') {
 
363
                                                $this->xdebug('arrayType for unusual array is ' . $attrs['type']);
 
364
                                                $this->complexTypes[$this->currentComplexType]['arrayType'] = $attrs['type'];
 
365
                                        }
 
366
                                        $this->currentElement = $attrs['name'];
 
367
                                        $ename = $attrs['name'];
 
368
                                } elseif(isset($attrs['ref'])){
 
369
                                        $this->xdebug("processing element as ref to ".$attrs['ref']);
 
370
                                        $this->currentElement = "ref to ".$attrs['ref'];
 
371
                                        $ename = $this->getLocalPart($attrs['ref']);
 
372
                                } else {
 
373
                                        $type = $this->CreateTypeName($this->currentComplexType . '_' . $attrs['name']);
 
374
                                        $this->xdebug("processing untyped element " . $attrs['name'] . ' type ' . $type);
 
375
                                        $this->currentElement = $attrs['name'];
 
376
                                        $attrs['type'] = $this->schemaTargetNamespace . ':' . $type;
 
377
                                        $ename = $attrs['name'];
 
378
                                }
 
379
                                if (isset($ename) && $this->currentComplexType) {
 
380
                                        $this->xdebug("add element $ename to complexType $this->currentComplexType");
 
381
                                        $this->complexTypes[$this->currentComplexType]['elements'][$ename] = $attrs;
 
382
                                } elseif (!isset($attrs['ref'])) {
 
383
                                        $this->xdebug("add element $ename to elements array");
 
384
                                        $this->elements[ $attrs['name'] ] = $attrs;
 
385
                                        $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
 
386
                                }
 
387
                        break;
 
388
                        case 'enumeration':     //      restriction value list member
 
389
                                $this->xdebug('enumeration ' . $attrs['value']);
 
390
                                if ($this->currentSimpleType) {
 
391
                                        $this->simpleTypes[$this->currentSimpleType]['enumeration'][] = $attrs['value'];
 
392
                                } elseif ($this->currentComplexType) {
 
393
                                        $this->complexTypes[$this->currentComplexType]['enumeration'][] = $attrs['value'];
 
394
                                }
 
395
                        break;
 
396
                        case 'extension':       // simpleContent or complexContent type extension
 
397
                                $this->xdebug('extension ' . $attrs['base']);
 
398
                                if ($this->currentComplexType) {
 
399
                                        $this->complexTypes[$this->currentComplexType]['extensionBase'] = $attrs['base'];
 
400
                                }
 
401
                        break;
 
402
                        case 'import':
 
403
                            if (isset($attrs['schemaLocation'])) {
 
404
                                        //$this->xdebug('import namespace ' . $attrs['namespace'] . ' from ' . $attrs['schemaLocation']);
 
405
                    $this->imports[$attrs['namespace']][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
 
406
                                } else {
 
407
                                        //$this->xdebug('import namespace ' . $attrs['namespace']);
 
408
                    $this->imports[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
 
409
                                        if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
 
410
                                                $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
 
411
                                        }
 
412
                                }
 
413
                        break;
 
414
                        case 'list':    // simpleType value list
 
415
                        break;
 
416
                        case 'restriction':     // simpleType, simpleContent or complexContent value restriction
 
417
                                $this->xdebug('restriction ' . $attrs['base']);
 
418
                                if($this->currentSimpleType){
 
419
                                        $this->simpleTypes[$this->currentSimpleType]['type'] = $attrs['base'];
 
420
                                } elseif($this->currentComplexType){
 
421
                                        $this->complexTypes[$this->currentComplexType]['restrictionBase'] = $attrs['base'];
 
422
                                        if(strstr($attrs['base'],':') == ':Array'){
 
423
                                                $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
 
424
                                        }
 
425
                                }
 
426
                        break;
 
427
                        case 'schema':
 
428
                                $this->schemaInfo = $attrs;
 
429
                                $this->schemaInfo['schemaVersion'] = $this->getNamespaceFromPrefix($prefix);
 
430
                                if (isset($attrs['targetNamespace'])) {
 
431
                                        $this->schemaTargetNamespace = $attrs['targetNamespace'];
 
432
                                }
 
433
                                if (!isset($attrs['elementFormDefault'])) {
 
434
                                        $this->schemaInfo['elementFormDefault'] = 'unqualified';
 
435
                                }
 
436
                                if (!isset($attrs['attributeFormDefault'])) {
 
437
                                        $this->schemaInfo['attributeFormDefault'] = 'unqualified';
 
438
                                }
 
439
                        break;
 
440
                        case 'simpleContent':   // (optional) content for a complexType
 
441
                        break;
 
442
                        case 'simpleType':
 
443
                                array_push($this->simpleTypeStack, $this->currentSimpleType);
 
444
                                if(isset($attrs['name'])){
 
445
                                        $this->xdebug("processing simpleType for name " . $attrs['name']);
 
446
                                        $this->currentSimpleType = $attrs['name'];
 
447
                                        $this->simpleTypes[ $attrs['name'] ] = $attrs;
 
448
                                        $this->simpleTypes[ $attrs['name'] ]['typeClass'] = 'simpleType';
 
449
                                        $this->simpleTypes[ $attrs['name'] ]['phpType'] = 'scalar';
 
450
                                } else {
 
451
                                        $name = $this->CreateTypeName($this->currentComplexType . '_' . $this->currentElement);
 
452
                                        $this->xdebug('processing unnamed simpleType for element ' . $this->currentElement . ' named ' . $name);
 
453
                                        $this->currentSimpleType = $name;
 
454
                                        //$this->currentElement = false;
 
455
                                        $this->simpleTypes[$this->currentSimpleType] = $attrs;
 
456
                                        $this->simpleTypes[$this->currentSimpleType]['phpType'] = 'scalar';
 
457
                                }
 
458
                        break;
 
459
                        case 'union':   // simpleType type list
 
460
                        break;
 
461
                        default:
 
462
                                //$this->xdebug("do not have anything to do for element $name");
 
463
                }
 
464
        }
 
465
 
 
466
        /**
 
467
        * end-element handler
 
468
        *
 
469
        * @param    string $parser XML parser object
 
470
        * @param    string $name element name
 
471
        * @access   private
 
472
        */
 
473
        function schemaEndElement($parser, $name) {
 
474
                // bring depth down a notch
 
475
                $this->depth--;
 
476
                // position of current element is equal to the last value left in depth_array for my depth
 
477
                if(isset($this->depth_array[$this->depth])){
 
478
                $pos = $this->depth_array[$this->depth];
 
479
        }
 
480
                // get element prefix
 
481
                if ($prefix = $this->getPrefix($name)){
 
482
                        // get unqualified name
 
483
                        $name = $this->getLocalPart($name);
 
484
                } else {
 
485
                $prefix = '';
 
486
        }
 
487
                // move on...
 
488
                if($name == 'complexType'){
 
489
                        $this->xdebug('done processing complexType ' . ($this->currentComplexType ? $this->currentComplexType : '(unknown)'));
 
490
                        $this->currentComplexType = array_pop($this->complexTypeStack);
 
491
                        //$this->currentElement = false;
 
492
                }
 
493
                if($name == 'element'){
 
494
                        $this->xdebug('done processing element ' . ($this->currentElement ? $this->currentElement : '(unknown)'));
 
495
                        $this->currentElement = array_pop($this->elementStack);
 
496
                }
 
497
                if($name == 'simpleType'){
 
498
                        $this->xdebug('done processing simpleType ' . ($this->currentSimpleType ? $this->currentSimpleType : '(unknown)'));
 
499
                        $this->currentSimpleType = array_pop($this->simpleTypeStack);
 
500
                }
 
501
        }
 
502
 
 
503
        /**
 
504
        * element content handler
 
505
        *
 
506
        * @param    string $parser XML parser object
 
507
        * @param    string $data element content
 
508
        * @access   private
 
509
        */
 
510
        function schemaCharacterData($parser, $data){
 
511
                $pos = $this->depth_array[$this->depth - 1];
 
512
                $this->message[$pos]['cdata'] .= $data;
 
513
        }
 
514
 
 
515
        /**
 
516
        * serialize the schema
 
517
        *
 
518
        * @access   public
 
519
        */
 
520
        function serializeSchema(){
 
521
 
 
522
                $schemaPrefix = $this->getPrefixFromNamespace($this->XMLSchemaVersion);
 
523
                $xml = '';
 
524
                // imports
 
525
                if (sizeof($this->imports) > 0) {
 
526
                        foreach($this->imports as $ns => $list) {
 
527
                                foreach ($list as $ii) {
 
528
                                        if ($ii['location'] != '') {
 
529
                                                $xml .= " <$schemaPrefix:import location=\"" . $ii['location'] . '" namespace="' . $ns . "\" />\n";
 
530
                                        } else {
 
531
                                                $xml .= " <$schemaPrefix:import namespace=\"" . $ns . "\" />\n";
 
532
                                        }
 
533
                                }
 
534
                        } 
 
535
                } 
 
536
                // complex types
 
537
                foreach($this->complexTypes as $typeName => $attrs){
 
538
                        $contentStr = '';
 
539
                        // serialize child elements
 
540
                        if(isset($attrs['elements']) && (count($attrs['elements']) > 0)){
 
541
                                foreach($attrs['elements'] as $element => $eParts){
 
542
                                        if(isset($eParts['ref'])){
 
543
                                                $contentStr .= "   <$schemaPrefix:element ref=\"$element\"/>\n";
 
544
                                        } else {
 
545
                                                $contentStr .= "   <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "\"";
 
546
                                                foreach ($eParts as $aName => $aValue) {
 
547
                                                        // handle, e.g., abstract, default, form, minOccurs, maxOccurs, nillable
 
548
                                                        if ($aName != 'name' && $aName != 'type') {
 
549
                                                                $contentStr .= " $aName=\"$aValue\"";
 
550
                                                        }
 
551
                                                }
 
552
                                                $contentStr .= "/>\n";
 
553
                                        }
 
554
                                }
 
555
                                // compositor wraps elements
 
556
                                if (isset($attrs['compositor']) && ($attrs['compositor'] != '')) {
 
557
                                        $contentStr = "  <$schemaPrefix:$attrs[compositor]>\n".$contentStr."  </$schemaPrefix:$attrs[compositor]>\n";
 
558
                                }
 
559
                        }
 
560
                        // attributes
 
561
                        if(isset($attrs['attrs']) && (count($attrs['attrs']) >= 1)){
 
562
                                foreach($attrs['attrs'] as $attr => $aParts){
 
563
                                        $contentStr .= "    <$schemaPrefix:attribute";
 
564
                                        foreach ($aParts as $a => $v) {
 
565
                                                if ($a == 'ref' || $a == 'type') {
 
566
                                                        $contentStr .= " $a=\"".$this->contractQName($v).'"';
 
567
                                                } elseif ($a == 'http://schemas.xmlsoap.org/wsdl/:arrayType') {
 
568
                                                        $this->usedNamespaces['wsdl'] = $this->namespaces['wsdl'];
 
569
                                                        $contentStr .= ' wsdl:arrayType="'.$this->contractQName($v).'"';
 
570
                                                } else {
 
571
                                                        $contentStr .= " $a=\"$v\"";
 
572
                                                }
 
573
                                        }
 
574
                                        $contentStr .= "/>\n";
 
575
                                }
 
576
                        }
 
577
                        // if restriction
 
578
                        if (isset($attrs['restrictionBase']) && $attrs['restrictionBase'] != ''){
 
579
                                $contentStr = "   <$schemaPrefix:restriction base=\"".$this->contractQName($attrs['restrictionBase'])."\">\n".$contentStr."   </$schemaPrefix:restriction>\n";
 
580
                                // complex or simple content
 
581
                                if ((isset($attrs['elements']) && count($attrs['elements']) > 0) || (isset($attrs['attrs']) && count($attrs['attrs']) > 0)){
 
582
                                        $contentStr = "  <$schemaPrefix:complexContent>\n".$contentStr."  </$schemaPrefix:complexContent>\n";
 
583
                                }
 
584
                        }
 
585
                        // finalize complex type
 
586
                        if($contentStr != ''){
 
587
                                $contentStr = " <$schemaPrefix:complexType name=\"$typeName\">\n".$contentStr." </$schemaPrefix:complexType>\n";
 
588
                        } else {
 
589
                                $contentStr = " <$schemaPrefix:complexType name=\"$typeName\"/>\n";
 
590
                        }
 
591
                        $xml .= $contentStr;
 
592
                }
 
593
                // simple types
 
594
                if(isset($this->simpleTypes) && count($this->simpleTypes) > 0){
 
595
                        foreach($this->simpleTypes as $typeName => $eParts){
 
596
                                $xml .= " <$schemaPrefix:simpleType name=\"$typeName\">\n  <$schemaPrefix:restriction base=\"".$this->contractQName($eParts['type'])."\">\n";
 
597
                                if (isset($eParts['enumeration'])) {
 
598
                                        foreach ($eParts['enumeration'] as $e) {
 
599
                                                $xml .= "  <$schemaPrefix:enumeration value=\"$e\"/>\n";
 
600
                                        }
 
601
                                }
 
602
                                $xml .= "  </$schemaPrefix:restriction>\n </$schemaPrefix:simpleType>";
 
603
                        }
 
604
                }
 
605
                // elements
 
606
                if(isset($this->elements) && count($this->elements) > 0){
 
607
                        foreach($this->elements as $element => $eParts){
 
608
                                $xml .= " <$schemaPrefix:element name=\"$element\" type=\"".$this->contractQName($eParts['type'])."\"/>\n";
 
609
                        }
 
610
                }
 
611
                // attributes
 
612
                if(isset($this->attributes) && count($this->attributes) > 0){
 
613
                        foreach($this->attributes as $attr => $aParts){
 
614
                                $xml .= " <$schemaPrefix:attribute name=\"$attr\" type=\"".$this->contractQName($aParts['type'])."\"\n/>";
 
615
                        }
 
616
                }
 
617
                // finish 'er up
 
618
                $attr = '';
 
619
                foreach ($this->schemaInfo as $k => $v) {
 
620
                        if ($k == 'elementFormDefault' || $k == 'attributeFormDefault') {
 
621
                                $attr .= " $k=\"$v\"";
 
622
                        }
 
623
                }
 
624
                $el = "<$schemaPrefix:schema$attr targetNamespace=\"$this->schemaTargetNamespace\"\n";
 
625
                foreach (array_diff($this->usedNamespaces, $this->enclosingNamespaces) as $nsp => $ns) {
 
626
                        $el .= " xmlns:$nsp=\"$ns\"";
 
627
                }
 
628
                $xml = $el . ">\n".$xml."</$schemaPrefix:schema>\n";
 
629
                return $xml;
 
630
        }
 
631
 
 
632
        /**
 
633
        * adds debug data to the clas level debug string
 
634
        *
 
635
        * @param    string $string debug data
 
636
        * @access   private
 
637
        */
 
638
        function xdebug($string){
 
639
                $this->debug('<' . $this->schemaTargetNamespace . '> '.$string);
 
640
        }
 
641
 
 
642
    /**
 
643
    * get the PHP type of a user defined type in the schema
 
644
    * PHP type is kind of a misnomer since it actually returns 'struct' for assoc. arrays
 
645
    * returns false if no type exists, or not w/ the given namespace
 
646
    * else returns a string that is either a native php type, or 'struct'
 
647
    *
 
648
    * @param string $type name of defined type
 
649
    * @param string $ns namespace of type
 
650
    * @return mixed
 
651
    * @access public
 
652
    * @deprecated
 
653
    */
 
654
        function getPHPType($type,$ns){
 
655
                if(isset($this->typemap[$ns][$type])){
 
656
                        //print "found type '$type' and ns $ns in typemap<br>";
 
657
                        return $this->typemap[$ns][$type];
 
658
                } elseif(isset($this->complexTypes[$type])){
 
659
                        //print "getting type '$type' and ns $ns from complexTypes array<br>";
 
660
                        return $this->complexTypes[$type]['phpType'];
 
661
                }
 
662
                return false;
 
663
        }
 
664
 
 
665
        /**
 
666
    * returns an associative array of information about a given type
 
667
    * returns false if no type exists by the given name
 
668
    *
 
669
        *       For a complexType typeDef = array(
 
670
        *       'restrictionBase' => '',
 
671
        *       'phpType' => '',
 
672
        *       'compositor' => '(sequence|all)',
 
673
        *       'elements' => array(), // refs to elements array
 
674
        *       'attrs' => array() // refs to attributes array
 
675
        *       ... and so on (see addComplexType)
 
676
        *       )
 
677
        *
 
678
        *   For simpleType or element, the array has different keys.
 
679
    *
 
680
    * @param string $type
 
681
    * @return mixed
 
682
    * @access public
 
683
    * @see addComplexType
 
684
    * @see addSimpleType
 
685
    * @see addElement
 
686
    */
 
687
        function getTypeDef($type){
 
688
                //$this->debug("in getTypeDef for type $type");
 
689
                if (substr($type, -1) == '^') {
 
690
                        $is_element = 1;
 
691
                        $type = substr($type, 0, -1);
 
692
                } else {
 
693
                        $is_element = 0;
 
694
                }
 
695
 
 
696
                if((! $is_element) && isset($this->complexTypes[$type])){
 
697
                        $this->xdebug("in getTypeDef, found complexType $type");
 
698
                        return $this->complexTypes[$type];
 
699
                } elseif((! $is_element) && isset($this->simpleTypes[$type])){
 
700
                        $this->xdebug("in getTypeDef, found simpleType $type");
 
701
                        if (!isset($this->simpleTypes[$type]['phpType'])) {
 
702
                                // get info for type to tack onto the simple type
 
703
                                // TODO: can this ever really apply (i.e. what is a simpleType really?)
 
704
                                $uqType = substr($this->simpleTypes[$type]['type'], strrpos($this->simpleTypes[$type]['type'], ':') + 1);
 
705
                                $ns = substr($this->simpleTypes[$type]['type'], 0, strrpos($this->simpleTypes[$type]['type'], ':'));
 
706
                                $etype = $this->getTypeDef($uqType);
 
707
                                if ($etype) {
 
708
                                        $this->xdebug("in getTypeDef, found type for simpleType $type:");
 
709
                                        $this->xdebug($this->varDump($etype));
 
710
                                        if (isset($etype['phpType'])) {
 
711
                                                $this->simpleTypes[$type]['phpType'] = $etype['phpType'];
 
712
                                        }
 
713
                                        if (isset($etype['elements'])) {
 
714
                                                $this->simpleTypes[$type]['elements'] = $etype['elements'];
 
715
                                        }
 
716
                                }
 
717
                        }
 
718
                        return $this->simpleTypes[$type];
 
719
                } elseif(isset($this->elements[$type])){
 
720
                        $this->xdebug("in getTypeDef, found element $type");
 
721
                        if (!isset($this->elements[$type]['phpType'])) {
 
722
                                // get info for type to tack onto the element
 
723
                                $uqType = substr($this->elements[$type]['type'], strrpos($this->elements[$type]['type'], ':') + 1);
 
724
                                $ns = substr($this->elements[$type]['type'], 0, strrpos($this->elements[$type]['type'], ':'));
 
725
                                $etype = $this->getTypeDef($uqType);
 
726
                                if ($etype) {
 
727
                                        $this->xdebug("in getTypeDef, found type for element $type:");
 
728
                                        $this->xdebug($this->varDump($etype));
 
729
                                        if (isset($etype['phpType'])) {
 
730
                                                $this->elements[$type]['phpType'] = $etype['phpType'];
 
731
                                        }
 
732
                                        if (isset($etype['elements'])) {
 
733
                                                $this->elements[$type]['elements'] = $etype['elements'];
 
734
                                        }
 
735
                                } elseif ($ns == 'http://www.w3.org/2001/XMLSchema') {
 
736
                                        $this->xdebug("in getTypeDef, element $type is an XSD type");
 
737
                                        $this->elements[$type]['phpType'] = 'scalar';
 
738
                                }
 
739
                        }
 
740
                        return $this->elements[$type];
 
741
                } elseif(isset($this->attributes[$type])){
 
742
                        $this->xdebug("in getTypeDef, found attribute $type");
 
743
                        return $this->attributes[$type];
 
744
                } elseif (ereg('_ContainedType$', $type)) {
 
745
                        $this->xdebug("in getTypeDef, have an untyped element $type");
 
746
                        $typeDef['typeClass'] = 'simpleType';
 
747
                        $typeDef['phpType'] = 'scalar';
 
748
                        $typeDef['type'] = 'http://www.w3.org/2001/XMLSchema:string';
 
749
                        return $typeDef;
 
750
                }
 
751
                $this->xdebug("in getTypeDef, did not find $type");
 
752
                return false;
 
753
        }
 
754
 
 
755
        /**
 
756
    * returns a sample serialization of a given type, or false if no type by the given name
 
757
    *
 
758
    * @param string $type name of type
 
759
    * @return mixed
 
760
    * @access public
 
761
    * @deprecated
 
762
    */
 
763
    function serializeTypeDef($type){
 
764
        //print "in sTD() for type $type<br>";
 
765
        if($typeDef = $this->getTypeDef($type)){
 
766
                $str .= '<'.$type;
 
767
            if(is_array($typeDef['attrs'])){
 
768
                foreach($typeDef['attrs'] as $attName => $data){
 
769
                    $str .= " $attName=\"{type = ".$data['type']."}\"";
 
770
                }
 
771
            }
 
772
            $str .= " xmlns=\"".$this->schema['targetNamespace']."\"";
 
773
            if(count($typeDef['elements']) > 0){
 
774
                $str .= ">";
 
775
                foreach($typeDef['elements'] as $element => $eData){
 
776
                    $str .= $this->serializeTypeDef($element);
 
777
                }
 
778
                $str .= "</$type>";
 
779
            } elseif($typeDef['typeClass'] == 'element') {
 
780
                $str .= "></$type>";
 
781
            } else {
 
782
                $str .= "/>";
 
783
            }
 
784
                        return $str;
 
785
        }
 
786
        return false;
 
787
    }
 
788
 
 
789
    /**
 
790
    * returns HTML form elements that allow a user
 
791
    * to enter values for creating an instance of the given type.
 
792
    *
 
793
    * @param string $name name for type instance
 
794
    * @param string $type name of type
 
795
    * @return string
 
796
    * @access public
 
797
    * @deprecated
 
798
        */
 
799
        function typeToForm($name,$type){
 
800
                // get typedef
 
801
                if($typeDef = $this->getTypeDef($type)){
 
802
                        // if struct
 
803
                        if($typeDef['phpType'] == 'struct'){
 
804
                                $buffer .= '<table>';
 
805
                                foreach($typeDef['elements'] as $child => $childDef){
 
806
                                        $buffer .= "
 
807
                                        <tr><td align='right'>$childDef[name] (type: ".$this->getLocalPart($childDef['type'])."):</td>
 
808
                                        <td><input type='text' name='parameters[".$name."][$childDef[name]]'></td></tr>";
 
809
                                }
 
810
                                $buffer .= '</table>';
 
811
                        // if array
 
812
                        } elseif($typeDef['phpType'] == 'array'){
 
813
                                $buffer .= '<table>';
 
814
                                for($i=0;$i < 3; $i++){
 
815
                                        $buffer .= "
 
816
                                        <tr><td align='right'>array item (type: $typeDef[arrayType]):</td>
 
817
                                        <td><input type='text' name='parameters[".$name."][]'></td></tr>";
 
818
                                }
 
819
                                $buffer .= '</table>';
 
820
                        // if scalar
 
821
                        } else {
 
822
                                $buffer .= "<input type='text' name='parameters[$name]'>";
 
823
                        }
 
824
                } else {
 
825
                        $buffer .= "<input type='text' name='parameters[$name]'>";
 
826
                }
 
827
                return $buffer;
 
828
        }
 
829
        
 
830
        /**
 
831
        * adds a complex type to the schema
 
832
        * 
 
833
        * example: array
 
834
        * 
 
835
        * addType(
 
836
        *       'ArrayOfstring',
 
837
        *       'complexType',
 
838
        *       'array',
 
839
        *       '',
 
840
        *       'SOAP-ENC:Array',
 
841
        *       array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'string[]'),
 
842
        *       'xsd:string'
 
843
        * );
 
844
        * 
 
845
        * example: PHP associative array ( SOAP Struct )
 
846
        * 
 
847
        * addType(
 
848
        *       'SOAPStruct',
 
849
        *       'complexType',
 
850
        *       'struct',
 
851
        *       'all',
 
852
        *       array('myVar'=> array('name'=>'myVar','type'=>'string')
 
853
        * );
 
854
        * 
 
855
        * @param name
 
856
        * @param typeClass (complexType|simpleType|attribute)
 
857
        * @param phpType: currently supported are array and struct (php assoc array)
 
858
        * @param compositor (all|sequence|choice)
 
859
        * @param restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
 
860
        * @param elements = array ( name = array(name=>'',type=>'') )
 
861
        * @param attrs = array(
 
862
        *       array(
 
863
        *               'ref' => "http://schemas.xmlsoap.org/soap/encoding/:arrayType",
 
864
        *               "http://schemas.xmlsoap.org/wsdl/:arrayType" => "string[]"
 
865
        *       )
 
866
        * )
 
867
        * @param arrayType: namespace:name (http://www.w3.org/2001/XMLSchema:string)
 
868
        * @access public
 
869
        * @see getTypeDef
 
870
        */
 
871
        function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType=''){
 
872
                $this->complexTypes[$name] = array(
 
873
            'name'              => $name,
 
874
            'typeClass' => $typeClass,
 
875
            'phpType'   => $phpType,
 
876
                'compositor'=> $compositor,
 
877
            'restrictionBase' => $restrictionBase,
 
878
                'elements'      => $elements,
 
879
            'attrs'             => $attrs,
 
880
            'arrayType' => $arrayType
 
881
                );
 
882
                
 
883
                $this->xdebug("addComplexType $name:");
 
884
                $this->appendDebug($this->varDump($this->complexTypes[$name]));
 
885
        }
 
886
        
 
887
        /**
 
888
        * adds a simple type to the schema
 
889
        *
 
890
        * @param string $name
 
891
        * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
 
892
        * @param string $typeClass (should always be simpleType)
 
893
        * @param string $phpType (should always be scalar)
 
894
        * @param array $enumeration array of values
 
895
        * @access public
 
896
        * @see nusoap_xmlschema
 
897
        * @see getTypeDef
 
898
        */
 
899
        function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {
 
900
                $this->simpleTypes[$name] = array(
 
901
            'name'                      => $name,
 
902
            'typeClass'         => $typeClass,
 
903
            'phpType'           => $phpType,
 
904
            'type'                      => $restrictionBase,
 
905
            'enumeration'       => $enumeration
 
906
                );
 
907
                
 
908
                $this->xdebug("addSimpleType $name:");
 
909
                $this->appendDebug($this->varDump($this->simpleTypes[$name]));
 
910
        }
 
911
 
 
912
        /**
 
913
        * adds an element to the schema
 
914
        *
 
915
        * @param array $attrs attributes that must include name and type
 
916
        * @see nusoap_xmlschema
 
917
        * @access public
 
918
        */
 
919
        function addElement($attrs) {
 
920
                if (! $this->getPrefix($attrs['type'])) {
 
921
                        $attrs['type'] = $this->schemaTargetNamespace . ':' . $attrs['type'];
 
922
                }
 
923
                $this->elements[ $attrs['name'] ] = $attrs;
 
924
                $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
 
925
                
 
926
                $this->xdebug("addElement " . $attrs['name']);
 
927
                $this->appendDebug($this->varDump($this->elements[ $attrs['name'] ]));
 
928
        }
 
929
}
 
930
 
 
931
/**
 
932
 * Backward compatibility
 
933
 */
 
934
class XMLSchema extends nusoap_xmlschema {
 
935
}
 
936
 
 
937
 
938
938
?>
 
 
b'\\ No newline at end of file'