00001 <?php 00002 00003 00004 00005 00015 class nusoap_xmlschema extends nusoap_base { 00016 00017 // files 00018 var $schema = ''; 00019 var $xml = ''; 00020 // namespaces 00021 var $enclosingNamespaces; 00022 // schema info 00023 var $schemaInfo = array(); 00024 var $schemaTargetNamespace = ''; 00025 // types, elements, attributes defined by the schema 00026 var $attributes = array(); 00027 var $complexTypes = array(); 00028 var $complexTypeStack = array(); 00029 var $currentComplexType = null; 00030 var $elements = array(); 00031 var $elementStack = array(); 00032 var $currentElement = null; 00033 var $simpleTypes = array(); 00034 var $simpleTypeStack = array(); 00035 var $currentSimpleType = null; 00036 // imports 00037 var $imports = array(); 00038 // parser vars 00039 var $parser; 00040 var $position = 0; 00041 var $depth = 0; 00042 var $depth_array = array(); 00043 var $message = array(); 00044 var $defaultNamespace = array(); 00045 00054 function nusoap_xmlschema($schema='',$xml='',$namespaces=array()){ 00055 parent::nusoap_base(); 00056 $this->debug('nusoap_xmlschema class instantiated, inside constructor'); 00057 // files 00058 $this->schema = $schema; 00059 $this->xml = $xml; 00060 00061 // namespaces 00062 $this->enclosingNamespaces = $namespaces; 00063 $this->namespaces = array_merge($this->namespaces, $namespaces); 00064 00065 // parse schema file 00066 if($schema != ''){ 00067 $this->debug('initial schema file: '.$schema); 00068 $this->parseFile($schema, 'schema'); 00069 } 00070 00071 // parse xml file 00072 if($xml != ''){ 00073 $this->debug('initial xml file: '.$xml); 00074 $this->parseFile($xml, 'xml'); 00075 } 00076 00077 } 00078 00087 function parseFile($xml,$type){ 00088 // parse xml file 00089 if($xml != ""){ 00090 $xmlStr = @join("",@file($xml)); 00091 if($xmlStr == ""){ 00092 $msg = 'Error reading XML from '.$xml; 00093 $this->setError($msg); 00094 $this->debug($msg); 00095 return false; 00096 } else { 00097 $this->debug("parsing $xml"); 00098 $this->parseString($xmlStr,$type); 00099 $this->debug("done parsing $xml"); 00100 return true; 00101 } 00102 } 00103 return false; 00104 } 00105 00113 function parseString($xml,$type){ 00114 // parse xml string 00115 if($xml != ""){ 00116 00117 // Create an XML parser. 00118 $this->parser = xml_parser_create(); 00119 // Set the options for parsing the XML data. 00120 xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0); 00121 00122 // Set the object for the parser. 00123 xml_set_object($this->parser, $this); 00124 00125 // Set the element handlers for the parser. 00126 if($type == "schema"){ 00127 xml_set_element_handler($this->parser, 'schemaStartElement','schemaEndElement'); 00128 xml_set_character_data_handler($this->parser,'schemaCharacterData'); 00129 } elseif($type == "xml"){ 00130 xml_set_element_handler($this->parser, 'xmlStartElement','xmlEndElement'); 00131 xml_set_character_data_handler($this->parser,'xmlCharacterData'); 00132 } 00133 00134 // Parse the XML file. 00135 if(!xml_parse($this->parser,$xml,true)){ 00136 // Display an error message. 00137 $errstr = sprintf('XML error parsing XML schema on line %d: %s', 00138 xml_get_current_line_number($this->parser), 00139 xml_error_string(xml_get_error_code($this->parser)) 00140 ); 00141 $this->debug($errstr); 00142 $this->debug("XML payload:\n" . $xml); 00143 $this->setError($errstr); 00144 } 00145 00146 xml_parser_free($this->parser); 00147 } else{ 00148 $this->debug('no xml passed to parseString()!!'); 00149 $this->setError('no xml passed to parseString()!!'); 00150 } 00151 } 00152 00160 function CreateTypeName($ename) { 00161 $scope = ''; 00162 for ($i = 0; $i < count($this->complexTypeStack); $i++) { 00163 $scope .= $this->complexTypeStack[$i] . '_'; 00164 } 00165 return $scope . $ename . '_ContainedType'; 00166 } 00167 00176 function schemaStartElement($parser, $name, $attrs) { 00177 00178 // position in the total number of elements, starting from 0 00179 $pos = $this->position++; 00180 $depth = $this->depth++; 00181 // set self as current value for this depth 00182 $this->depth_array[$depth] = $pos; 00183 $this->message[$pos] = array('cdata' => ''); 00184 if ($depth > 0) { 00185 $this->defaultNamespace[$pos] = $this->defaultNamespace[$this->depth_array[$depth - 1]]; 00186 } else { 00187 $this->defaultNamespace[$pos] = false; 00188 } 00189 00190 // get element prefix 00191 if($prefix = $this->getPrefix($name)){ 00192 // get unqualified name 00193 $name = $this->getLocalPart($name); 00194 } else { 00195 $prefix = ''; 00196 } 00197 00198 // loop thru attributes, expanding, and registering namespace declarations 00199 if(count($attrs) > 0){ 00200 foreach($attrs as $k => $v){ 00201 // if ns declarations, add to class level array of valid namespaces 00202 if(ereg("^xmlns",$k)){ 00203 //$this->xdebug("$k: $v"); 00204 //$this->xdebug('ns_prefix: '.$this->getPrefix($k)); 00205 if($ns_prefix = substr(strrchr($k,':'),1)){ 00206 //$this->xdebug("Add namespace[$ns_prefix] = $v"); 00207 $this->namespaces[$ns_prefix] = $v; 00208 } else { 00209 $this->defaultNamespace[$pos] = $v; 00210 if (! $this->getPrefixFromNamespace($v)) { 00211 $this->namespaces['ns'.(count($this->namespaces)+1)] = $v; 00212 } 00213 } 00214 if($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema'){ 00215 $this->XMLSchemaVersion = $v; 00216 $this->namespaces['xsi'] = $v.'-instance'; 00217 } 00218 } 00219 } 00220 foreach($attrs as $k => $v){ 00221 // expand each attribute 00222 $k = strpos($k,':') ? $this->expandQname($k) : $k; 00223 $v = strpos($v,':') ? $this->expandQname($v) : $v; 00224 $eAttrs[$k] = $v; 00225 } 00226 $attrs = $eAttrs; 00227 } else { 00228 $attrs = array(); 00229 } 00230 // find status, register data 00231 switch($name){ 00232 case 'all': // (optional) compositor content for a complexType 00233 case 'choice': 00234 case 'group': 00235 case 'sequence': 00236 //$this->xdebug("compositor $name for currentComplexType: $this->currentComplexType and currentElement: $this->currentElement"); 00237 $this->complexTypes[$this->currentComplexType]['compositor'] = $name; 00238 //if($name == 'all' || $name == 'sequence'){ 00239 // $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct'; 00240 //} 00241 break; 00242 case 'attribute': // complexType attribute 00243 //$this->xdebug("parsing attribute $attrs[name] $attrs[ref] of value: ".$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']); 00244 $this->xdebug("parsing attribute:"); 00245 $this->appendDebug($this->varDump($attrs)); 00246 if (!isset($attrs['form'])) { 00247 // TODO: handle globals 00248 $attrs['form'] = $this->schemaInfo['attributeFormDefault']; 00249 } 00250 if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) { 00251 $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']; 00252 if (!strpos($v, ':')) { 00253 // no namespace in arrayType attribute value... 00254 if ($this->defaultNamespace[$pos]) { 00255 // ...so use the default 00256 $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'] = $this->defaultNamespace[$pos] . ':' . $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']; 00257 } 00258 } 00259 } 00260 if(isset($attrs['name'])){ 00261 $this->attributes[$attrs['name']] = $attrs; 00262 $aname = $attrs['name']; 00263 } elseif(isset($attrs['ref']) && $attrs['ref'] == 'http://schemas.xmlsoap.org/soap/encoding/:arrayType'){ 00264 if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) { 00265 $aname = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']; 00266 } else { 00267 $aname = ''; 00268 } 00269 } elseif(isset($attrs['ref'])){ 00270 $aname = $attrs['ref']; 00271 $this->attributes[$attrs['ref']] = $attrs; 00272 } 00273 00274 if($this->currentComplexType){ // This should *always* be 00275 $this->complexTypes[$this->currentComplexType]['attrs'][$aname] = $attrs; 00276 } 00277 // arrayType attribute 00278 if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']) || $this->getLocalPart($aname) == 'arrayType'){ 00279 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array'; 00280 $prefix = $this->getPrefix($aname); 00281 if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])){ 00282 $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']; 00283 } else { 00284 $v = ''; 00285 } 00286 if(strpos($v,'[,]')){ 00287 $this->complexTypes[$this->currentComplexType]['multidimensional'] = true; 00288 } 00289 $v = substr($v,0,strpos($v,'[')); // clip the [] 00290 if(!strpos($v,':') && isset($this->typemap[$this->XMLSchemaVersion][$v])){ 00291 $v = $this->XMLSchemaVersion.':'.$v; 00292 } 00293 $this->complexTypes[$this->currentComplexType]['arrayType'] = $v; 00294 } 00295 break; 00296 case 'complexContent': // (optional) content for a complexType 00297 $this->xdebug("do nothing for element $name"); 00298 break; 00299 case 'complexType': 00300 array_push($this->complexTypeStack, $this->currentComplexType); 00301 if(isset($attrs['name'])){ 00302 // TODO: what is the scope of named complexTypes that appear 00303 // nested within other c complexTypes? 00304 $this->xdebug('processing named complexType '.$attrs['name']); 00305 //$this->currentElement = false; 00306 $this->currentComplexType = $attrs['name']; 00307 $this->complexTypes[$this->currentComplexType] = $attrs; 00308 $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType'; 00309 // This is for constructs like 00310 // <complexType name="ListOfString" base="soap:Array"> 00311 // <sequence> 00312 // <element name="string" type="xsd:string" 00313 // minOccurs="0" maxOccurs="unbounded" /> 00314 // </sequence> 00315 // </complexType> 00316 if(isset($attrs['base']) && ereg(':Array$',$attrs['base'])){ 00317 $this->xdebug('complexType is unusual array'); 00318 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array'; 00319 } else { 00320 $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct'; 00321 } 00322 } else { 00323 $name = $this->CreateTypeName($this->currentElement); 00324 $this->xdebug('processing unnamed complexType for element ' . $this->currentElement . ' named ' . $name); 00325 $this->currentComplexType = $name; 00326 //$this->currentElement = false; 00327 $this->complexTypes[$this->currentComplexType] = $attrs; 00328 $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType'; 00329 // This is for constructs like 00330 // <complexType name="ListOfString" base="soap:Array"> 00331 // <sequence> 00332 // <element name="string" type="xsd:string" 00333 // minOccurs="0" maxOccurs="unbounded" /> 00334 // </sequence> 00335 // </complexType> 00336 if(isset($attrs['base']) && ereg(':Array$',$attrs['base'])){ 00337 $this->xdebug('complexType is unusual array'); 00338 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array'; 00339 } else { 00340 $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct'; 00341 } 00342 } 00343 break; 00344 case 'element': 00345 array_push($this->elementStack, $this->currentElement); 00346 if (!isset($attrs['form'])) { 00347 if ($this->currentComplexType) { 00348 $attrs['form'] = $this->schemaInfo['elementFormDefault']; 00349 } else { 00350 // global 00351 $attrs['form'] = 'qualified'; 00352 } 00353 } 00354 if(isset($attrs['type'])){ 00355 $this->xdebug("processing typed element ".$attrs['name']." of type ".$attrs['type']); 00356 if (! $this->getPrefix($attrs['type'])) { 00357 if ($this->defaultNamespace[$pos]) { 00358 $attrs['type'] = $this->defaultNamespace[$pos] . ':' . $attrs['type']; 00359 $this->xdebug('used default namespace to make type ' . $attrs['type']); 00360 } 00361 } 00362 // This is for constructs like 00363 // <complexType name="ListOfString" base="soap:Array"> 00364 // <sequence> 00365 // <element name="string" type="xsd:string" 00366 // minOccurs="0" maxOccurs="unbounded" /> 00367 // </sequence> 00368 // </complexType> 00369 if ($this->currentComplexType && $this->complexTypes[$this->currentComplexType]['phpType'] == 'array') { 00370 $this->xdebug('arrayType for unusual array is ' . $attrs['type']); 00371 $this->complexTypes[$this->currentComplexType]['arrayType'] = $attrs['type']; 00372 } 00373 $this->currentElement = $attrs['name']; 00374 $ename = $attrs['name']; 00375 } elseif(isset($attrs['ref'])){ 00376 $this->xdebug("processing element as ref to ".$attrs['ref']); 00377 $this->currentElement = "ref to ".$attrs['ref']; 00378 $ename = $this->getLocalPart($attrs['ref']); 00379 } else { 00380 $type = $this->CreateTypeName($this->currentComplexType . '_' . $attrs['name']); 00381 $this->xdebug("processing untyped element " . $attrs['name'] . ' type ' . $type); 00382 $this->currentElement = $attrs['name']; 00383 $attrs['type'] = $this->schemaTargetNamespace . ':' . $type; 00384 $ename = $attrs['name']; 00385 } 00386 if (isset($ename) && $this->currentComplexType) { 00387 $this->xdebug("add element $ename to complexType $this->currentComplexType"); 00388 $this->complexTypes[$this->currentComplexType]['elements'][$ename] = $attrs; 00389 } elseif (!isset($attrs['ref'])) { 00390 $this->xdebug("add element $ename to elements array"); 00391 $this->elements[ $attrs['name'] ] = $attrs; 00392 $this->elements[ $attrs['name'] ]['typeClass'] = 'element'; 00393 } 00394 break; 00395 case 'enumeration': // restriction value list member 00396 $this->xdebug('enumeration ' . $attrs['value']); 00397 if ($this->currentSimpleType) { 00398 $this->simpleTypes[$this->currentSimpleType]['enumeration'][] = $attrs['value']; 00399 } elseif ($this->currentComplexType) { 00400 $this->complexTypes[$this->currentComplexType]['enumeration'][] = $attrs['value']; 00401 } 00402 break; 00403 case 'extension': // simpleContent or complexContent type extension 00404 $this->xdebug('extension ' . $attrs['base']); 00405 if ($this->currentComplexType) { 00406 $ns = $this->getPrefix($attrs['base']); 00407 if ($ns == '') { 00408 $this->complexTypes[$this->currentComplexType]['extensionBase'] = $this->schemaTargetNamespace . ':' . $attrs['base']; 00409 } elseif ($this->getNamespaceFromPrefix($ns)) { 00410 $this->complexTypes[$this->currentComplexType]['extensionBase'] = $attrs['base']; 00411 } 00412 } 00413 break; 00414 case 'import': 00415 if (isset($attrs['schemaLocation'])) { 00416 $this->xdebug('import namespace ' . $attrs['namespace'] . ' from ' . $attrs['schemaLocation']); 00417 $this->imports[$attrs['namespace']][] = array('location' => $attrs['schemaLocation'], 'loaded' => false); 00418 } else { 00419 $this->xdebug('import namespace ' . $attrs['namespace']); 00420 $this->imports[$attrs['namespace']][] = array('location' => '', 'loaded' => true); 00421 if (! $this->getPrefixFromNamespace($attrs['namespace'])) { 00422 $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace']; 00423 } 00424 } 00425 break; 00426 case 'include': 00427 if (isset($attrs['schemaLocation'])) { 00428 $this->xdebug('include into namespace ' . $this->schemaTargetNamespace . ' from ' . $attrs['schemaLocation']); 00429 $this->imports[$this->schemaTargetNamespace][] = array('location' => $attrs['schemaLocation'], 'loaded' => false); 00430 } else { 00431 $this->xdebug('ignoring invalid XML Schema construct: include without schemaLocation attribute'); 00432 } 00433 break; 00434 case 'list': // simpleType value list 00435 $this->xdebug("do nothing for element $name"); 00436 break; 00437 case 'restriction': // simpleType, simpleContent or complexContent value restriction 00438 $this->xdebug('restriction ' . $attrs['base']); 00439 if($this->currentSimpleType){ 00440 $this->simpleTypes[$this->currentSimpleType]['type'] = $attrs['base']; 00441 } elseif($this->currentComplexType){ 00442 $this->complexTypes[$this->currentComplexType]['restrictionBase'] = $attrs['base']; 00443 if(strstr($attrs['base'],':') == ':Array'){ 00444 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array'; 00445 } 00446 } 00447 break; 00448 case 'schema': 00449 $this->schemaInfo = $attrs; 00450 $this->schemaInfo['schemaVersion'] = $this->getNamespaceFromPrefix($prefix); 00451 if (isset($attrs['targetNamespace'])) { 00452 $this->schemaTargetNamespace = $attrs['targetNamespace']; 00453 } 00454 if (!isset($attrs['elementFormDefault'])) { 00455 $this->schemaInfo['elementFormDefault'] = 'unqualified'; 00456 } 00457 if (!isset($attrs['attributeFormDefault'])) { 00458 $this->schemaInfo['attributeFormDefault'] = 'unqualified'; 00459 } 00460 break; 00461 case 'simpleContent': // (optional) content for a complexType 00462 $this->xdebug("do nothing for element $name"); 00463 break; 00464 case 'simpleType': 00465 array_push($this->simpleTypeStack, $this->currentSimpleType); 00466 if(isset($attrs['name'])){ 00467 $this->xdebug("processing simpleType for name " . $attrs['name']); 00468 $this->currentSimpleType = $attrs['name']; 00469 $this->simpleTypes[ $attrs['name'] ] = $attrs; 00470 $this->simpleTypes[ $attrs['name'] ]['typeClass'] = 'simpleType'; 00471 $this->simpleTypes[ $attrs['name'] ]['phpType'] = 'scalar'; 00472 } else { 00473 $name = $this->CreateTypeName($this->currentComplexType . '_' . $this->currentElement); 00474 $this->xdebug('processing unnamed simpleType for element ' . $this->currentElement . ' named ' . $name); 00475 $this->currentSimpleType = $name; 00476 //$this->currentElement = false; 00477 $this->simpleTypes[$this->currentSimpleType] = $attrs; 00478 $this->simpleTypes[$this->currentSimpleType]['phpType'] = 'scalar'; 00479 } 00480 break; 00481 case 'union': // simpleType type list 00482 $this->xdebug("do nothing for element $name"); 00483 break; 00484 default: 00485 $this->xdebug("do not have any logic to process element $name"); 00486 } 00487 } 00488 00496 function schemaEndElement($parser, $name) { 00497 // bring depth down a notch 00498 $this->depth--; 00499 // position of current element is equal to the last value left in depth_array for my depth 00500 if(isset($this->depth_array[$this->depth])){ 00501 $pos = $this->depth_array[$this->depth]; 00502 } 00503 // get element prefix 00504 if ($prefix = $this->getPrefix($name)){ 00505 // get unqualified name 00506 $name = $this->getLocalPart($name); 00507 } else { 00508 $prefix = ''; 00509 } 00510 // move on... 00511 if($name == 'complexType'){ 00512 $this->xdebug('done processing complexType ' . ($this->currentComplexType ? $this->currentComplexType : '(unknown)')); 00513 $this->currentComplexType = array_pop($this->complexTypeStack); 00514 //$this->currentElement = false; 00515 } 00516 if($name == 'element'){ 00517 $this->xdebug('done processing element ' . ($this->currentElement ? $this->currentElement : '(unknown)')); 00518 $this->currentElement = array_pop($this->elementStack); 00519 } 00520 if($name == 'simpleType'){ 00521 $this->xdebug('done processing simpleType ' . ($this->currentSimpleType ? $this->currentSimpleType : '(unknown)')); 00522 $this->currentSimpleType = array_pop($this->simpleTypeStack); 00523 } 00524 } 00525 00533 function schemaCharacterData($parser, $data){ 00534 $pos = $this->depth_array[$this->depth - 1]; 00535 $this->message[$pos]['cdata'] .= $data; 00536 } 00537 00543 function serializeSchema(){ 00544 00545 $schemaPrefix = $this->getPrefixFromNamespace($this->XMLSchemaVersion); 00546 $xml = ''; 00547 // imports 00548 if (sizeof($this->imports) > 0) { 00549 foreach($this->imports as $ns => $list) { 00550 foreach ($list as $ii) { 00551 if ($ii['location'] != '') { 00552 $xml .= " <$schemaPrefix:import location=\"" . $ii['location'] . '" namespace="' . $ns . "\" />\n"; 00553 } else { 00554 $xml .= " <$schemaPrefix:import namespace=\"" . $ns . "\" />\n"; 00555 } 00556 } 00557 } 00558 } 00559 // complex types 00560 foreach($this->complexTypes as $typeName => $attrs){ 00561 $contentStr = ''; 00562 // serialize child elements 00563 if(isset($attrs['elements']) && (count($attrs['elements']) > 0)){ 00564 foreach($attrs['elements'] as $element => $eParts){ 00565 if(isset($eParts['ref'])){ 00566 $contentStr .= " <$schemaPrefix:element ref=\"$element\"/>\n"; 00567 } else { 00568 $contentStr .= " <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "\""; 00569 foreach ($eParts as $aName => $aValue) { 00570 // handle, e.g., abstract, default, form, minOccurs, maxOccurs, nillable 00571 if ($aName != 'name' && $aName != 'type') { 00572 $contentStr .= " $aName=\"$aValue\""; 00573 } 00574 } 00575 $contentStr .= "/>\n"; 00576 } 00577 } 00578 // compositor wraps elements 00579 if (isset($attrs['compositor']) && ($attrs['compositor'] != '')) { 00580 $contentStr = " <$schemaPrefix:$attrs[compositor]>\n".$contentStr." </$schemaPrefix:$attrs[compositor]>\n"; 00581 } 00582 } 00583 // attributes 00584 if(isset($attrs['attrs']) && (count($attrs['attrs']) >= 1)){ 00585 foreach($attrs['attrs'] as $attr => $aParts){ 00586 $contentStr .= " <$schemaPrefix:attribute"; 00587 foreach ($aParts as $a => $v) { 00588 if ($a == 'ref' || $a == 'type') { 00589 $contentStr .= " $a=\"".$this->contractQName($v).'"'; 00590 } elseif ($a == 'http://schemas.xmlsoap.org/wsdl/:arrayType') { 00591 $this->usedNamespaces['wsdl'] = $this->namespaces['wsdl']; 00592 $contentStr .= ' wsdl:arrayType="'.$this->contractQName($v).'"'; 00593 } else { 00594 $contentStr .= " $a=\"$v\""; 00595 } 00596 } 00597 $contentStr .= "/>\n"; 00598 } 00599 } 00600 // if restriction 00601 if (isset($attrs['restrictionBase']) && $attrs['restrictionBase'] != ''){ 00602 $contentStr = " <$schemaPrefix:restriction base=\"".$this->contractQName($attrs['restrictionBase'])."\">\n".$contentStr." </$schemaPrefix:restriction>\n"; 00603 // complex or simple content 00604 if ((isset($attrs['elements']) && count($attrs['elements']) > 0) || (isset($attrs['attrs']) && count($attrs['attrs']) > 0)){ 00605 $contentStr = " <$schemaPrefix:complexContent>\n".$contentStr." </$schemaPrefix:complexContent>\n"; 00606 } 00607 } 00608 // finalize complex type 00609 if($contentStr != ''){ 00610 $contentStr = " <$schemaPrefix:complexType name=\"$typeName\">\n".$contentStr." </$schemaPrefix:complexType>\n"; 00611 } else { 00612 $contentStr = " <$schemaPrefix:complexType name=\"$typeName\"/>\n"; 00613 } 00614 $xml .= $contentStr; 00615 } 00616 // simple types 00617 if(isset($this->simpleTypes) && count($this->simpleTypes) > 0){ 00618 foreach($this->simpleTypes as $typeName => $eParts){ 00619 $xml .= " <$schemaPrefix:simpleType name=\"$typeName\">\n <$schemaPrefix:restriction base=\"".$this->contractQName($eParts['type'])."\">\n"; 00620 if (isset($eParts['enumeration'])) { 00621 foreach ($eParts['enumeration'] as $e) { 00622 $xml .= " <$schemaPrefix:enumeration value=\"$e\"/>\n"; 00623 } 00624 } 00625 $xml .= " </$schemaPrefix:restriction>\n </$schemaPrefix:simpleType>"; 00626 } 00627 } 00628 // elements 00629 if(isset($this->elements) && count($this->elements) > 0){ 00630 foreach($this->elements as $element => $eParts){ 00631 $xml .= " <$schemaPrefix:element name=\"$element\" type=\"".$this->contractQName($eParts['type'])."\"/>\n"; 00632 } 00633 } 00634 // attributes 00635 if(isset($this->attributes) && count($this->attributes) > 0){ 00636 foreach($this->attributes as $attr => $aParts){ 00637 $xml .= " <$schemaPrefix:attribute name=\"$attr\" type=\"".$this->contractQName($aParts['type'])."\"\n/>"; 00638 } 00639 } 00640 // finish 'er up 00641 $attr = ''; 00642 foreach ($this->schemaInfo as $k => $v) { 00643 if ($k == 'elementFormDefault' || $k == 'attributeFormDefault') { 00644 $attr .= " $k=\"$v\""; 00645 } 00646 } 00647 $el = "<$schemaPrefix:schema$attr targetNamespace=\"$this->schemaTargetNamespace\"\n"; 00648 foreach (array_diff($this->usedNamespaces, $this->enclosingNamespaces) as $nsp => $ns) { 00649 $el .= " xmlns:$nsp=\"$ns\""; 00650 } 00651 $xml = $el . ">\n".$xml."</$schemaPrefix:schema>\n"; 00652 return $xml; 00653 } 00654 00661 function xdebug($string){ 00662 $this->debug('<' . $this->schemaTargetNamespace . '> '.$string); 00663 } 00664 00677 function getPHPType($type,$ns){ 00678 if(isset($this->typemap[$ns][$type])){ 00679 //print "found type '$type' and ns $ns in typemap<br>"; 00680 return $this->typemap[$ns][$type]; 00681 } elseif(isset($this->complexTypes[$type])){ 00682 //print "getting type '$type' and ns $ns from complexTypes array<br>"; 00683 return $this->complexTypes[$type]['phpType']; 00684 } 00685 return false; 00686 } 00687 00710 function getTypeDef($type){ 00711 //$this->debug("in getTypeDef for type $type"); 00712 if (substr($type, -1) == '^') { 00713 $is_element = 1; 00714 $type = substr($type, 0, -1); 00715 } else { 00716 $is_element = 0; 00717 } 00718 00719 if((! $is_element) && isset($this->complexTypes[$type])){ 00720 $this->xdebug("in getTypeDef, found complexType $type"); 00721 return $this->complexTypes[$type]; 00722 } elseif((! $is_element) && isset($this->simpleTypes[$type])){ 00723 $this->xdebug("in getTypeDef, found simpleType $type"); 00724 if (!isset($this->simpleTypes[$type]['phpType'])) { 00725 // get info for type to tack onto the simple type 00726 // TODO: can this ever really apply (i.e. what is a simpleType really?) 00727 $uqType = substr($this->simpleTypes[$type]['type'], strrpos($this->simpleTypes[$type]['type'], ':') + 1); 00728 $ns = substr($this->simpleTypes[$type]['type'], 0, strrpos($this->simpleTypes[$type]['type'], ':')); 00729 $etype = $this->getTypeDef($uqType); 00730 if ($etype) { 00731 $this->xdebug("in getTypeDef, found type for simpleType $type:"); 00732 $this->xdebug($this->varDump($etype)); 00733 if (isset($etype['phpType'])) { 00734 $this->simpleTypes[$type]['phpType'] = $etype['phpType']; 00735 } 00736 if (isset($etype['elements'])) { 00737 $this->simpleTypes[$type]['elements'] = $etype['elements']; 00738 } 00739 } 00740 } 00741 return $this->simpleTypes[$type]; 00742 } elseif(isset($this->elements[$type])){ 00743 $this->xdebug("in getTypeDef, found element $type"); 00744 if (!isset($this->elements[$type]['phpType'])) { 00745 // get info for type to tack onto the element 00746 $uqType = substr($this->elements[$type]['type'], strrpos($this->elements[$type]['type'], ':') + 1); 00747 $ns = substr($this->elements[$type]['type'], 0, strrpos($this->elements[$type]['type'], ':')); 00748 $etype = $this->getTypeDef($uqType); 00749 if ($etype) { 00750 $this->xdebug("in getTypeDef, found type for element $type:"); 00751 $this->xdebug($this->varDump($etype)); 00752 if (isset($etype['phpType'])) { 00753 $this->elements[$type]['phpType'] = $etype['phpType']; 00754 } 00755 if (isset($etype['elements'])) { 00756 $this->elements[$type]['elements'] = $etype['elements']; 00757 } 00758 if (isset($etype['extensionBase'])) { 00759 $this->elements[$type]['extensionBase'] = $etype['extensionBase']; 00760 } 00761 } elseif ($ns == 'http://www.w3.org/2001/XMLSchema') { 00762 $this->xdebug("in getTypeDef, element $type is an XSD type"); 00763 $this->elements[$type]['phpType'] = 'scalar'; 00764 } 00765 } 00766 return $this->elements[$type]; 00767 } elseif(isset($this->attributes[$type])){ 00768 $this->xdebug("in getTypeDef, found attribute $type"); 00769 return $this->attributes[$type]; 00770 } elseif (ereg('_ContainedType$', $type)) { 00771 $this->xdebug("in getTypeDef, have an untyped element $type"); 00772 $typeDef['typeClass'] = 'simpleType'; 00773 $typeDef['phpType'] = 'scalar'; 00774 $typeDef['type'] = 'http://www.w3.org/2001/XMLSchema:string'; 00775 return $typeDef; 00776 } 00777 $this->xdebug("in getTypeDef, did not find $type"); 00778 return false; 00779 } 00780 00789 function serializeTypeDef($type){ 00790 //print "in sTD() for type $type<br>"; 00791 if($typeDef = $this->getTypeDef($type)){ 00792 $str .= '<'.$type; 00793 if(is_array($typeDef['attrs'])){ 00794 foreach($typeDef['attrs'] as $attName => $data){ 00795 $str .= " $attName=\"{type = ".$data['type']."}\""; 00796 } 00797 } 00798 $str .= " xmlns=\"".$this->schema['targetNamespace']."\""; 00799 if(count($typeDef['elements']) > 0){ 00800 $str .= ">"; 00801 foreach($typeDef['elements'] as $element => $eData){ 00802 $str .= $this->serializeTypeDef($element); 00803 } 00804 $str .= "</$type>"; 00805 } elseif($typeDef['typeClass'] == 'element') { 00806 $str .= "></$type>"; 00807 } else { 00808 $str .= "/>"; 00809 } 00810 return $str; 00811 } 00812 return false; 00813 } 00814 00825 function typeToForm($name,$type){ 00826 // get typedef 00827 if($typeDef = $this->getTypeDef($type)){ 00828 // if struct 00829 if($typeDef['phpType'] == 'struct'){ 00830 $buffer .= '<table>'; 00831 foreach($typeDef['elements'] as $child => $childDef){ 00832 $buffer .= " 00833 <tr><td align='right'>$childDef[name] (type: ".$this->getLocalPart($childDef['type'])."):</td> 00834 <td><input type='text' name='parameters[".$name."][$childDef[name]]'></td></tr>"; 00835 } 00836 $buffer .= '</table>'; 00837 // if array 00838 } elseif($typeDef['phpType'] == 'array'){ 00839 $buffer .= '<table>'; 00840 for($i=0;$i < 3; $i++){ 00841 $buffer .= " 00842 <tr><td align='right'>array item (type: $typeDef[arrayType]):</td> 00843 <td><input type='text' name='parameters[".$name."][]'></td></tr>"; 00844 } 00845 $buffer .= '</table>'; 00846 // if scalar 00847 } else { 00848 $buffer .= "<input type='text' name='parameters[$name]'>"; 00849 } 00850 } else { 00851 $buffer .= "<input type='text' name='parameters[$name]'>"; 00852 } 00853 return $buffer; 00854 } 00855 00897 function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType=''){ 00898 $this->complexTypes[$name] = array( 00899 'name' => $name, 00900 'typeClass' => $typeClass, 00901 'phpType' => $phpType, 00902 'compositor'=> $compositor, 00903 'restrictionBase' => $restrictionBase, 00904 'elements' => $elements, 00905 'attrs' => $attrs, 00906 'arrayType' => $arrayType 00907 ); 00908 00909 $this->xdebug("addComplexType $name:"); 00910 $this->appendDebug($this->varDump($this->complexTypes[$name])); 00911 } 00912 00925 function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) { 00926 $this->simpleTypes[$name] = array( 00927 'name' => $name, 00928 'typeClass' => $typeClass, 00929 'phpType' => $phpType, 00930 'type' => $restrictionBase, 00931 'enumeration' => $enumeration 00932 ); 00933 00934 $this->xdebug("addSimpleType $name:"); 00935 $this->appendDebug($this->varDump($this->simpleTypes[$name])); 00936 } 00937 00945 function addElement($attrs) { 00946 if (! $this->getPrefix($attrs['type'])) { 00947 $attrs['type'] = $this->schemaTargetNamespace . ':' . $attrs['type']; 00948 } 00949 $this->elements[ $attrs['name'] ] = $attrs; 00950 $this->elements[ $attrs['name'] ]['typeClass'] = 'element'; 00951 00952 $this->xdebug("addElement " . $attrs['name']); 00953 $this->appendDebug($this->varDump($this->elements[ $attrs['name'] ])); 00954 } 00955 } 00956 00960 class XMLSchema extends nusoap_xmlschema { 00961 } 00962 00963 00964 ?>
Copyright © 2003 - 2009 MyOOS [Shopsystem]. All rights reserved. MyOOS [Shopsystem] is Free Software released under the GNU/GPL License. Webmaster: info@r23.de (Impressum) |
|