class XMLReaderStruct extends XMLReader { public function xmlStruct($xml, $structure, $encoding = null, $options = 0, $debug = false) { $this->xml($xml, $encoding, $options); $stack = array(); $node = &$structure; $skipToDepth = false; while ($this->read()) { switch ($this->nodeType) { case self::ELEMENT: if ($skipToDepth === false) { //       ,     ,  :      //  ,   ,      ,      .  //  ,    ,        . if (isset($node[$this->name])) { if ($debug) echo "[  ]: ",$this->name," -   .   .\r\n"; $stack[$this->depth] = &$node; $node = &$node[$this->name]; if (isset($node["__open"])) { if ($debug) echo "    ",$this->name," - .\r\n"; if (false === $node["__open"]()) return false; } if (isset($node["__attrs"])) { if ($debug) echo "    ",$this->name," - .\r\n"; $attrs = array(); if ($this->hasAttributes) while ($this->moveToNextAttribute()) $attrs[$this->name] = $this->value; if (false === $node["__attrs"]($attrs)) return false; } if ($this->isEmptyElement) { if ($debug) echo "  ",$this->name," .   .\r\n"; if (isset($node["__close"])) { if ($debug) echo "    ",$this->name," - .\r\n"; if (false === $node["__close"]()) return false; } $node = &$stack[$this->depth]; } } else { $skipToDepth = $this->depth; if ($debug) echo "[  ]: ",$this->name," -    .        ",$skipToDepth,".\r\n"; } } else { if ($debug) echo "(  ): ",$this->name," -    .\r\n"; } break; case self::TEXT: if ($skipToDepth === false) { if ($debug) echo "[  ]: ",$this->value," -  .\r\n"; if (isset($node["__text"])) { if ($debug) echo "    - .\r\n"; if (false === $node["__text"]($this->value)) return false; } } else { if ($debug) echo "(  ): ",$this->value," -    .\r\n"; } break; case self::END_ELEMENT: if ($skipToDepth === false) { //  $skipToDepth  ,   ,        , //       . if ($debug) echo "[  ]: ",$this->name," -   .   .\r\n"; if (isset($node["__close"])) { if ($debug) echo "    ",$this->name," - .\r\n"; if (false === $node["__close"]()) return false; } $node = &$stack[$this->depth]; } elseif ($this->depth === $skipToDepth) { //  $skipToDepth ,   ,    ,         . if ($debug) echo "[  ]: ",$this->name," -   ",$skipToDepth,".    .\r\n"; $skipToDepth = false; } else { if ($debug) echo "(  ): ",$this->name," -    .\r\n"; } break; } } return true; } }  xmlStruct($xml, $structure, $encoding = null, $options = 0, $debug = false)  <?xml version="1.0" encoding="UTF-8"?> <root> <a attr_1="123" attr_2="456">Abc</a> <b> <x>This is node <x> inside <b></x> </b> <c></c> <d> <x>This is node <x> inside <d></x> </d> <e></e> </root>  $structure = array( 'root' => array( 'a' => array( "__attrs" => function($array) { echo "ATTR ARRAY IS ",json_encode($array),"\r\n"; }, "__text" => function($text) use (&$a) { echo "TEXT a {$text}\r\n"; } ), 'b' => array( "__open" => function() { echo "OPEN b\r\n"; }, "__close" => function() { echo "CLOSE b\r\n"; }, 'x' => array( "__open" => function() { echo "OPEN x\r\n"; }, "__text" => function($text) { echo "TEXT x {$text}\r\n"; }, "__close" => function() { echo "CLOSE x\r\n"; } ) ) ) ); $xmlReaderStruct->xmlStruct($xml, $structure);  <?xml version="1.0" encoding="UTF-8"?> <shop> <record> <id>0</id> <type>product</type> <name>Some product name. ID:0</name> <qty>0</qty> <price>0</price> </record> <record> <id>1</id> <type>service</type> <name>Some product name. ID:1</name> <qty>1</qty> <price>15</price> </record> <record> <id>2</id> <type>product</type> <name>Some product name. ID:2</name> <qty>2</qty> <price>30</price> </record> <record> <id>3</id> <type>service</type> <name>Some product name. ID:3</name> <qty>3</qty> <price>45</price> </record> <record> <id>4</id> <type>product</type> <name>Some product name. ID:4</name> <qty>4</qty> <price>60</price> </record> <record> <id>5</id> <type>service</type> <name>Some product name. ID:5</name> <qty>5</qty> <price>75</price> </record> </shop>  include_once "xmlreaderstruct.class.php"; $x = new XMLReaderStruct(); $productsSum = 0; $servicesSum = 0; $structure = array( 'shop' => array( 'record' => array( 'type' => array( "__text" => function($text) use (&$currentRecord) { $currentRecord['isService'] = $text === 'service'; } ), 'qty' => array( "__text" => function($text) use (&$currentRecord) { $currentRecord['qty'] = (int)$text; } ), 'price' => array( "__text" => function($text) use (&$currentRecord) { $currentRecord['price'] = (int)$text; } ), '__open' => function() use (&$currentRecord) { $currentRecord = array(); }, '__close' => function() use (&$currentRecord, &$productsSum, &$servicesSum) { $money = $currentRecord['qty'] * $currentRecord['price']; if ($currentRecord['isService']) $servicesSum += $money; else $productsSum += $money; } ) ) ); $x->xmlStruct(file_get_contents('example.xml'), $structure); echo 'Overal products price: ', $productsSum, ', Overal services price: ', $servicesSum; Source: https://habr.com/ru/post/452648/
All Articles