/src/com/mikebevz/xsd2php/Xsd2Php.php

http://github.com/moyarada/XSD-to-PHP · PHP · 797 lines · 467 code · 98 blank · 232 comment · 126 complexity · 84acb53c11619be80b4ba9eea8937e8e MD5 · raw file

  1. <?php
  2. namespace com\mikebevz\xsd2php;
  3. /**
  4. * Copyright 2010 Mike Bevz <myb@mikebevz.com>
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the "License");
  7. * you may not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. require_once dirname(__FILE__).'/PHPClass.php';
  19. //require_once dirname(__FILE__).'/Common.php';
  20. /**
  21. * Generate PHP classes based on XSD schema
  22. *
  23. * @author Mike Bevz <myb@mikebevz.com>
  24. * @version 0.0.1
  25. *
  26. */
  27. class Xsd2Php extends Common
  28. {
  29. /**
  30. * XSD schema to convert from
  31. * @var String
  32. */
  33. private $xsdFile;
  34. /**
  35. *
  36. * @var DOMXPath
  37. */
  38. private $xpath;
  39. /**
  40. * Namespaces in the current xsd schema
  41. * @var array
  42. */
  43. private $nspace;
  44. /**
  45. * XML file suitable for PHP code generation
  46. * @var string
  47. */
  48. private $xmlForPhp;
  49. /**
  50. * Show debug info
  51. * @var boolean
  52. */
  53. public $debug = true;
  54. /**
  55. * Namespaces = array (className => namespace ), used in dirs/files generation
  56. * @var array
  57. */
  58. //private $namespaces;
  59. /**
  60. * Short namespaces
  61. *
  62. * @var array
  63. */
  64. private $shortNamespaces;
  65. /**
  66. * XML Source
  67. *
  68. * @var string
  69. */
  70. private $xmlSource;
  71. /**
  72. * Target namespace
  73. *
  74. * @var string
  75. */
  76. private $targetNamespace;
  77. /**
  78. * XSD root namespace alias (fx, xsd = http://www.w3.org/2001/XMLSchema)
  79. *
  80. * @var string
  81. */
  82. private $xsdNs;
  83. /**
  84. * Already processed imports
  85. *
  86. * @var array
  87. */
  88. private $loadedImportFiles = array();
  89. /**
  90. * Processed namespaces
  91. *
  92. * @var array
  93. */
  94. private $importHeadNS = array();
  95. /**
  96. * Map of already generated paths for a XML namespace
  97. * @var array
  98. */
  99. private $namespaceToPath = array();
  100. /**
  101. * Map of already generated PHP namespaces for an XML namespace
  102. * @var array
  103. */
  104. private $namespaceToPhp = array();
  105. /**
  106. * XML Schema converted to XML
  107. *
  108. * @return string $xmlSource
  109. */
  110. public function getXmlSource()
  111. {
  112. return $this->xmlSource;
  113. }
  114. /**
  115. * Set XML representation of the XML Schema
  116. *
  117. * @param string $xmlSource XML Source
  118. *
  119. * @return void
  120. */
  121. public function setXmlSource($xmlSource)
  122. {
  123. $this->xmlSource = $xmlSource;
  124. }
  125. /**
  126. *
  127. *
  128. * @param string $xsdFile Xsd file to convert
  129. * @param boolean $debug Show debug messages[optional, default = false]
  130. *
  131. * @return void
  132. */
  133. public function __construct($xsdFile, $debug = false)
  134. {
  135. if ($debug != false) {
  136. $this->debug = $debug;
  137. }
  138. $this->xsdFile = $xsdFile;
  139. $this->dom = new \DOMDocument();
  140. $this->dom->load($this->xsdFile,
  141. LIBXML_DTDLOAD |
  142. LIBXML_DTDATTR |
  143. LIBXML_NOENT |
  144. LIBXML_XINCLUDE);
  145. $this->xpath = new \DOMXPath($this->dom);
  146. $this->targetNamespace = $this->getTargetNS($this->xpath);
  147. $this->shortNamespaces = $this->getNamespaces($this->xpath);
  148. $this->dom = $xsd = $this->loadIncludes($this->dom, dirname($this->xsdFile), $this->targetNamespace);
  149. $this->dom = $this->loadImports($this->dom, $this->xsdFile);
  150. if ($this->debug) print_r($this->shortNamespaces);
  151. }
  152. /**
  153. * Return target namespace for given DOMXPath object
  154. *
  155. * @param DOMXPath $xpath DOMXPath Object
  156. *
  157. * @return string
  158. */
  159. private function getTargetNS($xpath) {
  160. $query = "//*[local-name()='schema' and namespace-uri()='http://www.w3.org/2001/XMLSchema']/@targetNamespace";
  161. $targetNs = $xpath->query($query);
  162. if ($targetNs) {
  163. foreach ($targetNs as $entry) {
  164. return $entry->nodeValue;
  165. }
  166. }
  167. }
  168. /**
  169. * Return array of namespaces of the document
  170. *
  171. * @param DOMXPath $xpath
  172. *
  173. * @return array
  174. */
  175. public function getNamespaces($xpath) {
  176. $query = "//namespace::*";
  177. $entries = $xpath->query($query);
  178. $nspaces = array();
  179. foreach ($entries as $entry) {
  180. if ($entry->nodeValue == "http://www.w3.org/2001/XMLSchema") {
  181. $this->xsdNs = preg_replace('/xmlns:(.*)/', "$1", $entry->nodeName);
  182. }
  183. if (//$entry->nodeName != $this->xsdNs
  184. //&&
  185. $entry->nodeName != 'xmlns:xml') {
  186. if (preg_match('/:/', $entry->nodeName)) {
  187. $nodeName = explode(':', $entry->nodeName);
  188. $nspaces[$nodeName[1]] = $entry->nodeValue;
  189. } else {
  190. $nspaces[$entry->nodeName] = $entry->nodeValue;
  191. }
  192. }
  193. }
  194. return $nspaces;
  195. }
  196. /**
  197. * Save generated classes to directory
  198. *
  199. * @param string $dir Directory to save classes to
  200. * @param boolean $createDirectory [optional] Create directory, false by default
  201. *
  202. * @return void
  203. */
  204. public function saveClasses($dir, $createDirectory = false) {
  205. $this->setXmlSource($this->getXML()->saveXML());
  206. $this->savePhpFiles($dir, $createDirectory);
  207. }
  208. /**
  209. * Load imports
  210. *
  211. * @param DOMDocument $dom DOM model of the schema
  212. * @param string $xsdFile Full path to first XSD Schema
  213. *
  214. * @return void
  215. */
  216. public function loadImports($dom, $xsdFile = '') {
  217. $xpath = new \DOMXPath($dom);
  218. $query = "//*[local-name()='import' and namespace-uri()='http://www.w3.org/2001/XMLSchema']";
  219. $entries = $xpath->query($query);
  220. if ($entries->length == 0) {
  221. return $dom;
  222. }
  223. foreach ($entries as $entry) {
  224. // load XSD file
  225. $namespace = $entry->getAttribute('namespace');
  226. $parent = $entry->parentNode;
  227. $xsd = new \DOMDocument();
  228. $xsdFileName = realpath(dirname($xsdFile).DIRECTORY_SEPARATOR.$entry->getAttribute("schemaLocation"));
  229. if ($this->debug) print('Importing '.$xsdFileName."\n");
  230. if (!file_exists($xsdFileName)) {
  231. if ($this->debug) print $xsdFileName. " is not found \n";
  232. continue;
  233. }
  234. if (in_array($xsdFileName, $this->loadedImportFiles)) {
  235. if ($this->debug) print("Schema ".$xsdFileName." has been already imported");
  236. $parent->removeChild($entry);
  237. continue;
  238. }
  239. $filepath = dirname($xsdFileName);
  240. $result = $xsd->load($xsdFileName,
  241. LIBXML_DTDLOAD|LIBXML_DTDATTR|LIBXML_NOENT|LIBXML_XINCLUDE);
  242. if ($result) {
  243. $mxpath = new \DOMXPath($xsd);
  244. $this->shortNamespaces = array_merge($this->shortNamespaces, $this->getNamespaces($mxpath));
  245. $xsd = $this->loadIncludes($xsd, $filepath, $namespace);
  246. $this->loadedImportFiles[] = $xsdFileName;
  247. $this->loadedImportFiles = array_unique($this->loadedImportFiles);
  248. }
  249. foreach ($xsd->documentElement->childNodes as $node) {
  250. if ($node->nodeName == $this->xsdNs.":import") {
  251. // Do not change Namespace for import and include tags
  252. //if ($this->debug) print("Insert Import ".$node->nodeName." NS=". $node->getAttribute('namespace'). "\n");
  253. $loc = realpath($filepath.DIRECTORY_SEPARATOR.$node->getAttribute('schemaLocation'));
  254. $node->setAttribute('schemaLocation', $loc);
  255. if ($this->debug) print('Change imported schema location to '.$loc." \n");
  256. $newNode = $dom->importNode($node, true);
  257. $parent->insertBefore($newNode, $entry);
  258. continue;
  259. } else {
  260. //if ($this->debug) print($node->nodeName." \n". $namespace. "\n");
  261. $newNodeNs = $xsd->createAttribute("namespace");
  262. $textEl = $xsd->createTextNode($namespace);
  263. $newNodeNs->appendChild($textEl);
  264. $node->appendChild($newNodeNs);
  265. $newNode = $dom->importNode($node, true);
  266. $parent->insertBefore($newNode, $entry);
  267. }
  268. }
  269. // add to $dom
  270. $parent->removeChild($entry);
  271. }
  272. $xpath = new \DOMXPath($dom);
  273. $query = "//*[local-name()='import' and namespace-uri()='http://www.w3.org/2001/XMLSchema']";
  274. $imports = $xpath->query($query);
  275. if ($imports->length != 0) {
  276. $dom = $this->loadImports($dom);
  277. }
  278. if ($this->debug) print_r("\n------------------------------------\n");
  279. return $dom;
  280. }
  281. /**
  282. * Load includes in XML Schema
  283. *
  284. * @param DOMDocument $dom Instance of DOMDocument
  285. * @param string $filepath
  286. * @param string $namespace
  287. *
  288. * @return void
  289. */
  290. public function loadIncludes($dom, $filepath = '', $namespace = '') {
  291. $xpath = new \DOMXPath($dom);
  292. $query = "//*[local-name()='include' and namespace-uri()='http://www.w3.org/2001/XMLSchema']";
  293. $includes = $xpath->query($query);
  294. foreach ($includes as $entry) {
  295. $parent = $entry->parentNode;
  296. $xsd = new \DOMDocument();
  297. $xsdFileName = realpath($filepath.DIRECTORY_SEPARATOR.$entry->getAttribute("schemaLocation"));
  298. if ($this->debug) print('Including '.$xsdFileName."\n");
  299. if (!file_exists($xsdFileName)) {
  300. if ($this->debug) print $xsdFileName. " is not found \n";
  301. continue;
  302. }
  303. $result = $xsd->load($xsdFileName,
  304. LIBXML_DTDLOAD|LIBXML_DTDATTR|LIBXML_NOENT|LIBXML_XINCLUDE);
  305. if ($result) {
  306. $mxpath = new \DOMXPath($xsd);
  307. $this->shortNamespaces = array_merge($this->shortNamespaces, $this->getNamespaces($mxpath));
  308. }
  309. foreach ($xsd->documentElement->childNodes as $node) {
  310. if ($node->nodeName == $this->xsdNs.":include") {
  311. $loc = realpath($filepath.DIRECTORY_SEPARATOR.$node->getAttribute('schemaLocation'));
  312. $node->setAttribute('schemaLocation', $loc);
  313. if ($this->debug) print('Change included schema location to '.$loc." \n");
  314. $newNode = $dom->importNode($node, true);
  315. $parent->insertBefore($newNode, $entry);
  316. } else {
  317. if ($namespace != '') {
  318. $newNodeNs = $xsd->createAttribute("namespace");
  319. $textEl = $xsd->createTextNode($namespace);
  320. $newNodeNs->appendChild($textEl);
  321. $node->appendChild($newNodeNs);
  322. }
  323. $newNode = $dom->importNode($node, true);
  324. $parent->insertBefore($newNode, $entry);
  325. }
  326. }
  327. $parent->removeChild($entry);
  328. }
  329. /* $xpath = new \DOMXPath($dom);
  330. $query = "//*[local-name()='include' and namespace-uri()='http://www.w3.org/2001/XMLSchema']";
  331. $includes = $xpath->query($query);
  332. if ($includes->length != 0) {
  333. $dom = $this->loadIncludes($dom);
  334. } */
  335. if ($this->debug) print_r("\n------------------------------------\n");
  336. return $dom;
  337. }
  338. /**
  339. * Convert XSD to XML suitable for PHP code generation
  340. *
  341. * @return string
  342. */
  343. public function getXmlForPhp()
  344. {
  345. return $this->xmlForPhp;
  346. }
  347. /**
  348. * @param string $xmlForPhp XML
  349. *
  350. * @return void
  351. */
  352. public function setXmlForPhp($xmlForPhp)
  353. {
  354. $this->xmlForPhp = $xmlForPhp;
  355. }
  356. /**
  357. * Convert XSD to XML suitable for further processing
  358. *
  359. * @return string XML string
  360. *
  361. * @return DOMDocument
  362. */
  363. public function getXML()
  364. {
  365. try {
  366. $xsl = new \XSLTProcessor();
  367. $xslDom = new \DOMDocument();
  368. $xslDom->load(dirname(__FILE__) . "/xsd2php2.xsl");
  369. $xsl->registerPHPFunctions();
  370. $xsl->importStyleSheet($xslDom);
  371. $dom = $xsl->transformToDoc($this->dom);
  372. $dom->formatOutput = true;
  373. return $dom;
  374. } catch (\Exception $e) {
  375. throw new \Exception(
  376. "Error interpreting XSD document (".$e->getMessage().")");
  377. }
  378. }
  379. /**
  380. * Save PHP files to directory structure
  381. *
  382. * @param string $dir Directory to save files to
  383. * @param boolean $createDirectory Create $dir directory if it doesn't exist
  384. *
  385. * @throws RuntimeException if given directory does not exist
  386. *
  387. * @return void
  388. */
  389. private function savePhpFiles($dir, $createDirectory = false) {
  390. if (!file_exists($dir) && $createDirectory === false) {
  391. throw new \RuntimeException($dir." does not exist");
  392. }
  393. if (!file_exists($dir) && $createDirectory === true) {
  394. //@todo Implement Recursive mkdir
  395. mkdir($dir, 0777, true);
  396. }
  397. $classes = $this->getPHP();
  398. foreach ($classes as $fullkey => $value) {
  399. $keys = explode("|", $fullkey);
  400. $key = $keys[0];
  401. $namespace = $this->namespaceToPath($keys[1]);
  402. $targetDir = $dir.DIRECTORY_SEPARATOR.$namespace;
  403. if (!file_exists($targetDir)) {
  404. mkdir($targetDir, 0777, true);
  405. }
  406. file_put_contents($targetDir.DIRECTORY_SEPARATOR.$key.'.php', $value);
  407. }
  408. if ($this->debug) echo "Generated classes saved to ".$dir;
  409. }
  410. /**
  411. * Return generated PHP source code. That's where we generate bindings code
  412. *
  413. * @return string
  414. */
  415. private function getPHP() {
  416. $phpfile = $this->getXmlForPhp();
  417. if ($phpfile == '' && $this->getXmlSource() == '') {
  418. throw new \RuntimeException('There is no XML generated');
  419. }
  420. $dom = new \DOMDocument();
  421. //print_r($this->getXmlSource());
  422. if ($this->getXmlSource() != '') {
  423. $dom->loadXML($this->getXmlSource(), LIBXML_DTDLOAD | LIBXML_DTDATTR |
  424. LIBXML_NOENT | LIBXML_XINCLUDE);
  425. } else {
  426. $dom->load($phpfile, LIBXML_DTDLOAD | LIBXML_DTDATTR |
  427. LIBXML_NOENT | LIBXML_XINCLUDE);
  428. }
  429. $xPath = new \DOMXPath($dom);
  430. $classes = $xPath->query('//classes/class');
  431. $sourceCode = array();
  432. foreach ($classes as $class) {
  433. $phpClass = new PHPClass();
  434. $phpClass->name = $class->getAttribute('name');
  435. if ($class->getAttribute('type') != '') {
  436. $phpClass->type = $class->getAttribute('type');
  437. }
  438. if ($class->getAttribute('simpleType') != '') {
  439. $phpClass->type = $class->getAttribute('simpleType');
  440. }
  441. if ($class->getAttribute('namespace') != '') {
  442. $phpClass->namespace = $class->getAttribute('namespace');
  443. }
  444. if ($class->getElementsByTagName('extends')->length > 0) {
  445. $rawType = $type = $class->getElementsByTagName('extends')->item(0)->getAttribute('name');
  446. $extendsNamespace = $this->namespaceToPhp($class->getElementsByTagName('extends')->item(0)->getAttribute('namespace'));
  447. $colonPos = strpos($type, ':');
  448. if (empty($extendsNamespace) && $colonPos !== false)
  449. {
  450. $ns = substr($type, 0, $colonPos);
  451. if (!empty($this->shortNamespaces[$ns]) && $this->shortNamespaces[$ns] == 'http://www.w3.org/2001/XMLSchema')
  452. {
  453. $type = substr ($type, $colonPos + 1);
  454. if (empty($phpClass->type))
  455. $phpClass->type = $type;
  456. }
  457. }
  458. if (!in_array($type, $this->basicTypes)) {
  459. $phpClass->extends = $type;
  460. $phpClass->type = $rawType;
  461. $phpClass->extendsNamespace = $extendsNamespace;
  462. }
  463. }
  464. $docs = $xPath->query('docs/doc', $class);
  465. $docBlock = array();
  466. //if ($phpClass->namespace != $this->xsdNs) {
  467. $docBlock['xmlNamespace'] = $this->expandNS($phpClass->namespace);
  468. //}
  469. $docBlock['xmlType'] = $phpClass->type;
  470. $docBlock['xmlName'] = $phpClass->name;
  471. if ($phpClass->namespace != '') {
  472. $docBlock['var'] = $this->namespaceToPhp($this->expandNS($phpClass->namespace))."\\".$phpClass->name;
  473. } else {
  474. $docBlock['var'] = $phpClass->name;
  475. }
  476. foreach ($docs as $doc) {
  477. if ($doc->nodeValue != '') {
  478. $docBlock["xml".$doc->getAttribute('name')] = $doc->nodeValue;
  479. } elseif ($doc->getAttribute('value') != '') {
  480. $docBlock["xml".$doc->getAttribute('name')] = $doc->getAttribute('value');
  481. }
  482. }
  483. $phpClass->classDocBlock = $docBlock;
  484. $props = $xPath->query('property', $class);
  485. $properties = array();
  486. $i = 0;
  487. $isArray = false;
  488. foreach($props as $prop) {
  489. $properties[$i]['name'] = $prop->getAttribute('name');
  490. $docs = $xPath->query('docs/doc', $prop);
  491. foreach ($docs as $doc) {
  492. $properties[$i]["docs"][$doc->getAttribute('name')] = $doc->nodeValue;
  493. }
  494. if ($prop->getAttribute('xmlType') != '') {
  495. $properties[$i]["docs"]['xmlType'] = $prop->getAttribute('xmlType');
  496. }
  497. if ($prop->getAttribute('namespace') != '') {
  498. $properties[$i]["docs"]['xmlNamespace'] = $this->expandNS($prop->getAttribute('namespace'));
  499. }
  500. if ($prop->getAttribute('minOccurs') != '') {
  501. $properties[$i]["docs"]['xmlMinOccurs'] = $prop->getAttribute('minOccurs');
  502. }
  503. if ($prop->getAttribute('maxOccurs') != '') {
  504. $properties[$i]["docs"]['xmlMaxOccurs'] = $prop->getAttribute('maxOccurs');
  505. // If maxOccurs > 1, mark type as an array
  506. if ($prop->getAttribute('maxOccurs') > 1) {
  507. $isArray = $prop->getAttribute('maxOccurs');
  508. } elseif($prop->getAttribute('maxOccurs')=='unbounded') {
  509. $isArray = true;
  510. }
  511. }
  512. if ($prop->getAttribute('name') != '') {
  513. $properties[$i]["docs"]['xmlName'] = $prop->getAttribute('name');
  514. }
  515. //@todo if $prop->getAttribute('maxOccurs') > 1 - var can be an array - in future special accessor cane be implemented
  516. if ($prop->getAttribute('type') != '' && $prop->getAttribute('typeNamespace') == '') {
  517. /**
  518. * In general it's stange to give to Type name's namespace. Reconsider this part
  519. */
  520. if ($prop->getAttribute('namespace') != '' && $prop->getAttribute('namespace') != $this->xsdNs) {
  521. $ns = "";
  522. if ($prop->getAttribute('namespace') == "#default#") {
  523. $ns = $this->namespaceToPhp($this->targetNamespace);
  524. } else {
  525. $ns = $this->namespaceToPhp($this->expandNS($prop->getAttribute('namespace')));
  526. }
  527. $properties[$i]["docs"]['var'] = $ns.'\\'.$prop->getAttribute('type');
  528. } else {
  529. $properties[$i]["docs"]['var'] = $prop->getAttribute('type');
  530. }
  531. // Is it unbounded array?
  532. if ($isArray === true) {
  533. $properties[$i]["docs"]['var'] = $properties[$i]["docs"]['var']."[]";
  534. $isArray = false;
  535. }
  536. // Is it array with defined maximum amount of elements?
  537. if ($isArray > 1) {
  538. $properties[$i]["docs"]['var'] = $properties[$i]["docs"]['var']."[".$isArray."]";
  539. $isArray = false;
  540. }
  541. }
  542. if ($prop->getAttribute('type') != '' && $prop->getAttribute('typeNamespace') != '') {
  543. $ns = "";
  544. if ($prop->getAttribute('typeNamespace') == "#default#") {
  545. $ns = $this->namespaceToPhp($this->targetNamespace);
  546. } else {
  547. $ns = $this->namespaceToPhp($this->expandNS($prop->getAttribute('typeNamespace')));
  548. }
  549. if ($prop->getAttribute('typeNamespace') == $this->xsdNs) {
  550. $properties[$i]["docs"]['var'] = $this->normalizeType($prop->getAttribute('type'));
  551. } else {
  552. $properties[$i]["docs"]['var'] = $ns.'\\'.$prop->getAttribute('type');
  553. }
  554. }
  555. $i++;
  556. }
  557. $phpClass->classProperties = $properties;
  558. $namespaceClause = '';
  559. if ($docBlock['xmlNamespace'] != '') {
  560. $namespaceClause = "namespace ".$this->namespaceToPhp($docBlock['xmlNamespace']).";\n";
  561. }
  562. $sourceCode[$docBlock['xmlName']."|".$phpClass->namespace] = "<?php\n".
  563. $namespaceClause.
  564. $phpClass->getPhpCode();
  565. }
  566. return $sourceCode;
  567. }
  568. /**
  569. * Resolve short namespace
  570. * @param string $ns Short namespace
  571. *
  572. * @return string
  573. */
  574. private function expandNS($ns) {
  575. if ($ns == "#default#") {
  576. $ns = $this->targetNamespace;
  577. }
  578. foreach($this->shortNamespaces as $shortNs => $longNs) {
  579. if ($ns == $shortNs) {
  580. $ns = $longNs;
  581. }
  582. }
  583. return $ns;
  584. }
  585. /**
  586. * Convert XML URI to PHP complient namespace
  587. *
  588. * @param string $xmlNS XML URI
  589. *
  590. * @return string
  591. */
  592. public function namespaceToPhp($xmlNS) {
  593. if (!empty($this->namespaceToPhp[$xmlNS]))
  594. return ($this->namespaceToPhp[$xmlNS]);
  595. $ns = $xmlNS;
  596. $ns = $this->expandNS($ns);
  597. if (preg_match('/urn:/',$ns)) {
  598. //@todo check if there are any components of namespace which are
  599. $ns = preg_replace('/-/', '_',$ns);
  600. $ns = preg_replace('/urn:/', '', $ns);
  601. $ns = preg_replace('/:/','\\', $ns);
  602. }
  603. /**
  604. if (preg_match('/http:\/\//', $ns)) {
  605. $ns = preg_replace('/http:\/\//', '', $ns);
  606. $ns = preg_replace('/\//','\\', $ns);
  607. $ns = preg_replace('/\./', '\\',$ns);
  608. }*/
  609. $matches = array();
  610. if (preg_match("#((http|https|ftp)://(\S*?\.\S*?))(\s|\;|\)|\]|\[|\{|\}|,|\"|'|:|\<|$|\.\s)#", $ns, $matches)) {
  611. $elements = explode("/", $matches[3]);
  612. $domain = $elements[0];
  613. array_shift($elements);
  614. //print_r($domain."\n");
  615. $ns = implode("\\",array_reverse(explode(".", $domain)));
  616. //$ns = preg_replace('/\./', '\\', );
  617. //print $ns."\n";
  618. foreach($elements as $key => $value) {
  619. if ($value != '') {
  620. $value = preg_replace('/\./', '_', $value);
  621. $hashpos = strpos($value, '#');
  622. if ($hashpos !== false)
  623. {
  624. $ns .= "\\" . substr($value, 0, $hashpos);
  625. break;
  626. }
  627. $ns .= "\\" . $value;
  628. }
  629. }
  630. }
  631. $ns = explode('\\', $ns);
  632. $i = 0;
  633. foreach($ns as $elem) {
  634. if (preg_match('/^([0-9]+)(.*)$/', $elem)) {
  635. $ns[$i] = "_".$elem;
  636. }
  637. if (in_array($elem, $this->reservedWords)) {
  638. $ns[$i] = "_".$elem;
  639. }
  640. $i++;
  641. }
  642. $ns = implode('\\', $ns);
  643. $this->namespaceToPhp[$xmlNS] = $ns;
  644. return $ns;
  645. }
  646. /**
  647. * Convert XML URI to Path
  648. * @param string $xmlNS XML URI
  649. *
  650. * @return string
  651. */
  652. private function namespaceToPath($xmlNS) {
  653. if (!empty($this->namespaceToPath[$xmlNS]))
  654. return $this->namespaceToPath[$xmlNS];
  655. $ns = $xmlNS;
  656. $ns = $this->expandNS($ns);
  657. if (preg_match('/urn:/', $ns)) {
  658. $ns = preg_replace('/-/', '_', $ns);
  659. $ns = preg_replace('/urn:/', '', $ns);
  660. $ns = preg_replace('/:/', DIRECTORY_SEPARATOR, $ns);
  661. }
  662. $matches = array();
  663. if (preg_match("#((http|https|ftp)://(\S*?\.\S*?))(\s|\;|\)|\]|\[|\{|\}|,|\"|'|:|\<|$|\.\s)#", $ns, $matches)) {
  664. $elements = explode("/", $matches[3]);
  665. $domain = $elements[0];
  666. array_shift($elements);
  667. //print_r($domain."\n");
  668. $ns = implode(DIRECTORY_SEPARATOR, array_reverse(explode(".", $domain)));
  669. //$ns = preg_replace('/\./', '\\', );
  670. //print $ns."\n";
  671. foreach($elements as $key => $value) {
  672. if ($value != '') {
  673. $value = preg_replace('/[\.|-]/', '_', $value);
  674. $hashpos = strpos($value, '#');
  675. if ($hashpos !== false)
  676. {
  677. $ns .= DIRECTORY_SEPARATOR . substr($value, 0, $hashpos);
  678. break;
  679. }
  680. $ns .= DIRECTORY_SEPARATOR . $value;
  681. }
  682. }
  683. }
  684. $ns = explode(DIRECTORY_SEPARATOR, $ns);
  685. $i = 0;
  686. foreach($ns as $elem) {
  687. if (preg_match('/^([0-9]+)(.*)$/', $elem)) {
  688. $ns[$i] = "_".$elem;
  689. }
  690. if (in_array($elem, $this->reservedWords)) {
  691. $ns[$i] = "_".$elem;
  692. }
  693. $i++;
  694. }
  695. $ns = implode(DIRECTORY_SEPARATOR, $ns);
  696. $this->namespaceToPath[$xmlNS] = $ns;
  697. return $ns;
  698. }
  699. }