/home/a/aquarion/sites/www.aquarionics.com/epistula/include/nusoap.php
All my code (That is, anything not in the "Others" list on the right) is BSD licenced.
You can also view this page as text/plain or colour-coded source
<?php
/*
NuSOAP - Web Services Toolkit for PHP
Copyright (c) 2002 NuSphere Corporation
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
If you have any questions or comments, please email:
Dietrich Ayala
dietrich@ganx4.com
http://dietrich.ganx4.com/nusoap
NuSphere Corporation
http://www.nusphere.com
*/
// make errors handle properly in windows (thx, thong@xmethods.com)
//error_reporting(2039);
//error_reporting(E_ALL);
/* load classes
// necessary classes
require_once('class.soapclient.php');
require_once('class.soap_val.php');
require_once('class.soap_parser.php');
require_once('class.soap_fault.php');
// transport classes
require_once('class.soap_transport_http.php');
// optional add-on classes
require_once('class.xmlschema.php');
require_once('class.wsdl.php');
// server class
require_once('class.soap_server.php');*/
/**
*
* nusoap_base
*
* @author Dietrich Ayala <dietrich@ganx4.com>
* @version v 0.6.3
* @access public
*/
class nusoap_base {
var $title = 'NuSOAP';
var $version = '0.6.3';
var $error_str = false;
var $debug_str = '';
// toggles automatic encoding of special characters
var $charencoding = true;
/**
* set schema version
*
* @var XMLSchemaVersion
* @access public
*/
var $XMLSchemaVersion = 'http://www.w3.org/2001/XMLSchema';
/**
* set default encoding
*
* @var soap_defencoding
* @access public
*/
//var $soap_defencoding = 'UTF-8';
var $soap_defencoding = 'ISO-8859-1';
/**
* load namespace uris into an array of uri => prefix
*
* @var namespaces
* @access public
*/
var $namespaces = array(
'SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/',
'xsd' => 'http://www.w3.org/2001/XMLSchema',
'xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
'SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/',
'si' => 'http://soapinterop.org/xsd');
/**
* load types into typemap array
* is this legacy yet?
* no, this is used by the xmlschema class to verify type => namespace mappings.
* @var typemap
* @access public
*/
var $typemap = array(
'http://www.w3.org/2001/XMLSchema' => array(
'string'=>'string','boolean'=>'boolean','float'=>'double','double'=>'double','decimal'=>'double',
'duration'=>'','dateTime'=>'string','time'=>'string','date'=>'string','gYearMonth'=>'',
'gYear'=>'','gMonthDay'=>'','gDay'=>'','gMonth'=>'','hexBinary'=>'string','base64Binary'=>'string',
// derived datatypes
'normalizedString'=>'string','token'=>'string','language'=>'','NMTOKEN'=>'','NMTOKENS'=>'','Name'=>'','NCName'=>'','ID'=>'',
'IDREF'=>'','IDREFS'=>'','ENTITY'=>'','ENTITIES'=>'','integer'=>'integer','nonPositiveInteger'=>'integer',
'negativeInteger'=>'integer','long'=>'integer','int'=>'integer','short'=>'integer','byte'=>'integer','nonNegativeInteger'=>'integer',
'unsignedLong'=>'','unsignedInt'=>'','unsignedShort'=>'','unsignedByte'=>'','positiveInteger'=>''),
'http://www.w3.org/1999/XMLSchema' => array(
'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
'float'=>'double','dateTime'=>'string',
'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
'http://soapinterop.org/xsd' => array('SOAPStruct'=>'struct'),
'http://schemas.xmlsoap.org/soap/encoding/' => array('base64'=>'string','array'=>'array','Array'=>'array'),
'http://xml.apache.org/xml-soap' => array('Map')
);
/**
* entities to convert
*
* @var xmlEntities
* @access public
*/
var $xmlEntities = array('quot' => '"','amp' => '&',
'lt' => '<','gt' => '>','apos' => "'");
/**
* adds debug data to the class level debug string
*
* @param string $string debug data
* @access private
*/
function debug($string){
$this->debug_str .= get_class($this).": $string\n";
}
/**
* returns error string if present
*
* @return boolean $string error string
* @access public
*/
function getError(){
if($this->error_str != ''){
return $this->error_str;
}
return false;
}
/**
* sets error string
*
* @return boolean $string error string
* @access private
*/
function setError($str){
$this->error_str = $str;
}
/**
* serializes PHP values in accordance w/ section 5
* @return string
* @access public
*/
function serialize_val($val,$name=false,$type=false,$name_ns=false,$type_ns=false,$attributes=false){
if(is_object($val) && get_class($val) == 'soapval'){
return $val->serialize();
}
$this->debug( "in serialize_val: $val, $name, $type, $name_ns, $type_ns");
// if no name, use item
$name = (!$name|| is_numeric($name)) ? 'soapVal' : $name;
// if name has ns, add ns prefix to name
$xmlns = '';
if($name_ns){
$prefix = 'nu'.rand(1000,9999);
$name = $prefix.':'.$name;
$xmlns .= " xmlns:$prefix=\"$name_ns\"";
}
// if type is prefixed, create type prefix
if($type_ns != '' && $type_ns == $this->namespaces['xsd']){
// need to fix this. shouldn't default to xsd if no ns specified
// w/o checking against typemap
$type_prefix = 'xsd';
} elseif($type_ns){
$type_prefix = 'ns'.rand(1000,9999);
$xmlns .= " xmlns:$type_prefix=\"$type_ns\"";
}
// serialize attributes if present
if($attributes){
foreach($attributes as $k => $v){
$atts .= " $k=\"$v\"";
}
}
// serialize if an xsd built-in primitive type
if($type != '' && isset($this->typemap[$this->XMLSchemaVersion][$type])){
return "<$name$xmlns xsi:type=\"xsd:$type\">$val</$name>";
}
// detect type and serialize
$xml = '';
$atts = '';
switch(true) {
case ($type == '' && is_null($val)):
$xml .= "<$name$xmlns xsi:type=\"xsd:nil\"/>";
break;
case (is_bool($val) || $type == 'boolean'):
if(!$val){
$val = 0;
}
$xml .= "<$name$xmlns xsi:type=\"xsd:boolean\"$atts>$val</$name>";
break;
case (is_int($val) || is_long($val) || $type == 'int'):
$xml .= "<$name$xmlns xsi:type=\"xsd:int\"$atts>$val</$name>";
break;
case (is_float($val)|| is_double($val) || $type == 'float'):
$xml .= "<$name$xmlns xsi:type=\"xsd:float\"$atts>$val</$name>";
break;
case (is_string($val) || $type == 'string'):
if($this->charencoding){
$val = htmlspecialchars($val, ENT_QUOTES);
}
$xml .= "<$name$xmlns xsi:type=\"xsd:string\"$atts>$val</$name>";
break;
case is_object($val):
break;
break;
case (is_array($val) || $type):
// detect if struct or array
$keyList = array_keys($val);
$valueType = 'arraySimple';
foreach($keyList as $keyListValue){
if(!is_int($keyListValue)){
$valueType = 'arrayStruct';
}
}
if($valueType=='arraySimple' || ereg('^ArrayOf',$type)){
foreach($val as $v){
if(is_object($v) && get_class($v) == 'soapval'){
$tt = $v->type;
} else {
$tt = gettype($v);
}
$array_types[$tt] = 1;
$xml .= $this->serialize_val($v,'item');
$i = 0;
if(is_array($v) && is_numeric(key($v))){
$i += sizeof($v);
} else {
$i += 1;
}
}
if(count($array_types) > 1){
$array_typename = 'xsd:ur-type';
} elseif(isset($this->typemap[$this->XMLSchemaVersion][$tt])) {
$array_typename = 'xsd:'.$tt;
} elseif($tt == 'array' || $tt == 'Array'){
$array_typename = 'SOAP-ENC:Array';
} else {
$array_typename = $tt;
}
if(isset($array_types['array'])){
$array_type = $i.",".$i;
} else {
$array_type = $i;
}
$xml = "<$name xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"".$array_typename."[$array_type]\"$atts>".$xml."</$name>";
} else {
// got a struct
if(isset($type) && isset($type_prefix)){
$type_str = " xsi:type=\"$type_prefix:$type\"";
} else {
$type_str = '';
}
$xml .= "<$name$xmlns$type_str$atts>";
foreach($val as $k => $v){
$xml .= $this->serialize_val($v,$k);
}
$xml .= "</$name>";
}
break;
default:
$xml .= 'not detected, got '.gettype($val).' for '.$val;
break;
}
return $xml;
}
/**
* serialize message
*
* @param string body
* @param string headers
* @param array namespaces
* @return string message
* @access public
*/
function serializeEnvelope($body,$headers=false,$namespaces=array()){
// serialize namespaces
$ns_string = '';
foreach(array_merge($this->namespaces,$namespaces) as $k => $v){
$ns_string .= " xmlns:$k=\"$v\"";
}
// serialize headers
if($headers){
$headers = "<SOAP-ENV:Header>".$headers."</SOAP-ENV:Header>";
}
// serialize envelope
return
'<?xml version="1.0" encoding="'.$this->soap_defencoding .'"?'.">".
'<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"'.$ns_string.">".
$headers.
"<SOAP-ENV:Body>".
$body.
"</SOAP-ENV:Body>".
"</SOAP-ENV:Envelope>";
}
function formatDump($str){
$str = htmlspecialchars($str);
return nl2br($str);
}
/**
* returns the local part of a prefixed string
* returns the original string, if not prefixed
*
* @param string
* @return string
* @access public
*/
function getLocalPart($str){
if($sstr = strrchr($str,':')){
// get unqualified name
return substr( $sstr, 1 );
} else {
return $str;
}
}
/**
* returns the prefix part of a prefixed string
* returns false, if not prefixed
*
* @param string
* @return mixed
* @access public
*/
function getPrefix($str){
if($pos = strrpos($str,':')){
// get prefix
return substr($str,0,$pos);
}
return false;
}
function varDump($data) {
ob_start();
var_dump($data);
$ret_val = ob_get_contents();
ob_end_clean();
return $ret_val;
}
}
// XML Schema Datatype Helper Functions
//xsd:dateTime helpers
/**
* convert unix timestamp to ISO 8601 compliant date string
*
* @param string $timestamp Unix time stamp
* @access public
*/
function timestamp_to_iso8601($timestamp,$utc=true){
$datestr = date('Y-m-d\TH:i:sO',$timestamp);
if($utc){
$eregStr =
'([0-9]{4})-'. // centuries & years CCYY-
'([0-9]{2})-'. // months MM-
'([0-9]{2})'. // days DD
'T'. // separator T
'([0-9]{2}):'. // hours hh:
'([0-9]{2}):'. // minutes mm:
'([0-9]{2})(\.[0-9]*)?'. // seconds ss.ss...
'(Z|[+\-][0-9]{2}:?[0-9]{2})?'; // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
if(ereg($eregStr,$datestr,$regs)){
return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ',$regs[1],$regs[2],$regs[3],$regs[4],$regs[5],$regs[6]);
}
return false;
} else {
return $datestr;
}
}
/**
* convert ISO 8601 compliant date string to unix timestamp
*
* @param string $datestr ISO 8601 compliant date string
* @access public
*/
function iso8601_to_timestamp($datestr){
$eregStr =
'([0-9]{4})-'. // centuries & years CCYY-
'([0-9]{2})-'. // months MM-
'([0-9]{2})'. // days DD
'T'. // separator T
'([0-9]{2}):'. // hours hh:
'([0-9]{2}):'. // minutes mm:
'([0-9]{2})(\.[0-9]+)?'. // seconds ss.ss...
'(Z|[+\-][0-9]{2}:?[0-9]{2})?'; // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
if(ereg($eregStr,$datestr,$regs)){
// not utc
if($regs[8] != 'Z'){
$op = substr($regs[8],0,1);
$h = substr($regs[8],1,2);
$m = substr($regs[8],strlen($regs[8])-2,2);
if($op == '-'){
$regs[4] = $regs[4] + $h;
$regs[5] = $regs[5] + $m;
} elseif($op == '+'){
$regs[4] = $regs[4] - $h;
$regs[5] = $regs[5] - $m;
}
}
return strtotime("$regs[1]-$regs[2]-$regs[3] $regs[4]:$regs[5]:$regs[6]Z");
} else {
return false;
}
}
?><?php
/**
* soap_fault class, allows for creation of faults
* mainly used for returning faults from deployed functions
* in a server instance.
* @author Dietrich Ayala <dietrich@ganx4.com>
* @version v 0.6.3
* @access public
*/
class soap_fault extends nusoap_base {
var $faultcode;
var $faultactor;
var $faultstring;
var $faultdetail;
/**
* constructor
*
* @param string $faultcode (client | server)
* @param string $faultactor only used when msg routed between multiple actors
* @param string $faultstring human readable error message
* @param string $faultdetail
*/
function soap_fault($faultcode,$faultactor='',$faultstring='',$faultdetail=''){
$this->faultcode = $faultcode;
$this->faultactor = $faultactor;
$this->faultstring = $faultstring;
$this->faultdetail = $faultdetail;
}
/**
* serialize a fault
*
* @access public
*/
function serialize(){
$ns_string = '';
foreach($this->namespaces as $k => $v){
$ns_string .= "\n xmlns:$k=\"$v\"";
}
$return_msg =
'<?xml version="1.0"?'.">\n".
'<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"'.$ns_string.">\n".
'<SOAP-ENV:Body>'.
'<SOAP-ENV:Fault>'.
'<faultcode>'.$this->faultcode.'</faultcode>'.
'<faultactor>'.$this->faultactor.'</faultactor>'.
'<faultstring>'.$this->faultstring.'</faultstring>'.
'<detail>'.$this->serialize_val($this->faultdetail).'</detail>'.
'</SOAP-ENV:Fault>'.
'</SOAP-ENV:Body>'.
'</SOAP-ENV:Envelope>';
return $return_msg;
}
}
?><?php
/**
* parses an XML Schema, allows access to it's data, other utility methods
* no validation... yet.
* very experimental and limited. As is discussed on XML-DEV, I'm one of the people
* that just doesn't have time to read the spec(s) thoroughly, and just have a couple of trusty
* tutorials I refer to :)
*
* @author Dietrich Ayala <dietrich@ganx4.com>
* @version v 0.6.3
* @access public
*/
class XMLSchema extends nusoap_base {
// files
var $schema = '';
var $xml = '';
// define internal arrays of bindings, ports, operations, messages, etc.
var $complexTypes = array();
// target namespace
var $schemaTargetNamespace = '';
// parser vars
var $parser;
var $position;
var $depth = 0;
var $depth_array = array();
/**
* constructor
*
* @param string $schema schema document URI
* @param string $xml xml document URI
* @access public
*/
function XMLSchema($schema='',$xml=''){
$this->debug('xmlschema class instantiated, inside constructor');
// files
$this->schema = $schema;
$this->xml = $xml;
// parse schema file
if($schema != ''){
$this->debug('initial schema file: '.$schema);
$this->parseFile($schema);
}
// parse xml file
if($xml != ''){
$this->debug('initial xml file: '.$xml);
$this->parseFile($xml);
}
}
/**
* parse an XML file
*
* @param string $xml, path/URL to XML file
* @param string $type, (schema | xml)
* @return boolean
* @access public
*/
function parseFile($xml,$type){
// parse xml file
if($xml != ""){
$this->debug('parsing $xml');
$xmlStr = @join("",@file($xml));
if($xmlStr == ""){
$this->setError('No file at the specified URL: '.$xml);
return false;
} else {
$this->parseString($xmlStr,$type);
return true;
}
}
return false;
}
/**
* parse an XML string
*
* @param string $xml path or URL
* @param string $type, (schema|xml)
* @access private
*/
function parseString($xml,$type){
// parse xml string
if($xml != ""){
// Create an XML parser.
$this->parser = xml_parser_create();
// Set the options for parsing the XML data.
xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
// Set the object for the parser.
xml_set_object($this->parser, $this);
// Set the element handlers for the parser.
if($type == "schema"){
xml_set_element_handler($this->parser, 'schemaStartElement','schemaEndElement');
xml_set_character_data_handler($this->parser,'schemaCharacterData');
} elseif($type == "xml"){
xml_set_element_handler($this->parser, 'xmlStartElement"','xmlEndElement');
xml_set_character_data_handler($this->parser,'xmlCharacterData');
}
// Parse the XML file.
if(!xml_parse($this->parser,$xml,true)){
// Display an error message.
$errstr = sprintf('XML error on line %d: %s',
xml_get_current_line_number($this->parser),
xml_error_string(xml_get_error_code($this->parser))
);
$this->debug('XML parse error: '.$errstr);
$this->setError('Parser error: '.$errstr);
}
xml_parser_free($this->parser);
} else{
$this->debug('no xml passed to parseString()!!');
$this->setError('no xml passed to parseString()!!');
}
}
/**
* start-element handler
*
* @param string $parser XML parser object
* @param string $name element name
* @param string $attrs associative array of attributes
* @access private
*/
function schemaStartElement($parser, $name, $attrs) {
// position in the total number of elements, starting from 0
$pos = $this->position++;
$depth = $this->depth++;
// set self as current value for this depth
$this->depth_array[$depth] = $pos;
// get element prefix
if($prefix = $this->getPrefix($name)){
// get unqualified name
$name = $this->getLocalPart($name);
} else {
$prefix = '';
}
// loop thru attributes, expanding, and registering namespace declarations
if(count($attrs) > 0){
foreach($attrs as $k => $v){
// if ns declarations, add to class level array of valid namespaces
if(ereg("^xmlns",$k)){
//$this->xdebug("$k: $v");
//$this->xdebug('ns_prefix: '.$this->getPrefix($k));
if($ns_prefix = substr(strrchr($k,':'),1)){
$this->namespaces[$ns_prefix] = $v;
} else {
$this->namespaces['ns'.(count($this->namespaces)+1)] = $v;
}
if($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema'){
$this->XMLSchemaVersion = $v;
$this->namespaces['xsi'] = $v.'-instance';
}
}
// expand each attribute
$k = strpos($k,':') ? $this->expandQname($k) : $k;
$v = strpos($v,':') ? $this->expandQname($v) : $v;
$eAttrs[$k] = $v;
}
$attrs = $eAttrs;
} else {
$attrs = array();
}
// find status, register data
switch($name){
case ('all'|'choice'|'sequence'):
//$this->complexTypes[$this->currentComplexType]['compositor'] = 'all';
$this->complexTypes[$this->currentComplexType]['compositor'] = $name;
if($name == 'all'){
$this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
}
break;
case 'attribute':
//$this->xdebug("parsing attribute $attrs[name] $attrs[ref] of value: ".$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']);
if(isset($attrs['name'])){
$this->attributes[$attrs['name']] = $attrs;
$aname = $attrs['name'];
} elseif($attrs['ref']){
$aname = $attrs['ref'];
$this->attributes[$attrs['ref']] = $attrs;
}
if(isset($this->currentComplexType)){
$this->complexTypes[$this->currentComplexType]['attrs'][$aname] = $attrs;
} elseif(isset($this->currentElement)){
$this->elements[$this->currentElement]['attrs'][$aname] = $attrs;
}
// arrayType attribute
if($this->getLocalPart($aname) == 'arrayType'){
$this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])){
$v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
} else {
$v = '';
}
if(strpos($v,'[,]')){
$this->complexTypes[$this->currentComplexType]['multidimensional'] = true;
}
$v = substr($v,0,strpos($v,'[')); // clip the []
if(!strpos($v,':') && isset($this->typemap[$this->XMLSchemaVersion][$v])){
$v = $this->XMLSchemaVersion.':'.$v;
}
$this->complexTypes[$this->currentComplexType]['arrayType'] = $v;
}
break;
case 'complexType':
if(isset($attrs['name'])){
$this->currentElement = false;
$this->currentComplexType = $attrs['name'];
$this->complexTypes[$this->currentComplexType] = $attrs;
$this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
if(isset($attrs['base']) && ereg(':Array$',$attrs['base'])){
$this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
} else {
$this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
}
$this->xdebug('processing complexType '.$attrs['name']);
}
break;
case 'element':
if(isset($attrs['type'])){
$this->xdebug("processing element ".$attrs['name']);
$this->currentElement = $attrs['name'];
$this->elements[ $attrs['name'] ] = $attrs;
$this->elements[ $attrs['name'] ]['typeClass'] = 'element';
$ename = $attrs['name'];
} elseif(isset($attrs['ref'])){
$ename = $attrs['ref'];
} else {
$this->xdebug('adding complexType '.$attrs['name']);
$this->currentComplexType = $attrs['name'];
$this->complexTypes[ $attrs['name'] ] = $attrs;
$this->complexTypes[ $attrs['name'] ]['element'] = 1;
$this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
}
if(isset($ename) && $this->currentComplexType){
$this->complexTypes[$this->currentComplexType]['elements'][$ename] = $attrs;
}
break;
case 'restriction':
$this->xdebug("in restriction for ct: $this->currentComplexType and ce: $this->currentElement");
if($this->currentElement){
$this->elements[$this->currentElement]['type'] = $attrs['base'];
} elseif($this->currentComplexType){
$this->complexTypes[$this->currentComplexType]['restrictionBase'] = $attrs['base'];
if(strstr($attrs['base'],':') == ':Array'){
$this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
}
}
break;
case 'schema':
$this->schema = $attrs;
$this->schema['schemaVersion'] = $this->getNamespaceFromPrefix($prefix);
break;
case 'simpleType':
$this->currentElement = $attrs['name'];
$this->elements[ $attrs['name'] ] = $attrs;
$this->elements[ $attrs['name'] ]['typeClass'] = 'element';
break;
}
}
/**
* end-element handler
*
* @param string $parser XML parser object
* @param string $name element name
* @access private
*/
function schemaEndElement($parser, $name) {
// position of current element is equal to the last value left in depth_array for my depth
if(isset($this->depth_array[$this->depth])){
$pos = $this->depth_array[$this->depth];
}
// bring depth down a notch
$this->depth--;
// move on...
if($name == 'complexType'){
$this->currentComplexType = false;
$this->currentElement = false;
}
if($name == 'element'){
$this->currentElement = false;
}
}
/**
* element content handler
*
* @param string $parser XML parser object
* @param string $data element content
* @access private
*/
function schemaCharacterData($parser, $data){
$pos = $this->depth_array[$this->depth];
$this->message[$pos]['cdata'] .= $data;
}
/**
* serialize the schema
*
* @access public
*/
function serializeSchema(){
$schemaPrefix = $this->getPrefixFromNamespace($this->XMLSchemaVersion);
$xml = '';
// complex types
foreach($this->complexTypes as $typeName => $attrs){
$contentStr = '';
// serialize child elements
if(count($attrs['elements']) > 0){
foreach($attrs['elements'] as $element => $eParts){
if(isset($eParts['ref'])){
$contentStr .= "<element ref=\"$element\"/>";
} else {
$contentStr .= "<element name=\"$element\" type=\"$eParts[type]\"/>";
}
}
}
// attributes
if(count($attrs['attrs']) >= 1){
foreach($attrs['attrs'] as $attr => $aParts){
$contentStr .= '<attribute ref="'.$aParts['ref'].'"';
if(isset($aParts['wsdl:arrayType'])){
$contentStr .= ' wsdl:arrayType="'.$aParts['wsdl:arrayType'].'"';
}
$contentStr .= '/>';
}
}
// if restriction
if( isset($attrs['restrictionBase']) && $attrs['restrictionBase'] != ''){
$contentStr = "<$schemaPrefix:restriction base=\"".$attrs['restrictionBase']."\">".$contentStr."</$schemaPrefix:restriction>";
}
// "all" compositor obviates complex/simple content
if(isset($attrs['compositor']) && $attrs['compositor'] == 'all'){
$contentStr = "<$schemaPrefix:$attrs[compositor]>".$contentStr."</$schemaPrefix:$attrs[compositor]>";
}
// complex or simple content
elseif( count($attrs['elements']) > 0 || count($attrs