Advertisement
lignite0

XMLMapping

May 7th, 2017
183
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 9.42 KB | None | 0 0
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <offers>
  3.     <offer>
  4.         <id>{~ bind product.id ~}</id>
  5.         <availability>{~ bind product.availability ~}</availability>
  6.         <availability_description>{~ bind product.availability_description ~}</availability_description>
  7.         <promotional>{~ bind product.promotional ~}</promotional>
  8.         <name>{~ bind name ~}</name>
  9.         <price>{~ price netto PLN ~}</price>
  10.         <shipping>{~ bind product.shipping ~}</shipping>
  11.         <url>{~ bind product.url ~}</url>
  12.         <category>{~ bind product._temp.category ~}</category>
  13.         <subcategory>{~ call product.getCategoryId($0) ~}</subcategory>
  14.         <description>{~ call product.parseDescription($0) ~}</description>
  15.         <descriptionShort>{~ bind product.short_desc | gej ~}</descriptionShort>
  16.         <producer>{~ call product.getProducerId($0) ~}</producer>
  17.         <images>
  18.             <image>
  19.                 <url>{~ call product.parseImage($0) ~}</url>
  20.             </image>
  21.         </images>
  22.         <attributes>
  23.             <attribute>{~ call product.parseAttribute($0) ~}</attribute>
  24.         </attributes>
  25.     </offer>
  26. </offers>
  27.  
  28. ===================================================================================
  29.  
  30. <?xml version="1.0" encoding="UTF-8" ?>
  31. <offers>
  32.     <offer>
  33.         <id>3</id>
  34.         <availability>1</availability>
  35.         <availability_description>
  36.             <![CDATA[{JEZYK_DOSTEPNOSC}: <strong><span class="red">Produkt dostępny na miejscu.</span></strong><br /><span style="color: #999;">( produkt wycofany z produkcji, ograniczona dostępność )</span>]]></availability_description>
  37.         <promotional>1</promotional>
  38.         <name><![CDATA[Super Oferta: Portfel Ford BP WRC]]></name>
  39.         <price>39</price>
  40.         <shipping>
  41.             <![CDATA[Koszt wysyłki to 20 zł przy wpłacie na konto, 25 zł za pobraniem. Przy zakupach za min. 250 zł i płatności na konto wysyłka gratis.]]></shipping>
  42.         <url>http://www.rallyshop.pl/index.php?p3</url>
  43.         <category><![CDATA[Odzież i gadżety]]></category>
  44.         <subcategory><![CDATA[pozostałe]]></subcategory>
  45.         <description>
  46.             <![CDATA[Wieloprzegrodowy portfel Ford BP WRC w układzie pionowym. Posiada przegrodę z zamkiem błyskawicznym oraz z przegrodę z miejscami na zdjęcia z nadrukowanym logiem BP Ford World Rally Team.<br>]]></description>
  47.         <descriptionShort><![CDATA[Portfel Ford BP WRC.]]></descriptionShort>
  48.         <producer><![CDATA[Ford BP]]></producer>
  49.         <images>
  50.             <image>
  51.                 <url>http://rallyshop.pl/galerie/p/portfel-ford-bp-wrc_2.jpg</url>
  52.                 <thumb>http://rallyshop.pl/galerie/p/portfel-ford-bp-wrc_2_m.jpg</thumb>
  53.             </image>
  54.  
  55.         </images>
  56.         <attributes>
  57.  
  58.         </attributes>
  59.  
  60.     </offer>
  61.     <offer>
  62.         <id>4</id>
  63.         <availability>1</availability>
  64.         <availability_description>
  65.             <![CDATA[{JEZYK_DOSTEPNOSC}: <strong><span class="red">Produkt dostępny na miejscu.</span></strong><br /><span style="color: #999;">( produkt wycofany z produkcji, ograniczona dostępność )</span>]]></availability_description>
  66.         <promotional>1</promotional>
  67.         <name><![CDATA[Super Oferta: Kurtka BP Ford]]></name>
  68.         <price>299</price>
  69.         <shipping>
  70.             <![CDATA[Koszt wysyłki to 20 zł przy wpłacie na konto, 25 zł za pobraniem. Przy zakupach za min. 250 zł i płatności na konto wysyłka gratis.]]></shipping>
  71.         <url>http://www.rallyshop.pl/index.php?p4</url>
  72.         <category><![CDATA[Odzież i gadżety]]></category>
  73.         <subcategory><![CDATA[kurtki]]></subcategory>
  74.         <description>
  75.             <![CDATA[Lekka kurtka na wiosnę lub jesień. Wodoodporna. Posiada naszyte logo zespołu oraz loga sponsorów.]]></description>
  76.         <descriptionShort><![CDATA[Lekka kurtka na wiosnę lub jesień BP Ford WRC]]></descriptionShort>
  77.         <producer><![CDATA[Ford BP]]></producer>
  78.         <images>
  79.             <image>
  80.                 <url>http://rallyshop.pl/galerie/k/kurtka-bp-ford_3.jpg</url>
  81.                 <thumb>http://rallyshop.pl/galerie/k/kurtka-bp-ford_3_m.jpg</thumb>
  82.             </image>
  83.  
  84.         </images>
  85.         <attributes>
  86.             <attribute name="Wymiary własne">
  87.                 <![CDATA[<table style="text-align: left;" border="0" cellpadding="2" cellspacing="0"><tbody><tr><td align="undefined" valign="undefined"></td><td style="text-align: center; font-weight: bold;" valign="undefined">Szerokość (cm)</td><td style="text-align: center; font-weight: bold;" valign="undefined">Długość (cm)</td><td style="text-align: center; font-weight: bold;" valign="undefined">Długość rękawów (cm)</td></tr><tr><td style="text-align: center;" valign="undefined">S</td><td style="text-align: center;" valign="undefined">53</td><td style="text-align: center;" valign="undefined">69</td><td style="text-align: center;" valign="undefined">48</td></tr><tr><td style="text-align: center;" valign="undefined">M</td><td style="text-align: center;" valign="undefined">55</td><td style="text-align: center;" valign="undefined">72</td><td style="text-align: center;" valign="undefined">49</td></tr><tr><td style="text-align: center;" valign="undefined">L</td><td style="text-align: center;" valign="undefined">58</td><td style="text-align: center;" valign="undefined">73</td><td style="text-align: center;" valign="undefined">51</td></tr><tr><td style="text-align: center;" valign="undefined">XL</td><td style="text-align: center;" valign="undefined">60</td><td style="text-align: center;" valign="undefined">74</td><td style="text-align: center;" valign="undefined">53</td></tr><tr><td style="text-align: center;" valign="undefined">XXL</td><td style="text-align: center;" valign="undefined">62</td><td style="text-align: center;" valign="undefined">77</td><td style="text-align: center;" valign="undefined">53</td></tr></tbody></table>]]></attribute>
  88.  
  89.         </attributes>
  90.  
  91.     </offer>
  92. </offers>
  93.  
  94. ======================================================
  95.  
  96. <?php
  97.  
  98. class StackXMLReader extends XMLReader
  99. {
  100.     private $stack = [];
  101.  
  102.     public function process(callable $callback)
  103.     {
  104.         while ($this->read()) {
  105.             if ($this->nodeType === XMLReader::ELEMENT and $this->isEmptyElement === false) {
  106.                 array_push($this->stack, $this->name);
  107.                 $callback($this);
  108.             } elseif ($this->nodeType === XMLReader::END_ELEMENT) {
  109.                 array_pop($this->stack);
  110.             }
  111.         }
  112.     }
  113.  
  114.     public function getStack(): array
  115.     {
  116.         return $this->stack;
  117.     }
  118. }
  119.  
  120. abstract class XMLMapper
  121. {
  122.     private $xmlReader;
  123.  
  124.     public function __construct()
  125.     {
  126.         $this->xmlReader = new ExtendedXMLReader();
  127.         $this->registerMapping();
  128.     }
  129.  
  130.     public function process(string $filePath)
  131.     {
  132.         $this->xmlReader->open($filePath);
  133.         $this->xmlReader->parse();
  134.         $this->xmlReader->close();
  135.     }
  136.  
  137.     protected function registerCallbacksFromMappingFile(string $filePath)
  138.     {
  139.         $xml = new StackXMLReader();
  140.         $xml->open($filePath);
  141.         $xml->process(function (StackXMLReader $xml) {
  142.             $template = trim((string)$xml->readInnerXml());
  143.             if ($template and preg_match('/^{~(.*?)~}$/', $template, $matches)) {
  144.                 $xpath = '/'.implode('/', $xml->getStack());
  145.                 $parameters = array_map('trim', explode(' ', trim($matches[1])));
  146.                 $method = array_shift($parameters);
  147.                 $callback = [$this, $method];
  148.                 if (is_callable($callback) === false) {
  149.                     throw new UnexpectedValueException(sprintf(
  150.                         'Mapping callback (%s) does not exists in XMLMapping class', $method
  151.                     ));
  152.                 }
  153.                 $this->registerCallback($xpath, XMLReader::ELEMENT, $callback, $parameters);
  154.             }
  155.         });
  156.         $xml->close();
  157.     }
  158.  
  159.     protected function registerCallback(string $xpath, int $nodeType, callable $callback, array $parameters = [])
  160.     {
  161.         $this->xmlReader->registerCallback($xpath, function (ExtendedXMLReader $xml) use ($callback, $parameters) {
  162.             call_user_func($callback, $xml, ...$parameters);
  163.             return true;
  164.         }, $nodeType);
  165.     }
  166.  
  167.     abstract protected function registerMapping();
  168. }
  169.  
  170. class CurrentXMLMapper extends XMLMapper
  171. {
  172.     public $product = null;
  173.  
  174.     protected function registerMapping()
  175.     {
  176.         $this->registerCallbacksFromMappingFile('template.xml');
  177.  
  178.         $this->registerCallback('/offers/offer', XMLReader::ELEMENT, function () {
  179.             $this->product = new Product();
  180.         });
  181.  
  182.         $this->registerCallback('/offers/offer', XMLReader::END_ELEMENT, function () {
  183.             echo $this->product->name.PHP_EOL;
  184.         });
  185.     }
  186.  
  187.     protected function bind(ExtendedXMLReader $xml, string $expression)
  188.     {
  189.         $this->product->{$expression} = trim((string)$xml->readString());
  190.     }
  191.  
  192.     protected function call(ExtendedXMLReader $xml, string $expression)
  193.     {
  194.         $this->product->{$expression} = trim((string)$xml->readString());
  195.     }
  196.  
  197.     protected function price(ExtendedXMLReader $xml, string $type, string $currency)
  198.     {
  199.         $this->product->price[] = [
  200.             'type' => $type,
  201.             'currency' => $currency,
  202.             $type => trim((string)$xml->readString())
  203.         ];
  204.     }
  205. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement