root/docs/usc/nautilus/usr2/prod/buoys/perl/xml/nusoap/lib/nusoap.php

Revision 113 (checked in by jcothran, 5 years ago)

example php/perl script to process nerrs cdmo web service data to Xenia database.

Line 
1 <?php
2
3 /*
4 $Id: nusoap.php,v 1.94 2005/08/04 01:27:42 snichol Exp $
5
6 NuSOAP - Web Services Toolkit for PHP
7
8 Copyright (c) 2002 NuSphere Corporation
9
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Lesser General Public
12 License as published by the Free Software Foundation; either
13 version 2.1 of the License, or (at your option) any later version.
14
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 Lesser General Public License for more details.
19
20 You should have received a copy of the GNU Lesser General Public
21 License along with this library; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23
24 If you have any questions or comments, please email:
25
26 Dietrich Ayala
27 dietrich@ganx4.com
28 http://dietrich.ganx4.com/nusoap
29
30 NuSphere Corporation
31 http://www.nusphere.com
32
33 */
34
35 /* load classes
36
37 // necessary classes
38 require_once('class.soapclient.php');
39 require_once('class.soap_val.php');
40 require_once('class.soap_parser.php');
41 require_once('class.soap_fault.php');
42
43 // transport classes
44 require_once('class.soap_transport_http.php');
45
46 // optional add-on classes
47 require_once('class.xmlschema.php');
48 require_once('class.wsdl.php');
49
50 // server class
51 require_once('class.soap_server.php');*/
52
53 // class variable emulation
54 // cf. http://www.webkreator.com/php/techniques/php-static-class-variables.html
55 $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel = 9;
56
57 /**
58 *
59 * nusoap_base
60 *
61 * @author   Dietrich Ayala <dietrich@ganx4.com>
62 * @version  $Id: nusoap.php,v 1.94 2005/08/04 01:27:42 snichol Exp $
63 * @access   public
64 */
65 class nusoap_base {
66     /**
67      * Identification for HTTP headers.
68      *
69      * @var string
70      * @access private
71      */
72     var $title = 'NuSOAP';
73     /**
74      * Version for HTTP headers.
75      *
76      * @var string
77      * @access private
78      */
79     var $version = '0.7.2';
80     /**
81      * CVS revision for HTTP headers.
82      *
83      * @var string
84      * @access private
85      */
86     var $revision = '$Revision: 1.94 $';
87     /**
88      * Current error string (manipulated by getError/setError)
89      *
90      * @var string
91      * @access private
92      */
93     var $error_str = '';
94     /**
95      * Current debug string (manipulated by debug/appendDebug/clearDebug/getDebug/getDebugAsXMLComment)
96      *
97      * @var string
98      * @access private
99      */
100     var $debug_str = '';
101     /**
102      * toggles automatic encoding of special characters as entities
103      * (should always be true, I think)
104      *
105      * @var boolean
106      * @access private
107      */
108     var $charencoding = true;
109     /**
110      * the debug level for this instance
111      *
112      * @var    integer
113      * @access private
114      */
115     var $debugLevel;
116
117     /**
118     * set schema version
119     *
120     * @var      string
121     * @access   public
122     */
123     var $XMLSchemaVersion = 'http://www.w3.org/2001/XMLSchema';
124     
125     /**
126     * charset encoding for outgoing messages
127     *
128     * @var      string
129     * @access   public
130     */
131     var $soap_defencoding = 'ISO-8859-1';
132     //var $soap_defencoding = 'UTF-8';
133
134     /**
135     * namespaces in an array of prefix => uri
136     *
137     * this is "seeded" by a set of constants, but it may be altered by code
138     *
139     * @var      array
140     * @access   public
141     */
142     var $namespaces = array(
143         'SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/',
144         'xsd' => 'http://www.w3.org/2001/XMLSchema',
145         'xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
146         'SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/'
147         );
148
149     /**
150     * namespaces used in the current context, e.g. during serialization
151     *
152     * @var      array
153     * @access   private
154     */
155     var $usedNamespaces = array();
156
157     /**
158     * XML Schema types in an array of uri => (array of xml type => php type)
159     * is this legacy yet?
160     * no, this is used by the xmlschema class to verify type => namespace mappings.
161     * @var      array
162     * @access   public
163     */
164     var $typemap = array(
165     'http://www.w3.org/2001/XMLSchema' => array(
166         'string'=>'string','boolean'=>'boolean','float'=>'double','double'=>'double','decimal'=>'double',
167         'duration'=>'','dateTime'=>'string','time'=>'string','date'=>'string','gYearMonth'=>'',
168         'gYear'=>'','gMonthDay'=>'','gDay'=>'','gMonth'=>'','hexBinary'=>'string','base64Binary'=>'string',
169         // abstract "any" types
170         'anyType'=>'string','anySimpleType'=>'string',
171         // derived datatypes
172         'normalizedString'=>'string','token'=>'string','language'=>'','NMTOKEN'=>'','NMTOKENS'=>'','Name'=>'','NCName'=>'','ID'=>'',
173         'IDREF'=>'','IDREFS'=>'','ENTITY'=>'','ENTITIES'=>'','integer'=>'integer','nonPositiveInteger'=>'integer',
174         'negativeInteger'=>'integer','long'=>'integer','int'=>'integer','short'=>'integer','byte'=>'integer','nonNegativeInteger'=>'integer',
175         'unsignedLong'=>'','unsignedInt'=>'','unsignedShort'=>'','unsignedByte'=>'','positiveInteger'=>''),
176     'http://www.w3.org/2000/10/XMLSchema' => array(
177         'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
178         'float'=>'double','dateTime'=>'string',
179         'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
180     'http://www.w3.org/1999/XMLSchema' => array(
181         'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
182         'float'=>'double','dateTime'=>'string',
183         'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
184     'http://soapinterop.org/xsd' => array('SOAPStruct'=>'struct'),
185     'http://schemas.xmlsoap.org/soap/encoding/' => array('base64'=>'string','array'=>'array','Array'=>'array'),
186     'http://xml.apache.org/xml-soap' => array('Map')
187     );
188
189     /**
190     * XML entities to convert
191     *
192     * @var      array
193     * @access   public
194     * @deprecated
195     * @see    expandEntities
196     */
197     var $xmlEntities = array('quot' => '"','amp' => '&',
198         'lt' => '<','gt' => '>','apos' => "'");
199
200     /**
201     * constructor
202     *
203     * @access    public
204     */
205     function nusoap_base() {
206         $this->debugLevel = $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel;
207     }
208
209     /**
210     * gets the global debug level, which applies to future instances
211     *
212     * @return    integer    Debug level 0-9, where 0 turns off
213     * @access    public
214     */
215     function getGlobalDebugLevel() {
216         return $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel;
217     }
218
219     /**
220     * sets the global debug level, which applies to future instances
221     *
222     * @param    int    $level    Debug level 0-9, where 0 turns off
223     * @access    public
224     */
225     function setGlobalDebugLevel($level) {
226         $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel = $level;
227     }
228
229     /**
230     * gets the debug level for this instance
231     *
232     * @return    int    Debug level 0-9, where 0 turns off
233     * @access    public
234     */
235     function getDebugLevel() {
236         return $this->debugLevel;
237     }
238
239     /**
240     * sets the debug level for this instance
241     *
242     * @param    int    $level    Debug level 0-9, where 0 turns off
243     * @access    public
244     */
245     function setDebugLevel($level) {
246         $this->debugLevel = $level;
247     }
248
249     /**
250     * adds debug data to the instance debug string with formatting
251     *
252     * @param    string $string debug data
253     * @access   private
254     */
255     function debug($string){
256         if ($this->debugLevel > 0) {
257             $this->appendDebug($this->getmicrotime().' '.get_class($this).": $string\n");
258         }
259     }
260
261     /**
262     * adds debug data to the instance debug string without formatting
263     *
264     * @param    string $string debug data
265     * @access   public
266     */
267     function appendDebug($string){
268         if ($this->debugLevel > 0) {
269             // it would be nice to use a memory stream here to use
270             // memory more efficiently
271             $this->debug_str .= $string;
272         }
273     }
274
275     /**
276     * clears the current debug data for this instance
277     *
278     * @access   public
279     */
280     function clearDebug() {
281         // it would be nice to use a memory stream here to use
282         // memory more efficiently
283         $this->debug_str = '';
284     }
285
286     /**
287     * gets the current debug data for this instance
288     *
289     * @return   debug data
290     * @access   public
291     */
292     function &getDebug() {
293         // it would be nice to use a memory stream here to use
294         // memory more efficiently
295         return $this->debug_str;
296     }
297
298     /**
299     * gets the current debug data for this instance as an XML comment
300     * this may change the contents of the debug data
301     *
302     * @return   debug data as an XML comment
303     * @access   public
304     */
305     function &getDebugAsXMLComment() {
306         // it would be nice to use a memory stream here to use
307         // memory more efficiently
308         while (strpos($this->debug_str, '--')) {
309             $this->debug_str = str_replace('--', '- -', $this->debug_str);
310         }
311         return "<!--\n" . $this->debug_str . "\n-->";
312     }
313
314     /**
315     * expands entities, e.g. changes '<' to '&lt;'.
316     *
317     * @param    string    $val    The string in which to expand entities.
318     * @access    private
319     */
320     function expandEntities($val) {
321         if ($this->charencoding) {
322             $val = str_replace('&', '&amp;', $val);
323             $val = str_replace("'", '&apos;', $val);
324             $val = str_replace('"', '&quot;', $val);
325             $val = str_replace('<', '&lt;', $val);
326             $val = str_replace('>', '&gt;', $val);
327         }
328         return $val;
329     }
330
331     /**
332     * returns error string if present
333     *
334     * @return   mixed error string or false
335     * @access   public
336     */
337     function getError(){
338         if($this->error_str != ''){
339             return $this->error_str;
340         }
341         return false;
342     }
343
344     /**
345     * sets error string
346     *
347     * @return   boolean $string error string
348     * @access   private
349     */
350     function setError($str){
351         $this->error_str = $str;
352     }
353
354     /**
355     * detect if array is a simple array or a struct (associative array)
356     *
357     * @param    mixed    $val    The PHP array
358     * @return    string    (arraySimple|arrayStruct)
359     * @access    private
360     */
361     function isArraySimpleOrStruct($val) {
362         $keyList = array_keys($val);
363         foreach ($keyList as $keyListValue) {
364             if (!is_int($keyListValue)) {
365                 return 'arrayStruct';
366             }
367         }
368         return 'arraySimple';
369     }
370
371     /**
372     * serializes PHP values in accordance w/ section 5. Type information is
373     * not serialized if $use == 'literal'.
374     *
375     * @param    mixed    $val    The value to serialize
376     * @param    string    $name    The name (local part) of the XML element
377     * @param    string    $type    The XML schema type (local part) for the element
378     * @param    string    $name_ns    The namespace for the name of the XML element
379     * @param    string    $type_ns    The namespace for the type of the element
380     * @param    array    $attributes    The attributes to serialize as name=>value pairs
381     * @param    string    $use    The WSDL "use" (encoded|literal)
382     * @return    string    The serialized element, possibly with child elements
383     * @access    public
384     */
385     function serialize_val($val,$name=false,$type=false,$name_ns=false,$type_ns=false,$attributes=false,$use='encoded'){
386         $this->debug("in serialize_val: name=$name, type=$type, name_ns=$name_ns, type_ns=$type_ns, use=$use");
387         $this->appendDebug('value=' . $this->varDump($val));
388         $this->appendDebug('attributes=' . $this->varDump($attributes));
389         
390         if(is_object($val) && get_class($val) == 'soapval'){
391             return $val->serialize($use);
392         }
393         // force valid name if necessary
394         if (is_numeric($name)) {
395             $name = '__numeric_' . $name;
396         } elseif (! $name) {
397             $name = 'noname';
398         }
399         // if name has ns, add ns prefix to name
400         $xmlns = '';
401         if($name_ns){
402             $prefix = 'nu'.rand(1000,9999);
403             $name = $prefix.':'.$name;
404             $xmlns .= " xmlns:$prefix=\"$name_ns\"";
405         }
406         // if type is prefixed, create type prefix
407         if($type_ns != '' && $type_ns == $this->namespaces['xsd']){
408             // need to fix this. shouldn't default to xsd if no ns specified
409             // w/o checking against typemap
410             $type_prefix = 'xsd';
411         } elseif($type_ns){
412             $type_prefix = 'ns'.rand(1000,9999);
413             $xmlns .= " xmlns:$type_prefix=\"$type_ns\"";
414         }
415         // serialize attributes if present
416         $atts = '';
417         if($attributes){
418             foreach($attributes as $k => $v){
419                 $atts .= " $k=\"".$this->expandEntities($v).'"';
420             }
421         }
422         // serialize null value
423         if (is_null($val)) {
424             if ($use == 'literal') {
425                 // TODO: depends on minOccurs
426                 return "<$name$xmlns $atts/>";
427             } else {
428                 if (isset($type) && isset($type_prefix)) {
429                     $type_str = " xsi:type=\"$type_prefix:$type\"";
430                 } else {
431                     $type_str = '';
432                 }
433                 return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>";
434             }
435         }
436         // serialize if an xsd built-in primitive type
437         if($type != '' && isset($this->typemap[$this->XMLSchemaVersion][$type])){
438             if (is_bool($val)) {
439                 if ($type == 'boolean') {
440                     $val = $val ? 'true' : 'false';
441                 } elseif (! $val) {
442                     $val = 0;
443                 }
444             } else if (is_string($val)) {
445                 $val = $this->expandEntities($val);
446             }
447             if ($use == 'literal') {
448                 return "<$name$xmlns $atts>$val</$name>";
449             } else {
450                 return "<$name$xmlns $atts xsi:type=\"xsd:$type\">$val</$name>";
451             }
452         }
453         // detect type and serialize
454         $xml = '';
455         switch(true) {
456             case (is_bool($val) || $type == 'boolean'):
457                 if ($type == 'boolean') {
458                     $val = $val ? 'true' : 'false';
459                 } elseif (! $val) {
460                     $val = 0;
461                 }
462                 if ($use == 'literal') {
463                     $xml .= "<$name$xmlns $atts>$val</$name>";
464                 } else {
465                     $xml .= "<$name$xmlns xsi:type=\"xsd:boolean\"$atts>$val</$name>";
466                 }
467                 break;
468             case (is_int($val) || is_long($val) || $type == 'int'):
469                 if ($use == 'literal') {
470                     $xml .= "<$name$xmlns $atts>$val</$name>";
471                 } else {
472                     $xml .= "<$name$xmlns xsi:type=\"xsd:int\"$atts>$val</$name>";
473                 }
474                 break;
475             case (is_float($val)|| is_double($val) || $type == 'float'):
476                 if ($use == 'literal') {
477                     $xml .= "<$name$xmlns $atts>$val</$name>";
478                 } else {
479                     $xml .= "<$name$xmlns xsi:type=\"xsd:float\"$atts>$val</$name>";
480                 }
481                 break;
482             case (is_string($val) || $type == 'string'):
483                 $val = $this->expandEntities($val);
484                 if ($use == 'literal') {
485                     $xml .= "<$name$xmlns $atts>$val</$name>";
486                 } else {
487                     $xml .= "<$name$xmlns xsi:type=\"xsd:string\"$atts>$val</$name>";
488                 }
489                 break;
490             case is_object($val):
491                 if (! $name) {
492                     $name = get_class($val);
493                     $this->debug("In serialize_val, used class name $name as element name");
494                 } else {
495                     $this->debug("In serialize_val, do not override name $name for element name for class " . get_class($val));
496                 }
497                 foreach(get_object_vars($val) as $k => $v){
498                     $pXml = isset($pXml) ? $pXml.$this->serialize_val($v,$k,false,false,false,false,$use) : $this->serialize_val($v,$k,false,false,false,false,$use);
499                 }
500                 $xml .= '<'.$name.'>'.$pXml.'</'.$name.'>';
501                 break;
502             break;
503             case (is_array($val) || $type):
504                 // detect if struct or array
505                 $valueType = $this->isArraySimpleOrStruct($val);
506                 if($valueType=='arraySimple' || ereg('^ArrayOf',$type)){
507                     $i = 0;
508                     if(is_array($val) && count($val)> 0){
509                         foreach($val as $v){
510                             if(is_object($v) && get_class($v) ==  'soapval'){
511                                 $tt_ns = $v->type_ns;
512                                 $tt = $v->type;
513                             } elseif (is_array($v)) {
514                                 $tt = $this->isArraySimpleOrStruct($v);
515                             } else {
516                                 $tt = gettype($v);
517                             }
518                             $array_types[$tt] = 1;
519                             // TODO: for literal, the name should be $name
520                             $xml .= $this->serialize_val($v,'item',false,false,false,false,$use);
521                             ++$i;
522                         }
523                         if(count($array_types) > 1){
524                             $array_typename = 'xsd:anyType';
525                         } elseif(isset($tt) && isset($this->typemap[$this->XMLSchemaVersion][$tt])) {
526                             if ($tt == 'integer') {
527                                 $tt = 'int';
528                             }
529                             $array_typename = 'xsd:'.$tt;
530                         } elseif(isset($tt) && $tt == 'arraySimple'){
531                             $array_typename = 'SOAP-ENC:Array';
532                         } elseif(isset($tt) && $tt == 'arrayStruct'){
533                             $array_typename = 'unnamed_struct_use_soapval';
534                         } else {
535                             // if type is prefixed, create type prefix
536                             if ($tt_ns != '' && $tt_ns == $this->namespaces['xsd']){
537                                  $array_typename = 'xsd:' . $tt;
538                             } elseif ($tt_ns) {
539                                 $tt_prefix = 'ns' . rand(1000, 9999);
540                                 $array_typename = "$tt_prefix:$tt";
541                                 $xmlns .= " xmlns:$tt_prefix=\"$tt_ns\"";
542                             } else {
543                                 $array_typename = $tt;
544                             }
545                         }
546                         $array_type = $i;
547                         if ($use == 'literal') {
548                             $type_str = '';
549                         } else if (isset($type) && isset($type_prefix)) {
550                             $type_str = " xsi:type=\"$type_prefix:$type\"";
551                         } else {
552                             $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"".$array_typename."[$array_type]\"";
553                         }
554                     // empty array
555                     } else {
556                         if ($use == 'literal') {
557                             $type_str = '';
558                         } else if (isset($type) && isset($type_prefix)) {
559                             $type_str = " xsi:type=\"$type_prefix:$type\"";
560                         } else {
561                             $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"xsd:anyType[0]\"";
562                         }
563                     }
564                     // TODO: for array in literal, there is no wrapper here
565                     $xml = "<$name$xmlns$type_str$atts>".$xml."</$name>";
566                 } else {
567                     // got a struct
568                     if(isset($type) && isset($type_prefix)){
569                         $type_str = " xsi:type=\"$type_prefix:$type\"";
570                     } else {
571                         $type_str = '';
572                     }
573                     if ($use == 'literal') {
574                         $xml .= "<$name$xmlns $atts>";
575                     } else {
576                         $xml .= "<$name$xmlns$type_str$atts>";
577                     }
578                     foreach($val as $k => $v){
579                         // Apache Map
580                         if ($type == 'Map' && $type_ns == 'http://xml.apache.org/xml-soap') {
581                             $xml .= '<item>';
582                             $xml .= $this->serialize_val($k,'key',false,false,false,false,$use);
583                             $xml .= $this->serialize_val($v,'value',false,false,false,false,$use);
584                             $xml .= '</item>';
585                         } else {
586                             $xml .= $this->serialize_val($v,$k,false,false,false,false,$use);
587                         }
588                     }
589                     $xml .= "</$name>";
590                 }
591                 break;
592             default:
593                 $xml .= 'not detected, got '.gettype($val).' for '.$val;
594                 break;
595         }
596         return $xml;
597     }
598
599     /**
600     * serializes a message
601     *
602     * @param string $body the XML of the SOAP body
603     * @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers
604     * @param array $namespaces optional the namespaces used in generating the body and headers
605     * @param string $style optional (rpc|document)
606     * @param string $use optional (encoded|literal)
607     * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
608     * @return string the message
609     * @access public
610     */
611     function serializeEnvelope($body,$headers=false,$namespaces=array(),$style='rpc',$use='encoded',$encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'){
612     // TODO: add an option to automatically run utf8_encode on $body and $headers
613     // if $this->soap_defencoding is UTF-8.  Not doing this automatically allows
614     // one to send arbitrary UTF-8 characters, not just characters that map to ISO-8859-1
615
616     $this->debug("In serializeEnvelope length=" . strlen($body) . " body (max 1000 characters)=" . substr($body, 0, 1000) . " style=$style use=$use encodingStyle=$encodingStyle");
617     $this->debug("headers:");
618     $this->appendDebug($this->varDump($headers));
619     $this->debug("namespaces:");
620     $this->appendDebug($this->varDump($namespaces));
621
622     // serialize namespaces
623     $ns_string = '';
624     foreach(array_merge($this->namespaces,$namespaces) as $k => $v){
625         $ns_string .= " xmlns:$k=\"$v\"";
626     }
627     if($encodingStyle) {
628         $ns_string = " SOAP-ENV:encodingStyle=\"$encodingStyle\"$ns_string";
629     }
630
631     // serialize headers
632     if($headers){
633         if (is_array($headers)) {
634             $xml = '';
635             foreach ($headers as $header) {
636                 $xml .= $this->serialize_val($header, false, false, false, false, false, $use);
637             }
638             $headers = $xml;
639             $this->debug("In serializeEnvelope, serialzied array of headers to $headers");
640         }
641         $headers = "<SOAP-ENV:Header>".$headers."</SOAP-ENV:Header>";
642     }
643     // serialize envelope
644     return
645     '<?xml version="1.0" encoding="'.$this->soap_defencoding .'"?'.">".
646     '<SOAP-ENV:Envelope'.$ns_string.">".
647     $headers.
648     "<SOAP-ENV:Body>".
649         $body.
650     "</SOAP-ENV:Body>".
651     "</SOAP-ENV:Envelope>";
652     }
653
654     /**
655      * formats a string to be inserted into an HTML stream
656      *
657      * @param string $str The string to format
658      * @return string The formatted string
659      * @access public
660      * @deprecated
661      */
662     function formatDump($str){
663         $str = htmlspecialchars($str);
664         return nl2br($str);
665     }
666
667     /**
668     * contracts (changes namespace to prefix) a qualified name
669     *
670     * @param    string $qname qname
671     * @return    string contracted qname
672     * @access   private
673     */
674     function contractQname($qname){
675         // get element namespace
676         //$this->xdebug("Contract $qname");
677         if (strrpos($qname, ':')) {
678             // get unqualified name
679             $name = substr($qname, strrpos($qname, ':') + 1);
680             // get ns
681             $ns = substr($qname, 0, strrpos($qname, ':'));
682             $p = $this->getPrefixFromNamespace($ns);
683             if ($p) {
684                 return $p . ':' . $name;
685             }
686             return $qname;
687         } else {
688             return $qname;
689         }
690     }
691
692     /**
693     * expands (changes prefix to namespace) a qualified name
694     *
695     * @param    string $string qname
696     * @return    string expanded qname
697     * @access   private
698     */
699     function expandQname($qname){
700         // get element prefix
701         if(strpos($qname,':') && !ereg('^http://',$qname)){
702             // get unqualified name
703             $name = substr(strstr($qname,':'),1);
704             // get ns prefix
705             $prefix = substr($qname,0,strpos($qname,':'));
706             if(isset($this->namespaces[$prefix])){
707                 return $this->namespaces[$prefix].':'.$name;
708             } else {
709                 return $qname;
710             }
711         } else {
712             return $qname;
713         }
714     }
715
716     /**
717     * returns the local part of a prefixed string
718     * returns the original string, if not prefixed
719     *
720     * @param string $str The prefixed string
721     * @return string The local part
722     * @access public
723     */
724     function getLocalPart($str){
725         if($sstr = strrchr($str,':')){
726             // get unqualified name
727             return substr( $sstr, 1 );
728         } else {
729             return $str;
730         }
731     }
732
733     /**
734     * returns the prefix part of a prefixed string
735     * returns false, if not prefixed
736     *
737     * @param string $str The prefixed string
738     * @return mixed The prefix or false if there is no prefix
739     * @access public
740     */
741     function getPrefix($str){
742         if($pos = strrpos($str,':')){
743             // get prefix
744             return substr($str,0,$pos);
745         }
746         return false;
747     }
748
749     /**
750     * pass it a prefix, it returns a namespace
751     *
752     * @param string $prefix The prefix
753     * @return mixed The namespace, false if no namespace has the specified prefix
754     * @access public
755     */
756     function getNamespaceFromPrefix($prefix){
757         if (isset($this->namespaces[$prefix])) {
758             return $this->namespaces[$prefix];
759         }
760         //$this->setError("No namespace registered for prefix '$prefix'");
761         return false;
762     }
763
764     /**
765     * returns the prefix for a given namespace (or prefix)
766     * or false if no prefixes registered for the given namespace
767     *
768     * @param string $ns The namespace
769     * @return mixed The prefix, false if the namespace has no prefixes
770     * @access public
771     */
772     function getPrefixFromNamespace($ns) {
773         foreach ($this->namespaces as $p => $n) {
774             if ($ns == $n || $ns == $p) {
775                 $this->usedNamespaces[$p] = $n;
776                 return $p;
777             }
778         }
779         return false;
780     }
781
782     /**
783     * returns the time in ODBC canonical form with microseconds
784     *
785     * @return string The time in ODBC canonical form with microseconds
786     * @access public
787     */
788     function getmicrotime() {
789         if (function_exists('gettimeofday')) {
790             $tod = gettimeofday();
791             $sec = $tod['sec'];
792             $usec = $tod['usec'];
793         } else {
794             $sec = time();
795             $usec = 0;
796         }
797         return strftime('%Y-%m-%d %H:%M:%S', $sec) . '.' . sprintf('%06d', $usec);
798     }
799
800     /**
801      * Returns a string with the output of var_dump
802      *
803      * @param mixed $data The variable to var_dump
804      * @return string The output of var_dump
805      * @access public
806      */
807     function varDump($data) {
808         ob_start();
809         var_dump($data);
810         $ret_val = ob_get_contents();
811         ob_end_clean();
812         return $ret_val;
813     }
814 }
815
816 // XML Schema Datatype Helper Functions
817
818 //xsd:dateTime helpers
819
820 /**
821 * convert unix timestamp to ISO 8601 compliant date string
822 *
823 * @param    string $timestamp Unix time stamp
824 * @access   public
825 */
826 function timestamp_to_iso8601($timestamp,$utc=true){
827     $datestr = date('Y-m-d\TH:i:sO',$timestamp);
828     if($utc){
829         $eregStr =
830         '([0-9]{4})-'.    // centuries & years CCYY-
831         '([0-9]{2})-'.    // months MM-
832         '([0-9]{2})'.    // days DD
833         'T'.            // separator T
834         '([0-9]{2}):'.    // hours hh:
835         '([0-9]{2}):'.    // minutes mm:
836         '([0-9]{2})(\.[0-9]*)?'. // seconds ss.ss...
837         '(Z|[+\-][0-9]{2}:?[0-9]{2})?'; // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
838
839         if(ereg($eregStr,$datestr,$regs)){
840             return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ',$regs[1],$regs[2],$regs[3],$regs[4],$regs[5],$regs[6]);
841         }
842         return false;
843     } else {
844         return $datestr;
845     }
846 }
847
848 /**
849 * convert ISO 8601 compliant date string to unix timestamp
850 *
851 * @param    string $datestr ISO 8601 compliant date string
852 * @access   public
853 */
854 function iso8601_to_timestamp($datestr){
855     $eregStr =
856     '([0-9]{4})-'.    // centuries & years CCYY-
857     '([0-9]{2})-'.    // months MM-
858     '([0-9]{2})'.    // days DD
859     'T'.            // separator T
860     '([0-9]{2}):'.    // hours hh:
861     '([0-9]{2}):'.    // minutes mm:
862     '([0-9]{2})(\.[0-9]+)?'. // seconds ss.ss...
863     '(Z|[+\-][0-9]{2}:?[0-9]{2})?'; // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
864     if(ereg($eregStr,$datestr,$regs)){
865         // not utc
866         if($regs[8] != 'Z'){
867             $op = substr($regs[8],0,1);
868             $h = substr($regs[8],1,2);
869             $m = substr($regs[8],strlen($regs[8])-2,2);
870             if($op == '-'){
871                 $regs[4] = $regs[4] + $h;
872                 $regs[5] = $regs[5] + $m;
873             } elseif($op == '+'){
874                 $regs[4] = $regs[4] - $h;
875                 $regs[5] = $regs[5] - $m;
876             }
877         }
878         return strtotime("$regs[1]-$regs[2]-$regs[3] $regs[4]:$regs[5]:$regs[6]Z");
879     } else {
880         return false;
881     }
882 }
883
884 /**
885 * sleeps some number of microseconds
886 *
887 * @param    string $usec the number of microseconds to sleep
888 * @access   public
889 * @deprecated
890 */
891 function usleepWindows($usec)
892 {
893     $start = gettimeofday();
894     
895     do
896     {
897         $stop = gettimeofday();
898         $timePassed = 1000000 * ($stop['sec'] - $start['sec'])
899         + $stop['usec'] - $start['usec'];
900     }
901     while ($timePassed < $usec);
902 }
903
904 ?><?php
905
906
907
908 /**
909 * Contains information for a SOAP fault.
910 * Mainly used for returning faults from deployed functions
911 * in a server instance.
912 * @author   Dietrich Ayala <dietrich@ganx4.com>
913 * @version  $Id: nusoap.php,v 1.94 2005/08/04 01:27:42 snichol Exp $
914 * @access public
915 */
916 class soap_fault extends nusoap_base {
917     /**
918      * The fault code (client|server)
919      * @var string
920      * @access private
921      */
922     var $faultcode;
923     /**
924      * The fault actor
925      * @var string
926      * @access private
927      */
928     var $faultactor;
929     /**
930      * The fault string, a description of the fault
931      * @var string
932      * @access private
933      */
934     var $faultstring;
935     /**
936      * The fault detail, typically a string or array of string
937      * @var mixed
938      * @access private
939      */
940     var $faultdetail;
941
942     /**
943     * constructor
944     *
945     * @param string $faultcode (client | server)
946     * @param string $faultactor only used when msg routed between multiple actors
947     * @param string $faultstring human readable error message
948     * @param mixed $faultdetail detail, typically a string or array of string
949     */
950     function soap_fault($faultcode,$faultactor='',$faultstring='',$faultdetail=''){
951         parent::nusoap_base();
952         $this->faultcode = $faultcode;
953         $this->faultactor = $faultactor;
954         $this->faultstring = $faultstring;
955         $this->faultdetail = $faultdetail;
956     }
957
958     /**
959     * serialize a fault
960     *
961     * @return    string    The serialization of the fault instance.
962     * @access   public
963     */
964     function serialize(){
965         $ns_string = '';
966         foreach($this->namespaces as $k => $v){
967             $ns_string .= "\n  xmlns:$k=\"$v\"";
968         }
969         $return_msg =
970             '<?xml version="1.0" encoding="'.$this->soap_defencoding.'"?>'.
971             '<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"'.$ns_string.">\n".
972                 '<SOAP-ENV:Body>'.
973                 '<SOAP-ENV:Fault>'.
974                     $this->serialize_val($this->faultcode, 'faultcode').
975                     $this->serialize_val($this->faultactor, 'faultactor').
976                     $this->serialize_val($this->faultstring, 'faultstring').
977                     $this->serialize_val($this->faultdetail, 'detail').
978                 '</SOAP-ENV:Fault>'.
979                 '</SOAP-ENV:Body>'.
980             '</SOAP-ENV:Envelope>';
981         return $return_msg;
982     }
983 }
984
985
986
987 ?><?php
988
989
990
991 /**
992 * parses an XML Schema, allows access to it's data, other utility methods
993 * no validation... yet.
994 * very experimental and limited. As is discussed on XML-DEV, I'm one of the people
995 * that just doesn't have time to read the spec(s) thoroughly, and just have a couple of trusty
996 * tutorials I refer to :)
997 *
998 * @author   Dietrich Ayala <dietrich@ganx4.com>
999 * @version  $Id: nusoap.php,v 1.94 2005/08/04 01:27:42 snichol Exp $
1000 * @access   public
1001 */
1002 class XMLSchema extends nusoap_base  {
1003     
1004     // files
1005     var $schema = '';
1006     var $xml = '';
1007     // namespaces
1008     var $enclosingNamespaces;
1009     // schema info
1010     var $schemaInfo = array();
1011     var $schemaTargetNamespace = '';
1012     // types, elements, attributes defined by the schema
1013     var $attributes = array();
1014     var $complexTypes = array();
1015     var $complexTypeStack = array();
1016     var $currentComplexType = null;
1017     var $elements = array();
1018     var $elementStack = array();
1019     var $currentElement = null;
1020     var $simpleTypes = array();
1021     var $simpleTypeStack = array();
1022     var $currentSimpleType = null;
1023     // imports
1024     var $imports = array();
1025     // parser vars
1026     var $parser;
1027     var $position = 0;
1028     var $depth = 0;
1029     var $depth_array = array();
1030     var $message = array();
1031     var $defaultNamespace = array();
1032     
1033     /**
1034     * constructor
1035     *
1036     * @param    string $schema schema document URI
1037     * @param    string $xml xml document URI
1038     * @param    string $namespaces namespaces defined in enclosing XML
1039     * @access   public
1040     */
1041     function XMLSchema($schema='',$xml='',$namespaces=array()){
1042         parent::nusoap_base();
1043         $this->debug('xmlschema class instantiated, inside constructor');
1044         // files
1045         $this->schema = $schema;
1046         $this->xml = $xml;
1047
1048         // namespaces
1049         $this->enclosingNamespaces = $namespaces;
1050         $this->namespaces = array_merge($this->namespaces, $namespaces);
1051
1052         // parse schema file
1053         if($schema != ''){
1054             $this->debug('initial schema file: '.$schema);
1055             $this->parseFile($schema, 'schema');
1056         }
1057
1058         // parse xml file
1059         if($xml != ''){
1060             $this->debug('initial xml file: '.$xml);
1061             $this->parseFile($xml, 'xml');
1062         }
1063
1064     }
1065
1066     /**
1067     * parse an XML file
1068     *
1069     * @param string $xml, path/URL to XML file
1070     * @param string $type, (schema | xml)
1071     * @return boolean
1072     * @access public
1073     */
1074     function parseFile($xml,$type){
1075         // parse xml file
1076         if($xml != ""){
1077             $xmlStr = @join("",@file($xml));
1078             if($xmlStr == ""){
1079                 $msg = 'Error reading XML from '.$xml;
1080                 $this->setError($msg);
1081                 $this->debug($msg);
1082             return false;
1083             } else {
1084                 $this->debug("parsing $xml");
1085                 $this->parseString($xmlStr,$type);
1086                 $this->debug("done parsing $xml");
1087             return true;
1088             }
1089         }
1090         return false;
1091     }
1092
1093     /**
1094     * parse an XML string
1095     *
1096     * @param    string $xml path or URL
1097     * @param string $type, (schema|xml)
1098     * @access   private
1099     */
1100     function parseString($xml,$type){
1101         // parse xml string
1102         if($xml != ""){
1103
1104             // Create an XML parser.
1105             $this->parser = xml_parser_create();
1106             // Set the options for parsing the XML data.
1107             xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
1108
1109             // Set the object for the parser.
1110             xml_set_object($this->parser, $this);
1111
1112             // Set the element handlers for the parser.
1113             if($type == "schema"){
1114                 xml_set_element_handler($this->parser, 'schemaStartElement','schemaEndElement');
1115                 xml_set_character_data_handler($this->parser,'schemaCharacterData');
1116             } elseif($type == "xml"){
1117                 xml_set_element_handler($this->parser, 'xmlStartElement','xmlEndElement');
1118                 xml_set_character_data_handler($this->parser,'xmlCharacterData');
1119             }
1120
1121             // Parse the XML file.
1122             if(!xml_parse($this->parser,$xml,true)){
1123             // Display an error message.
1124                 $errstr = sprintf('XML error parsing XML schema on line %d: %s',
1125                 xml_get_current_line_number($this->parser),
1126                 xml_error_string(xml_get_error_code($this->parser))
1127                 );
1128                 $this->debug($errstr);
1129                 $this->debug("XML payload:\n" . $xml);
1130                 $this->setError($errstr);
1131             }
1132             
1133             xml_parser_free($this->parser);
1134         } else{
1135             $this->debug('no xml passed to parseString()!!');
1136             $this->setError('no xml passed to parseString()!!');
1137         }
1138     }
1139
1140     /**
1141     * start-element handler
1142     *
1143     * @param    string $parser XML parser object
1144     * @param    string $name element name
1145     * @param    string $attrs associative array of attributes
1146     * @access   private
1147     */
1148     function schemaStartElement($parser, $name, $attrs) {
1149         
1150         // position in the total number of elements, starting from 0
1151         $pos = $this->position++;
1152         $depth = $this->depth++;
1153         // set self as current value for this depth
1154         $this->depth_array[$depth] = $pos;
1155         $this->message[$pos] = array('cdata' => '');
1156         if ($depth > 0) {
1157             $this->defaultNamespace[$pos] = $this->defaultNamespace[$this->depth_array[$depth - 1]];
1158         } else {
1159             $this->defaultNamespace[$pos] = false;
1160         }
1161
1162         // get element prefix
1163         if($prefix = $this->getPrefix($name)){
1164             // get unqualified name
1165             $name = $this->getLocalPart($name);
1166         } else {
1167             $prefix = '';
1168         }
1169         
1170         // loop thru attributes, expanding, and registering namespace declarations
1171         if(count($attrs) > 0){
1172             foreach($attrs as $k => $v){
1173                 // if ns declarations, add to class level array of valid namespaces
1174                 if(ereg("^xmlns",$k)){
1175                     //$this->xdebug("$k: $v");
1176                     //$this->xdebug('ns_prefix: '.$this->getPrefix($k));
1177                     if($ns_prefix = substr(strrchr($k,':'),1)){
1178                         //$this->xdebug("Add namespace[$ns_prefix] = $v");
1179                         $this->namespaces[$ns_prefix] = $v;
1180                     } else {
1181                         $this->defaultNamespace[$pos] = $v;
1182                         if (! $this->getPrefixFromNamespace($v)) {
1183                             $this->namespaces['ns'.(count($this->namespaces)+1)] = $v;
1184                         }
1185                     }
1186                     if($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema'){
1187                         $this->XMLSchemaVersion = $v;
1188                         $this->namespaces['xsi'] = $v.'-instance';
1189                     }
1190                 }
1191             }
1192             foreach($attrs as $k => $v){
1193                 // expand each attribute
1194                 $k = strpos($k,':') ? $this->expandQname($k) : $k;
1195                 $v = strpos($v,':') ? $this->expandQname($v) : $v;
1196                 $eAttrs[$k] = $v;
1197             }
1198             $attrs = $eAttrs;
1199         } else {
1200             $attrs = array();
1201         }
1202         // find status, register data
1203         switch($name){
1204             case 'all':            // (optional) compositor content for a complexType
1205             case 'choice':
1206             case 'group':
1207             case 'sequence':
1208                 //$this->xdebug("compositor $name for currentComplexType: $this->currentComplexType and currentElement: $this->currentElement");
1209                 $this->complexTypes[$this->currentComplexType]['compositor'] = $name;
1210                 //if($name == 'all' || $name == 'sequence'){
1211                 //    $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1212                 //}
1213             break;
1214             case 'attribute':    // complexType attribute
1215                 //$this->xdebug("parsing attribute $attrs[name] $attrs[ref] of value: ".$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']);
1216                 $this->xdebug("parsing attribute:");
1217                 $this->appendDebug($this->varDump($attrs));
1218                 if (!isset($attrs['form'])) {
1219                     $attrs['form'] = $this->schemaInfo['attributeFormDefault'];
1220                 }
1221                 if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1222                     $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1223                     if (!strpos($v, ':')) {
1224                         // no namespace in arrayType attribute value...
1225                         if ($this->defaultNamespace[$pos]) {
1226                             // ...so use the default
1227                             $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'] = $this->defaultNamespace[$pos] . ':' . $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1228                         }
1229                     }
1230                 }
1231                 if(isset($attrs['name'])){
1232                     $this->attributes[$attrs['name']] = $attrs;
1233                     $aname = $attrs['name'];
1234                 } elseif(isset($attrs['ref']) && $attrs['ref'] == 'http://schemas.xmlsoap.org/soap/encoding/:arrayType'){
1235                     if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1236                         $aname = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1237                     } else {
1238                         $aname = '';
1239                     }
1240                 } elseif(isset($attrs['ref'])){
1241                     $aname = $attrs['ref'];
1242                     $this->attributes[$attrs['ref']] = $attrs;
1243                 }
1244                 
1245                 if($this->currentComplexType){    // This should *always* be
1246                     $this->complexTypes[$this->currentComplexType]['attrs'][$aname] = $attrs;
1247                 }
1248                 // arrayType attribute
1249                 if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']) || $this->getLocalPart($aname) == 'arrayType'){
1250                     $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1251                     $prefix = $this->getPrefix($aname);
1252                     if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])){
1253                         $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1254                     } else {
1255                         $v = '';
1256                     }
1257                     if(strpos($v,'[,]')){
1258                         $this->complexTypes[$this->currentComplexType]['multidimensional'] = true;
1259                     }
1260                     $v = substr($v,0,strpos($v,'[')); // clip the []
1261                     if(!strpos($v,':') && isset($this->typemap[$this->XMLSchemaVersion][$v])){
1262                         $v = $this->XMLSchemaVersion.':'.$v;
1263                     }
1264                     $this->complexTypes[$this->currentComplexType]['arrayType'] = $v;
1265                 }
1266             break;
1267             case 'complexContent':    // (optional) content for a complexType
1268             break;
1269             case 'complexType':
1270                 array_push($this->complexTypeStack, $this->currentComplexType);
1271                 if(isset($attrs['name'])){
1272                     $this->xdebug('processing named complexType '.$attrs['name']);
1273                     //$this->currentElement = false;
1274                     $this->currentComplexType = $attrs['name'];
1275                     $this->complexTypes[$this->currentComplexType] = $attrs;
1276                     $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
1277                     // This is for constructs like
1278                     //           <complexType name="ListOfString" base="soap:Array">
1279                     //                <sequence>
1280                     //                    <element name="string" type="xsd:string"
1281                     //                        minOccurs="0" maxOccurs="unbounded" />
1282                     //                </sequence>
1283                     //            </complexType>
1284                     if(isset($attrs['base']) && ereg(':Array$',$attrs['base'])){
1285                         $this->xdebug('complexType is unusual array');
1286                         $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1287                     } else {
1288                         $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1289                     }
1290                 }else{
1291                     $this->xdebug('processing unnamed complexType for element '.$this->currentElement);
1292                     $this->currentComplexType = $this->currentElement . '_ContainedType';
1293                     //$this->currentElement = false;
1294                     $this->complexTypes[$this->currentComplexType] = $attrs;
1295                     $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
1296                     // This is for constructs like
1297                     //           <complexType name="ListOfString" base="soap:Array">
1298                     //                <sequence>
1299                     //                    <element name="string" type="xsd:string"
1300                     //                        minOccurs="0" maxOccurs="unbounded" />
1301                     //                </sequence>
1302                     //            </complexType>
1303                     if(isset($attrs['base']) && ereg(':Array$',$attrs['base'])){
1304                         $this->xdebug('complexType is unusual array');
1305                         $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1306                     } else {
1307                         $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1308                     }
1309                 }
1310             break;
1311             case 'element':
1312                 array_push($this->elementStack, $this->currentElement);
1313                 // elements defined as part of a complex type should
1314                 // not really be added to $this->elements, but for some
1315                 // reason, they are
1316                 if (!isset($attrs['form'])) {
1317                     $attrs['form'] = $this->schemaInfo['elementFormDefault'];
1318                 }
1319                 if(isset($attrs['type'])){
1320                     $this->xdebug("processing typed element ".$attrs['name']." of type ".$attrs['type']);
1321                     if (! $this->getPrefix($attrs['type'])) {
1322                         if ($this->defaultNamespace[$pos]) {
1323                             $attrs['type'] = $this->defaultNamespace[$pos] . ':' . $attrs['type'];
1324                             $this->xdebug('used default namespace to make type ' . $attrs['type']);
1325                         }
1326                     }
1327                     // This is for constructs like
1328                     //           <complexType name="ListOfString" base="soap:Array">
1329                     //                <sequence>
1330                     //                    <element name="string" type="xsd:string"
1331                     //                        minOccurs="0" maxOccurs="unbounded" />
1332                     //                </sequence>
1333                     //            </complexType>
1334                     if ($this->currentComplexType && $this->complexTypes[$this->currentComplexType]['phpType'] == 'array') {
1335                         $this->xdebug('arrayType for unusual array is ' . $attrs['type']);
1336                         $this->complexTypes[$this->currentComplexType]['arrayType'] = $attrs['type'];
1337                     }
1338                     $this->currentElement = $attrs['name'];
1339                     $this->elements[ $attrs['name'] ] = $attrs;
1340                     $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
1341                     $ename = $attrs['name'];
1342                 } elseif(isset($attrs['ref'])){
1343                     $this->xdebug("processing element as ref to ".$attrs['ref']);
1344                     $this->currentElement = "ref to ".$attrs['ref'];
1345                     $ename = $this->getLocalPart($attrs['ref']);
1346                 } else {
1347                     $this->xdebug("processing untyped element ".$attrs['name']);
1348                     $this->currentElement = $attrs['name'];
1349                     $this->elements[ $attrs['name'] ] = $attrs;
1350                     $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
1351                     $attrs['type'] = $this->schemaTargetNamespace . ':' . $attrs['name'] . '_ContainedType';
1352                     $this->elements[ $attrs['name'] ]['type'] = $attrs['type'];
1353                     $ename = $attrs['name'];
1354                 }
1355                 if(isset($ename) && $this->currentComplexType){
1356                     $this->complexTypes[$this->currentComplexType]['elements'][$ename] = $attrs;
1357                 }
1358             break;
1359             case 'enumeration':    //    restriction value list member
1360                 $this->xdebug('enumeration ' . $attrs['value']);
1361                 if ($this->currentSimpleType) {
1362                     $this->simpleTypes[$this->currentSimpleType]['enumeration'][] = $attrs['value'];
1363                 } elseif ($this->currentComplexType) {
1364                     $this->complexTypes[$this->currentComplexType]['enumeration'][] = $attrs['value'];
1365                 }
1366             break;
1367             case 'extension':    // simpleContent or complexContent type extension
1368                 $this->xdebug('extension ' . $attrs['base']);
1369                 if ($this->currentComplexType) {
1370                     $this->complexTypes[$this->currentComplexType]['extensionBase'] = $attrs['base'];
1371                 }
1372             break;
1373             case 'import':
1374                 if (isset($attrs['schemaLocation'])) {
1375                     //$this->xdebug('import namespace ' . $attrs['namespace'] . ' from ' . $attrs['schemaLocation']);
1376                     $this->imports[$attrs['namespace']][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
1377                 } else {
1378                     //$this->xdebug('import namespace ' . $attrs['namespace']);
1379                     $this->imports[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
1380                     if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
1381                         $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
1382                     }
1383                 }
1384             break;
1385             case 'list':    // simpleType value list
1386             break;
1387             case 'restriction':    // simpleType, simpleContent or complexContent value restriction
1388                 $this->xdebug('restriction ' . $attrs['base']);
1389                 if($this->currentSimpleType){
1390                     $this->simpleTypes[$this->currentSimpleType]['type'] = $attrs['base'];
1391                 } elseif($this->currentComplexType){
1392                     $this->complexTypes[$this->currentComplexType]['restrictionBase'] = $attrs['base'];
1393                     if(strstr($attrs['base'],':') == ':Array'){
1394                         $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1395                     }
1396                 }
1397             break;
1398             case 'schema':
1399                 $this->schemaInfo = $attrs;
1400                 $this->schemaInfo['schemaVersion'] = $this->getNamespaceFromPrefix($prefix);
1401                 if (isset($attrs['targetNamespace'])) {
1402                     $this->schemaTargetNamespace = $attrs['targetNamespace'];
1403                 }
1404                 if (!isset($attrs['elementFormDefault'])) {
1405                     $this->schemaInfo['elementFormDefault'] = 'unqualified';
1406                 }
1407                 if (!isset($attrs['attributeFormDefault'])) {
1408                     $this->schemaInfo['attributeFormDefault'] = 'unqualified';
1409                 }
1410             break;
1411             case 'simpleContent':    // (optional) content for a complexType
1412             break;
1413             case 'simpleType':
1414                 array_push($this->simpleTypeStack, $this->currentSimpleType);
1415                 if(isset($attrs['name'])){
1416                     $this->xdebug("processing simpleType for name " . $attrs['name']);
1417                     $this->currentSimpleType = $attrs['name'];
1418                     $this->simpleTypes[ $attrs['name'] ] = $attrs;
1419                     $this->simpleTypes[ $attrs['name'] ]['typeClass'] = 'simpleType';
1420                     $this->simpleTypes[ $attrs['name'] ]['phpType'] = 'scalar';
1421                 } else {
1422                     $this->xdebug('processing unnamed simpleType for element '.$this->currentElement);
1423                     $this->currentSimpleType = $this->currentElement . '_ContainedType';
1424                     //$this->currentElement = false;
1425                     $this->simpleTypes[$this->currentSimpleType] = $attrs;
1426                     $this->simpleTypes[$this->currentSimpleType]['phpType'] = 'scalar';
1427                 }
1428             break;
1429             case 'union':    // simpleType type list
1430             break;
1431             default:
1432                 //$this->xdebug("do not have anything to do for element $name");
1433         }
1434     }
1435
1436     /**
1437     * end-element handler
1438     *
1439     * @param    string $parser XML parser object
1440     * @param    string $name element name
1441     * @access   private
1442     */
1443     function schemaEndElement($parser, $name) {
1444         // bring depth down a notch
1445         $this->depth--;
1446         // position of current element is equal to the last value left in depth_array for my depth
1447         if(isset($this->depth_array[$this->depth])){
1448             $pos = $this->depth_array[$this->depth];
1449         }
1450         // get element prefix
1451         if ($prefix = $this->getPrefix($name)){
1452             // get unqualified name
1453             $name = $this->getLocalPart($name);
1454         } else {
1455             $prefix = '';
1456         }
1457         // move on...
1458         if($name == 'complexType'){
1459             $this->xdebug('done processing complexType ' . ($this->currentComplexType ? $this->currentComplexType : '(unknown)'));
1460             $this->currentComplexType = array_pop($this->complexTypeStack);
1461             //$this->currentElement = false;
1462         }
1463         if($name == 'element'){
1464             $this->xdebug('done processing element ' . ($this->currentElement ? $this->currentElement : '(unknown)'));
1465             $this->currentElement = array_pop($this->elementStack);
1466         }
1467         if($name == 'simpleType'){
1468             $this->xdebug('done processing simpleType ' . ($this->currentSimpleType ? $this->currentSimpleType : '(unknown)'));
1469             $this->currentSimpleType = array_pop($this->simpleTypeStack);
1470         }
1471     }
1472
1473     /**
1474     * element content handler
1475     *
1476     * @param    string $parser XML parser object
1477     * @param    string $data element content
1478     * @access   private
1479     */
1480     function schemaCharacterData($parser, $data){
1481         $pos = $this->depth_array[$this->depth - 1];
1482         $this->message[$pos]['cdata'] .= $data;
1483     }
1484
1485     /**
1486     * serialize the schema
1487     *
1488     * @access   public
1489     */
1490     function serializeSchema(){
1491
1492         $schemaPrefix = $this->getPrefixFromNamespace($this->XMLSchemaVersion);
1493         $xml = '';
1494         // imports
1495         if (sizeof($this->imports) > 0) {
1496             foreach($this->imports as $ns => $list) {
1497                 foreach ($list as $ii) {
1498                     if ($ii['location'] != '') {
1499                         $xml .= " <$schemaPrefix:import location=\"" . $ii['location'] . '" namespace="' . $ns . "\" />\n";
1500                     } else {
1501                         $xml .= " <$schemaPrefix:import namespace=\"" . $ns . "\" />\n";
1502                     }
1503                 }
1504             }
1505         }
1506         // complex types
1507         foreach($this->complexTypes as $typeName => $attrs){
1508             $contentStr = '';
1509             // serialize child elements
1510             if(isset($attrs['elements']) && (count($attrs['elements']) > 0)){
1511                 foreach($attrs['elements'] as $element => $eParts){
1512                     if(isset($eParts['ref'])){
1513                         $contentStr .= "   <$schemaPrefix:element ref=\"$element\"/>\n";
1514                     } else {
1515                         $contentStr .= "   <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "\"";
1516                         foreach ($eParts as $aName => $aValue) {
1517                             // handle, e.g., abstract, default, form, minOccurs, maxOccurs, nillable
1518                             if ($aName != 'name' && $aName != 'type') {
1519                                 $contentStr .= " $aName=\"$aValue\"";
1520                             }
1521                         }
1522                         $contentStr .= "/>\n";
1523                     }
1524                 }
1525                 // compositor wraps elements
1526                 if (isset($attrs['compositor']) && ($attrs['compositor'] != '')) {
1527                     $contentStr = "  <$schemaPrefix:$attrs[compositor]>\n".$contentStr."  </$schemaPrefix:$attrs[compositor]>\n";
1528                 }
1529             }
1530             // attributes
1531             if(isset($attrs['attrs']) && (count($attrs['attrs']) >= 1)){
1532                 foreach($attrs['attrs'] as $attr => $aParts){
1533                     $contentStr .= "    <$schemaPrefix:attribute";
1534                     foreach ($aParts as $a => $v) {
1535                         if ($a == 'ref' || $a == 'type') {
1536                             $contentStr .= " $a=\"".$this->contractQName($v).'"';
1537                         } elseif ($a == 'http://schemas.xmlsoap.org/wsdl/:arrayType') {
1538                             $this->usedNamespaces['wsdl'] = $this->namespaces['wsdl'];
1539                             $contentStr .= ' wsdl:arrayType="'.$this->contractQName($v).'"';
1540                         } else {
1541                             $contentStr .= " $a=\"$v\"";
1542                         }
1543                     }
1544                     $contentStr .= "/>\n";
1545                 }
1546             }
1547             // if restriction
1548             if (isset($attrs['restrictionBase']) && $attrs['restrictionBase'] != ''){
1549                 $contentStr = "   <$schemaPrefix:restriction base=\"".$this->contractQName($attrs['restrictionBase'])."\">\n".$contentStr."   </$schemaPrefix:restriction>\n";
1550                 // complex or simple content
1551                 if ((isset($attrs['elements']) && count($attrs['elements']) > 0) || (isset($attrs['attrs']) && count($attrs['attrs']) > 0)){
1552                     $contentStr = "  <$schemaPrefix:complexContent>\n".$contentStr."  </$schemaPrefix:complexContent>\n";
1553                 }
1554             }
1555             // finalize complex type
1556             if($contentStr != ''){
1557                 $contentStr = " <$schemaPrefix:complexType name=\"$typeName\">\n".$contentStr." </$schemaPrefix:complexType>\n";
1558             } else {
1559                 $contentStr = " <$schemaPrefix:complexType name=\"$typeName\"/>\n";
1560             }
1561             $xml .= $contentStr;
1562         }
1563         // simple types
1564         if(isset($this->simpleTypes) && count($this->simpleTypes) > 0){
1565             foreach($this->simpleTypes as $typeName => $eParts){
1566                 $xml .= " <$schemaPrefix:simpleType name=\"$typeName\">\n  <$schemaPrefix:restriction base=\"".$this->contractQName($eParts['type'])."\"/>\n";
1567                 if (isset($eParts['enumeration'])) {
1568                     foreach ($eParts['enumeration'] as $e) {
1569                         $xml .= "  <$schemaPrefix:enumeration value=\"$e\"/>\n";
1570                     }
1571                 }
1572                 $xml .= " </$schemaPrefix:simpleType>";
1573             }
1574         }
1575         // elements
1576         if(isset($this->elements) && count($this->elements) > 0){
1577             foreach($this->elements as $element => $eParts){
1578                 $xml .= " <$schemaPrefix:element name=\"$element\" type=\"".$this->contractQName($eParts['type'])."\"/>\n";
1579             }
1580         }
1581         // attributes
1582         if(isset($this->attributes) && count($this->attributes) > 0){
1583             foreach($this->attributes as $attr => $aParts){
1584                 $xml .= " <$schemaPrefix:attribute name=\"$attr\" type=\"".$this->contractQName($aParts['type'])."\"\n/>";
1585             }
1586         }
1587         // finish 'er up
1588         $el = "<$schemaPrefix:schema targetNamespace=\"$this->schemaTargetNamespace\"\n";
1589         foreach (array_diff($this->usedNamespaces, $this->enclosingNamespaces) as $nsp => $ns) {
1590             $el .= " xmlns:$nsp=\"$ns\"\n";
1591         }
1592         $xml = $el . ">\n".$xml."</$schemaPrefix:schema>\n";
1593         return $xml;
1594     }
1595
1596     /**
1597     * adds debug data to the clas level debug string
1598     *
1599     * @param    string $string debug data
1600     * @access   private
1601     */
1602     function xdebug($string){
1603         $this->debug('<' . $this->schemaTargetNamespace . '> '.$string);
1604     }
1605
1606     /**
1607     * get the PHP type of a user defined type in the schema
1608     * PHP type is kind of a misnomer since it actually returns 'struct' for assoc. arrays
1609     * returns false if no type exists, or not w/ the given namespace
1610     * else returns a string that is either a native php type, or 'struct'
1611     *
1612     * @param string $type, name of defined type
1613     * @param string $ns, namespace of type
1614     * @return mixed
1615     * @access public
1616     * @deprecated
1617     */
1618     function getPHPType($type,$ns){
1619         if(isset($this->typemap[$ns][$type])){
1620             //print "found type '$type' and ns $ns in typemap<br>";
1621             return $this->typemap[$ns][$type];
1622         } elseif(isset($this->complexTypes[$type])){
1623             //print "getting type '$type' and ns $ns from complexTypes array<br>";
1624             return $this->complexTypes[$type]['phpType'];
1625         }
1626         return false;
1627     }
1628
1629     /**
1630     * returns an associative array of information about a given type
1631     * returns false if no type exists by the given name
1632     *
1633     *    For a complexType typeDef = array(
1634     *    'restrictionBase' => '',
1635     *    'phpType' => '',
1636     *    'compositor' => '(sequence|all)',
1637     *    'elements' => array(), // refs to elements array
1638     *    'attrs' => array() // refs to attributes array
1639     *    ... and so on (see addComplexType)
1640     *    )
1641     *
1642     *   For simpleType or element, the array has different keys.
1643     *
1644     * @param string
1645     * @return mixed
1646     * @access public
1647     * @see addComplexType
1648     * @see addSimpleType
1649     * @see addElement
1650     */
1651     function getTypeDef($type){
1652         //$this->debug("in getTypeDef for type $type");
1653         if(isset($this->complexTypes[$type])){
1654             $this->xdebug("in getTypeDef, found complexType $type");
1655             return $this->complexTypes[$type];
1656         } elseif(isset($this->simpleTypes[$type])){
1657             $this->xdebug("in getTypeDef, found simpleType $type");
1658             if (!isset($this->simpleTypes[$type]['phpType'])) {
1659                 // get info for type to tack onto the simple type
1660                 // TODO: can this ever really apply (i.e. what is a simpleType really?)
1661                 $uqType = substr($this->simpleTypes[$type]['type'], strrpos($this->simpleTypes[$type]['type'], ':') + 1);
1662                 $ns = substr($this->simpleTypes[$type]['type'], 0, strrpos($this->simpleTypes[$type]['type'], ':'));
1663                 $etype = $this->getTypeDef($uqType);
1664                 if ($etype) {
1665                     $this->xdebug("in getTypeDef, found type for simpleType $type:");
1666                     $this->xdebug($this->varDump($etype));
1667                     if (isset($etype['phpType'])) {
1668                         $this->simpleTypes[$type]['phpType'] = $etype['phpType'];
1669                     }
1670                     if (isset($etype['elements'])) {
1671                         $this->simpleTypes[$type]['elements'] = $etype['elements'];
1672                     }
1673                 }
1674             }
1675             return $this->simpleTypes[$type];
1676         } elseif(isset($this->elements[$type])){
1677             $this->xdebug("in getTypeDef, found element $type");
1678             if (!isset($this->elements[$type]['phpType'])) {
1679                 // get info for type to tack onto the element
1680                 $uqType = substr($this->elements[$type]['type'], strrpos($this->elements[$type]['type'], ':') + 1);
1681                 $ns = substr($this->elements[$type]['type'], 0, strrpos($this->elements[$type]['type'], ':'));
1682                 $etype = $this->getTypeDef($uqType);
1683                 if ($etype) {
1684                     $this->xdebug("in getTypeDef, found type for element $type:");
1685                     $this->xdebug($this->varDump($etype));
1686                     if (isset($etype['phpType'])) {
1687                         $this->elements[$type]['phpType'] = $etype['phpType'];
1688                     }
1689                     if (isset($etype['elements'])) {
1690                         $this->elements[$type]['elements'] = $etype['elements'];
1691                     }
1692                 } elseif ($ns == 'http://www.w3.org/2001/XMLSchema') {
1693                     $this->xdebug("in getTypeDef, element $type is an XSD type");
1694                     $this->elements[$type]['phpType'] = 'scalar';
1695                 }
1696             }
1697             return $this->elements[$type];
1698         } elseif(isset($this->attributes[$type])){
1699             $this->xdebug("in getTypeDef, found attribute $type");
1700             return $this->attributes[$type];
1701         } elseif (ereg('_ContainedType$', $type)) {
1702             $this->xdebug("in getTypeDef, have an untyped element $type");
1703             $typeDef['typeClass'] = 'simpleType';
1704             $typeDef['phpType'] = 'scalar';
1705             $typeDef['type'] = 'http://www.w3.org/2001/XMLSchema:string';
1706             return $typeDef;
1707         }
1708         $this->xdebug("in getTypeDef, did not find $type");
1709         return false;
1710     }
1711
1712     /**
1713     * returns a sample serialization of a given type, or false if no type by the given name
1714     *
1715     * @param string $type, name of type
1716     * @return mixed
1717     * @access public
1718     * @deprecated
1719     */
1720     function serializeTypeDef($type){
1721         //print "in sTD() for type $type<br>";
1722     if($typeDef = $this->getTypeDef($type)){
1723         $str .= '<'.$type;
1724         if(is_array($typeDef['attrs'])){
1725         foreach($attrs as $attName => $data){
1726             $str .= " $attName=\"{type = ".$data['type']."}\"";
1727         }
1728         }
1729         $str .= " xmlns=\"".$this->schema['targetNamespace']."\"";
1730         if(count($typeDef['elements']) > 0){
1731         $str .= ">";
1732         foreach($typeDef['elements'] as $element => $eData){
1733             $str .= $this->serializeTypeDef($element);
1734         }
1735         $str .= "</$type>";
1736         } elseif($typeDef['typeClass'] == 'element') {
1737         $str .= "></$type>";
1738         } else {
1739         $str .= "/>";
1740         }
1741             return $str;
1742     }
1743         return false;
1744     }
1745
1746     /**
1747     * returns HTML form elements that allow a user
1748     * to enter values for creating an instance of the given type.
1749     *
1750     * @param string $name, name for type instance
1751     * @param string $type, name of type
1752     * @return string
1753     * @access public
1754     * @deprecated
1755     */
1756     function typeToForm($name,$type){
1757         // get typedef
1758         if($typeDef = $this->getTypeDef($type)){
1759             // if struct
1760             if($typeDef['phpType'] == 'struct'){
1761                 $buffer .= '<table>';
1762                 foreach($typeDef['elements'] as $child => $childDef){
1763                     $buffer .= "
1764                     <tr><td align='right'>$childDef[name] (type: ".$this->getLocalPart($childDef['type'])."):</td>
1765                     <td><input type='text' name='parameters[".$name."][$childDef[name]]'></td></tr>";
1766                 }
1767                 $buffer .= '</table>';
1768             // if array
1769             } elseif($typeDef['phpType'] == 'array'){
1770                 $buffer .= '<table>';
1771                 for($i=0;$i < 3; $i++){
1772                     $buffer .= "
1773                     <tr><td align='right'>array item (type: $typeDef[arrayType]):</td>
1774                     <td><input type='text' name='parameters[".$name."][]'></td></tr>";
1775                 }
1776                 $buffer .= '</table>';
1777             // if scalar
1778             } else {
1779                 $buffer .= "<input type='text' name='parameters[$name]'>";
1780             }
1781         } else {
1782             $buffer .= "<input type='text' name='parameters[$name]'>";
1783         }
1784         return $buffer;
1785     }
1786     
1787     /**
1788     * adds a complex type to the schema
1789     *
1790     * example: array
1791     *
1792     * addType(
1793     *     'ArrayOfstring',
1794     *     'complexType',
1795     *     'array',
1796     *     '',
1797     *     'SOAP-ENC:Array',
1798     *     array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'string[]'),
1799     *     'xsd:string'
1800     * );
1801     *
1802     * example: PHP associative array ( SOAP Struct )
1803     *
1804     * addType(
1805     *     'SOAPStruct',
1806     *     'complexType',
1807     *     'struct',
1808     *     'all',
1809     *     array('myVar'=> array('name'=>'myVar','type'=>'string')
1810     * );
1811     *
1812     * @param name
1813     * @param typeClass (complexType|simpleType|attribute)
1814     * @param phpType: currently supported are array and struct (php assoc array)
1815     * @param compositor (all|sequence|choice)
1816     * @param restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
1817     * @param elements = array ( name = array(name=>'',type=>'') )
1818     * @param attrs = array(
1819     *     array(
1820     *        'ref' => "http://schemas.xmlsoap.org/soap/encoding/:arrayType",
1821     *        "http://schemas.xmlsoap.org/wsdl/:arrayType" => "string[]"
1822     *     )
1823     * )
1824     * @param arrayType: namespace:name (http://www.w3.org/2001/XMLSchema:string)
1825     * @access public
1826     * @see getTypeDef
1827     */
1828     function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType=''){
1829         $this->complexTypes[$name] = array(
1830         'name'        => $name,
1831         'typeClass'    => $typeClass,
1832         'phpType'    => $phpType,
1833         'compositor'=> $compositor,
1834         'restrictionBase' => $restrictionBase,
1835         'elements'    => $elements,
1836         'attrs'        => $attrs,
1837         'arrayType'    => $arrayType
1838         );
1839         
1840         $this->xdebug("addComplexType $name:");
1841         $this->appendDebug($this->varDump($this->complexTypes[$name]));
1842     }
1843     
1844     /**
1845     * adds a simple type to the schema
1846     *
1847     * @param string $name
1848     * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
1849     * @param string $typeClass (should always be simpleType)
1850     * @param string $phpType (should always be scalar)
1851     * @param array $enumeration array of values
1852     * @access public
1853     * @see xmlschema
1854     * @see getTypeDef
1855     */
1856     function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {
1857         $this->simpleTypes[$name] = array(
1858         'name'            => $name,
1859         'typeClass'        => $typeClass,
1860         'phpType'        => $phpType,
1861         'type'            => $restrictionBase,
1862         'enumeration'    => $enumeration
1863         );
1864         
1865         $this->xdebug("addSimpleType $name:");
1866         $this->appendDebug($this->varDump($this->simpleTypes[$name]));
1867     }
1868
1869     /**
1870     * adds an element to the schema
1871     *
1872     * @param array $attrs attributes that must include name and type
1873     * @see xmlschema
1874     * @access public
1875     */
1876     function addElement($attrs) {
1877         if (! $this->getPrefix($attrs['type'])) {
1878             $attrs['type'] = $this->schemaTargetNamespace . ':' . $attrs['type'];
1879         }
1880         $this->elements[ $attrs['name'] ] = $attrs;
1881         $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
1882         
1883         $this->xdebug("addElement " . $attrs['name']);
1884         $this->appendDebug($this->varDump($this->elements[ $attrs['name'] ]));
1885     }
1886 }
1887
1888
1889
1890 ?><?php
1891
1892
1893
1894 /**
1895 * For creating serializable abstractions of native PHP types.  This class
1896 * allows element name/namespace, XSD type, and XML attributes to be
1897 * associated with a value.  This is extremely useful when WSDL is not
1898 * used, but is also useful when WSDL is used with polymorphic types, including
1899 * xsd:anyType and user-defined types.
1900 *
1901 * @author   Dietrich Ayala <dietrich@ganx4.com>
1902 * @version  $Id: nusoap.php,v 1.94 2005/08/04 01:27:42 snichol Exp $
1903 * @access   public
1904 */
1905 class soapval extends nusoap_base {
1906     /**
1907      * The XML element name
1908      *
1909      * @var string
1910      * @access private
1911      */
1912     var $name;
1913     /**
1914      * The XML type name (string or false)
1915      *
1916      * @var mixed
1917      * @access private
1918      */
1919     var $type;
1920     /**
1921      * The PHP value
1922      *
1923      * @var mixed
1924      * @access private
1925      */
1926     var $value;
1927     /**
1928      * The XML element namespace (string or false)
1929      *
1930      * @var mixed
1931      * @access private
1932      */
1933     var $element_ns;
1934     /**
1935      * The XML type namespace (string or false)
1936      *
1937      * @var mixed
1938      * @access private
1939      */
1940     var $type_ns;
1941     /**
1942      * The XML element attributes (array or false)
1943      *
1944      * @var mixed
1945      * @access private
1946      */
1947     var $attributes;
1948
1949     /**
1950     * constructor
1951     *
1952     * @param    string $name optional name
1953     * @param    mixed $type optional type name
1954     * @param    mixed $value optional value
1955     * @param    mixed $element_ns optional namespace of value
1956     * @param    mixed $type_ns optional namespace of type
1957     * @param    mixed $attributes associative array of attributes to add to element serialization