Обход XML c неизвестной структурой php


0

Имеется XML-документ с неизвестной структурой (вложенностей может быть любое количество). Можно как-то обойти весь документ используя SimpleXML и получить нужные мне объекты, например, виды спорта?

p.s. В гугле нашёл статьи только для документов с известной структурой

Источник
  •  68
  •  2
  • 16 янв 2018 2018-01-16 10:39:20

2 ответа

0

Очень простой способ парсинга XML-файла c неизвестной структурой. Создаём рекурсивную функцию для перебора $xml:

public function xmlMap(&$result_array, SimpleXMLElement $xmlArray): void
{
    foreach($xmlArray as $key => $node) {
        $object = $this->getObject($node);
        if (!is_null($object)) {
            if (!is_null($object)) {
                if (!isset($result_array)) {
                    $result_array = array();
                }
                $i=-1;
                foreach ($node as $child) {
                    $object2 = $this->getObject($child);
                    $i++;
                    if (!is_null($object2)) {
                        break;
                    }
                }
                array_push($result_array, [$object, $node->children()[$i]->getName() => array()]);
                $this->xmlMap($result_array[count($result_array) - 1][$node->children()[$i]->getName()], $node);
            }
        }
    }
}

Где:

$result_array - массив, в котором будут храниться полученные данные (передаётся по ссылке)
$xmlArray - собственно наша переменная $xml
getObject($node) - функция для создания объекта в зависимости от узла

public function getObject(SimpleXMLElement $node)
    {
        switch ($node->getName()) {
            case XmlParser::NODE_SPORT:
                $object = $this->getSportOrCountry($node, new Sport());
                break;
            case XmlParser::NODE_COUNTRY:
                $object = $this->getSportOrCountry($node, new Country());
                break;
            case XmlParser::NODE_TOURNAMENT:
                $object = $this->getTournament($node, new Tournament());
                break;
            case XmlParser::NODE_EVENT:
                $object = $this->getEvent($node, new Event());
                break;
            case XmlParser::NODE_SCOPE:
                $object = $this->getScope($node, new Scope());
                break;
            case XmlParser::NODE_MARKET:
                $object = $this->getMarket($node, new Market());
                break;
            case XmlParser::NODE_OUTCOME:
                $object = $this->getOutcome($node, new Outcome());
                break;
            default:
                $object = null;
        }
        return $object;
    }

Использование кода:

 $xml = new SimpleXMLElement($this->xml_document);
 $result_array = array();
 $this->xmlMap($result_array, $xml);
 var_dump($result_array);
0

Могу предложить проверенный способ парса XML файлов любых строений, вывод данных будет в виде массива(если подойдёт)։

parseXml( $xml )

function parseXml( $xml ) {
        $xml_parser = xml_parser_create();
        xml_parse_into_struct( $xml_parser, $XML, $vals );
        xml_parser_free( $xml_parser );

        $_tmp = ;
        foreach ( $vals as $xml_elem ) {
            $x_tag = $xml_elem[ tag ];
            $x_level = $xml_elem[ level ];
            $x_type = $xml_elem[ type ];
            if ( $x_level != 1 && $x_type == close ) {
                if ( isset( $multi_key[ $x_tag ][ $x_level ] ) )
                    $multi_key[ $x_tag ][ $x_level ] = 1;
                else
                    $multi_key[ $x_tag ][ $x_level ] = 0;
            }
            if ( $x_level != 1 && $x_type == complete ) {
                if ( $_tmp == $x_tag )
                    $multi_key[ $x_tag ][ $x_level ] = 1;
                $_tmp = $x_tag;
            }
        }

        foreach ( $vals as $xml_elem ) {
            $x_tag = $xml_elem[ tag ];
            $x_level = $xml_elem[ level ];
            $x_type = $xml_elem[ type ];
            if ( $x_type == open )
                $level[ $x_level ] = $x_tag;
            $start_level = 1;
            $php_stmt = $xml_array;
            if ( $x_type == close && $x_level != 1 )
                $multi_key[ $x_tag ][ $x_level ]++;
            while ( $start_level < $x_level ) {
                $php_stmt .= [$level[ . $start_level . ]];
                if ( isset( $multi_key[ $level[ $start_level ] ][ $start_level ] ) && $multi_key[ $level[ $start_level ] ][ $start_level ] )
                    $php_stmt .= [ . ( $multi_key[ $level[ $start_level ] ][ $start_level ] - 1 ) . ];
                $start_level++;
            }
            $add = ;
            if ( isset( $multi_key[ $x_tag ][ $x_level ] ) && $multi_key[ $x_tag ][ $x_level ] && ( $x_type == open || $x_type == complete ) ) {
                if ( !isset( $multi_key2[ $x_tag ][ $x_level ] ) )
                    $multi_key2[ $x_tag ][ $x_level ] = 0;
                else
                    $multi_key2[ $x_tag ][ $x_level ]++;
                $add = [ . $multi_key2[ $x_tag ][ $x_level ] . ];
            }
            if ( isset( $xml_elem[ value ] ) && trim( $xml_elem[ value ] ) !=  && !array_key_exists( attributes, $xml_elem ) ) {
                if ( $x_type == open )
                    $php_stmt_main = $php_stmt . [$x_type] . $add . [content] = $xml_elem[value];;
                else
                    $php_stmt_main = $php_stmt . [$x_tag] . $add .  = $xml_elem[value];;
                eval( $php_stmt_main );
            }
            if ( array_key_exists( attributes, $xml_elem ) ) {
                if ( isset( $xml_elem[ value ] ) ) {
                    $php_stmt_main = $php_stmt . [$x_tag] . $add . [content] = $xml_elem[value];;
                    eval( $php_stmt_main );
                }
                foreach ( $xml_elem[ attributes ] as $key => $value ) {
                    $php_stmt_att = $php_stmt . [$x_tag] . $add . [$key] = $value;;
                    eval( $php_stmt_att );
                }
            }
        }
        return $xml_array;
    }
  • 16 янв 2018 2018-01-16 10:56:05