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