PHP DOM XML в преобразование массива - PullRequest
0 голосов
/ 09 июля 2020

У меня есть документ xml ниже:

<?xml version="1.0" encoding="UTF-8" ?>
<books>
    <book>
        <name>Title One</name>
        <year>2014</year>
        <authors>
            <author>
                <name>Author One</name>
            </author>
        </authors>
    </book>
    <book serie="yes">
        <name>Title Two</name>
        <year>2015</year>
        <authors>
            <author>
                <name>Author two</name>
            </author>
            <author>
                <name>Author three</name>
            </author>
        </authors>
    </book>
    <book serie="no">
        <name>Title Three</name>
        <year>2015</year>
        <authors>
            <author>
                <name>Author four</name>
            </author>
        </authors>
    </book>
</books>

Я хочу преобразовать его в приведенный ниже массив.

array(
    array('Tittle one', 2014, 'Author One'),
    array('Tittle two', 2015, 'Author two, Author three'),
    array('Tittle three', 2015, 'Author four'),
);

Мой приведенный ниже код не может создать структуру массива что я хотел бы:

function arrayRepresentation(){

    $xmldoc = new DOMDocument();

    $xmldoc->load("data/data.xml");

    $parentArray =  array();

    foreach ($xmldoc->getElementsByTagName('book') as $item) {

        $parentArray[] = array_generate($item);

    }

    var_dump($parentArray);
}


function array_generate($item){

    $movieArray = array();
    $childMovieArray = array();

    for ($i = 0; $i < $item->childNodes->length; ++$i) {
        $child = $item->childNodes->item($i);

        if ($child->nodeType == XML_ELEMENT_NODE) {
            if(hasChild($child)){

                $childMovieArray = array_generate($child);

            }

        }
        $movieArray[] = trim($child->nodeValue);
    }
    
    if(!empty($childMovieArray)){
        $movieArray = array_merge($movieArray,$childMovieArray);
    }
    

    return $movieArray;

}

function hasChild($p)
{
    if ($p->hasChildNodes()) {
        foreach ($p->childNodes as $c) {
            if ($c->nodeType == XML_ELEMENT_NODE)
                return true;
        }
    }
}


arrayRepresentation();

В основном я перебираю узлы, чтобы получить значения элементов xml. Затем я проверяю, есть ли у I Node дополнительные дочерние узлы и снова ли через него проходит I l oop, чтобы получить значения. Я не могу вывести способ, который: (i) не даст мне пустых элементов массива (ii) Проверьте наличие дочерних узлов и поместите все xml дочерние элементы в одну строку

1 Ответ

3 голосов
/ 09 июля 2020

PHP DOM поддерживает выражения Xpath для получения c определенных узлов и значений. Это резко сокращает количество циклов и условий, которые вам понадобятся.

Вот демонстрация:

// bootstrap the XML document
$document = new DOMDocument();
$document->loadXML($xml);
$xpath = new DOMXpath($document);

$data = [];
// iterate the node element nodes
foreach ($xpath->evaluate('/books/book') as $book) {
    $authors = array_map(
       fn ($node) => $node->textContent,
       // fetch author name nodes as an array
       iterator_to_array($xpath->evaluate('authors/author/name', $book))
    );
    $data[] = [
        // cast first name element child to string
        $xpath->evaluate('string(name)', $book),
        // cast first year element child to string
        $xpath->evaluate('string(year)', $book),
        implode(', ', $authors)
    ];
}

var_dump($data);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...