XML рекурсивная итерационная группировка - PullRequest
1 голос
/ 12 октября 2019

XML-файл с разной глубиной «детей» в семье должен быть проанализирован, чтобы собрать всех потомков в список.

Как показано в примере кода на https://3v4l.org/GV0UV, который включает в себя XML, код, который обрабатывает XML, является следующим, где $buffer содержит XML:

$xml       = new SimpleXMLIterator($buffer);
$recursive = new RecursiveIteratorIterator($xml);

foreach ($recursive as $tag => $object) {
    if ($tag !== 'Name') { 
        continue;
    }

        echo "-> " . $object ;
}

Вывод такой:

-> 1David-> 1Samuel-> 1Fred-> 1John-> 1Frank-> 1Robert-> 2David-> 2Samuel-> 2Fred-> 2John-> 3David-> 3Samuel-> 3Fred-> 3John-> 3Frank

Мне нужно разделить это на семьи («1David» - это человек из другой семьи, нежели «2David»; в реальном мире предполагаются разные имена для каждого члена семьи).

Требуемый вывод должен быть таким:

-> 1David-> 1Samuel-> 1Fred-> 1John-> 1Frank-> 1Robert
-> 2David-> 2Samuel-> 2Fred-> 2John
-> 3David-> 3Samuel-> 3Fred-> 3John-> 3Frank

Таким образом, RecursiveIteratorIterator находит все значения 'name' в XML, но вывод должен быть разделен на 'семьи'.

Как разделить извлечение имен в семейства?

(Примечание: мой предыдущий вопрос здесь Итерация по многоуровневому XML-файлу ; было предложеночто я начинаю новый вопрос.)

Ответы [ 2 ]

3 голосов
/ 12 октября 2019

Вы можете просто проверить уровень RecursiveIteratorIterator (используя getDepth()), который скажет вам, как далеко вы находитесь во вложенности. 1 означает, что вы находитесь на верхнем уровне ...

foreach ($recursive as $tag => $object) {
    if ($tag !== 'Name') {
        continue;
    }

    if ( $recursive->getDepth() == 1 )  {
        echo PHP_EOL;
    }
    echo "-> " . $object ;
}

, что будет эхом ...

-> 1David-> 1Samuel-> 1Fred-> 1John-> 1Frank-> 1Robert
-> 2David-> 2Samuel-> 2Fred-> 2John
-> 3David-> 3Samuel-> 3Fred-> 3John-> 3Frank

Несмотря на то, что спереди есть пустая строка, это должно бытьлегко удалить.

Чтобы превратить это во что-то, что хранит данные ...

$output = [];
$family = [];
foreach ($recursive as $tag => $object) {
    if ($tag !== 'Name') {
        continue;
    }

    if ( $recursive->getDepth() == 1 )  {
        if (!empty($family) )   {
            $output[] = $family;
            $family = [];
        }
    }
    $family[] = (string)$object;
}
if (!empty($family) )   {
    $output[] = $family;
}

print_r($output);

дает ...

Array
(
    [0] => Array
        (
            [0] => 1David
            [1] => 1Samuel
            [2] => 1Fred
            [3] => 1John
            [4] => 1Frank
            [5] => 1Robert
        )

    [1] => Array
        (
            [0] => 2David
            [1] => 2Samuel
            [2] => 2Fred
            [3] => 2John
        )

    [2] => Array
        (
            [0] => 3David
            [1] => 3Samuel
            [2] => 3Fred
            [3] => 3John
            [4] => 3Frank
        )

)
0 голосов
/ 13 октября 2019

Вот другой подход для этого с использованием выражений Xpath. Это не рекурсивно, но гораздо более конкретно. У Xpath есть ось, подобная ancestor и descendant, чтобы заставить выражение двигаться в определенном направлении в дереве узлов.

$document = new DOMDocument();
$document->loadXml($buffer);
$xpath = new DOMXpath($document);

// for each top level Family
foreach ($xpath->evaluate('/root/Family') as $family) {
    echo $xpath->evaluate('string(Name)', $family), "\n-------------------\n";
    // find all ancestors without ancestors themself
    foreach ($xpath->evaluate('.//Ancestors[not(.//Ancestors)]/Family', $family) as $ancestor) 
        $names = [];
        // get the Family nodes on the path upwards
        foreach ($xpath->evaluate('ancestor::Family', $ancestor) as $descendant) {
            // collect the name
            $names[] = $xpath->evaluate('string(Name)', $descendant);
        }
        echo implode(' -> ', $names), "\n";
    }
    echo "\n";   
}

Вывод:

1David
-------------------
1David -> 1Samuel -> 1Fred -> 1John -> 1Frank

2David
-------------------
2David -> 2Samuel -> 2Fred

3David
-------------------
3David -> 3Samuel -> 3Fred -> 3John
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...