【问题标题】:PHP DOM XML to arrray conversionPHP DOM XML 到数组的转换
【发布时间】:2020-10-29 22:48:22
【问题描述】:

我在下面有一个 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)不会给我一些空数组元素(ii)检查任何子节点并将所有 xml 兄弟元素放在一个字符串中

【问题讨论】:

    标签: php arrays xml


    【解决方案1】:

    PHPs DOM 支持用于获取特定节点和值的 Xpath 表达式。这大大减少了您需要的循环数量和条件。

    这是一个演示:

    // 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);
    

    【讨论】:

    • 虽然这编码了一堆关于问题中代码没有的结构的假设,但我认为这是一件好事——试图使代码完全通用几乎肯定会导致更多比它解决的问题。
    • 是的,因为“通用转换”通常取决于元素的特定数量和位置。否则会产生不一致的数据。例如,如果您在名称或名称和年份元素的更改顺序之前添加 ISBN 元素。它实际上做了很多假设,只是在源代码中并不那么明显。
    猜你喜欢
    • 1970-01-01
    • 2020-09-28
    • 2017-04-01
    • 2011-12-25
    • 2015-09-03
    • 2016-10-03
    • 1970-01-01
    • 1970-01-01
    • 2017-06-24
    相关资源
    最近更新 更多