【问题标题】:Parse a nested xml with PHP to an object使用 PHP 将嵌套的 xml 解析为对象
【发布时间】:2010-12-25 06:04:50
【问题描述】:

我必须用 PHP 将一个 xml 文件解析为一个对象。目前我不知道如何执行此操作,不胜感激。

xml 很大。我必须解析它的一部分,如下所示:

<someNamespace:xmlDocument>
<someNamespace:categories>
    <category name="Patrick" anAttribute="numericValue" anotherAttribute="numericValue">
        <category name="Andrew" anAttribute="numericValue" anotherAttribute="numericValue">
            <category name="Alice" anAttribute="numericValue" anotherAttribute="numericValue">
                <category name="Thomas" anAttribute="numericValue" anotherAttribute="numericValue">
                    <category name="Michael" anAttribute="numericValue" anotherAttribute="numericValue"/>
                    <category name="Matthew" anAttribute="numericValue" anotherAttribute="numericValue"/>
                </category>
                <category name="Janet" anAttribute="numericValue" anotherAttribute="numericValue">
                    <category name="Steven" anAttribute="numericValue" anotherAttribute="numericValue"/>
                    <category name="Christopher" anAttribute="numericValue" anotherAttribute="numericValue"/>
                </category>
                <category name="Sue" anAttribute="numericValue" anotherAttribute="numericValue"/>
            </category>
            <category name="Charles" anAttribute="numericValue" anotherAttribute="numericValue">
                <category name="John" anAttribute="numericValue" anotherAttribute="numericValue">
                    <category name="Charles" anAttribute="numericValue" anotherAttribute="numericValue"/>
                    <category name="Rosamund" anAttribute="numericValue" anotherAttribute="numericValue"/>
                    <category name="Stuart" anAttribute="numericValue" anotherAttribute="numericValue"/>
                    <category name="Rosamund" anAttribute="numericValue" anotherAttribute="numericValue"/>
                </category>
                <category name="John" anAttribute="numericValue" anotherAttribute="numericValue"/>
            </category>
        </category>
        <category name="Oliver" anAttribute="numericValue" anotherAttribute="numericValue">
            <category name="Jane" anAttribute="numericValue" anotherAttribute="numericValue"/>
            <category name="Lucy" anAttribute="numericValue" anotherAttribute="numericValue">
                <category name="David" anAttribute="numericValue" anotherAttribute="numericValue"/>
                <category name="Robert" anAttribute="numericValue" anotherAttribute="numericValue"/>
                <category name="Hetty" anAttribute="numericValue" anotherAttribute="numericValue">
                    <category name="Kenneth" anAttribute="numericValue" anotherAttribute="numericValue"/>
                    <category name="Jonathan" anAttribute="numericValue" anotherAttribute="numericValue"/>
                </category>
                <category name="Freddy" anAttribute="numericValue" anotherAttribute="numericValue"/>
                <category name="Virginia" anAttribute="numericValue" anotherAttribute="numericValue"/>
            </category>
        </category>
    </category>
</someNamespace:categories>

每个“name”和“anAttribute”属性都是唯一的。

之后我想要的是一个包含许多类别对象的类别对象......

谢谢!

【问题讨论】:

    标签: php xml arrays


    【解决方案1】:

    simplexml_load_file

    <?php
    // The file test.xml contains an XML document with a root element
    // and at least an element /[root]/title.
    
    if (file_exists('test.xml')) {
        $xml = simplexml_load_file('test.xml');
    
        print_r($xml);
    } else {
        exit('Failed to open test.xml.');
    }
    ?>
    

    【讨论】:

    • 请注意,这将返回 simpleXML 元素而不是普通对象。 simplexml 元素在某些上下文中的行为不同。查看文档以获取示例。
    • 我想知道这是否真的有效,因为我知道 simpleXML 在命名空间方面存在很大问题。
    • SimpleXML 与命名空间一起工作得很好,只是它的行为并不总是像你想象的那样。
    • 好吧,意外的行为并不是我所说的“工作得很好”,但这是一个见仁见智的问题。我从来没有想过让它发挥作用。
    【解决方案2】:

    定义 DOMDocument 的扩展

    class MyDOMDocument extends DOMDocument
    {
        public function toArray(DOMNode $oDomNode = null)
        {
            // return empty array if dom is blank
            if (is_null($oDomNode) && !$this->hasChildNodes()) {
                return array();
            }
            $oDomNode = (is_null($oDomNode)) ? $this->documentElement : $oDomNode;
            if (!$oDomNode->hasChildNodes()) {
                $mResult = $oDomNode->nodeValue;
            } else {
                $mResult = array();
                foreach ($oDomNode->childNodes as $oChildNode) {
                    // how many of these child nodes do we have?
                    // this will give us a clue as to what the result structure should be
                    $oChildNodeList = $oDomNode->getElementsByTagName($oChildNode->nodeName);
                    $iChildCount = 0;
                    // there are x number of childs in this node that have the same tag name
                    // however, we are only interested in the # of siblings with the same tag name
                    foreach ($oChildNodeList as $oNode) {
                        if ($oNode->parentNode->isSameNode($oChildNode->parentNode)) {
                            $iChildCount++;
                        }
                    }
                    $mValue = $this->toArray($oChildNode);
                    $sKey   = ($oChildNode->nodeName{0} == '#') ? 0 : $oChildNode->nodeName;
                    $mValue = is_array($mValue) ? $mValue[$oChildNode->nodeName] : $mValue;
                    // how many of thse child nodes do we have?
                    if ($iChildCount > 1) {  // more than 1 child - make numeric array
                        $mResult[$sKey][] = $mValue;
                    } else {
                        $mResult[$sKey] = $mValue;
                    }
                }
                // if the child is <foo>bar</foo>, the result will be array(bar)
                // make the result just 'bar'
                if (count($mResult) == 1 && isset($mResult[0]) && !is_array($mResult[0])) {
                    $mResult = $mResult[0];
                }
            }
            // get our attributes if we have any
            $arAttributes = array();
            if ($oDomNode->hasAttributes()) {
                foreach ($oDomNode->attributes as $sAttrName=>$oAttrNode) {
                    // retain namespace prefixes
                    $arAttributes["@{$oAttrNode->nodeName}"] = $oAttrNode->nodeValue;
                }
            }
            // check for namespace attribute - Namespaces will not show up in the attributes list
            if ($oDomNode instanceof DOMElement && $oDomNode->getAttribute('xmlns')) {
                $arAttributes["@xmlns"] = $oDomNode->getAttribute('xmlns');
            }
            if (count($arAttributes)) {
                if (!is_array($mResult)) {
                    $mResult = (trim($mResult)) ? array($mResult) : array();
                }
                $mResult = array_merge($mResult, $arAttributes);
            }
            $arResult = array($oDomNode->nodeName=>$mResult);
            return $arResult;
        }
    }
    

    这样使用

    $mydom = new MyDOMDocument();
    $mydom->load('test.xml');
    
    print_r($mydom->toArray());
    

    【讨论】:

    • 嗨彼得,非常感谢你!这帮助我开始了。但我还没说完,所以也许我得在这里再问一次。
    猜你喜欢
    • 1970-01-01
    • 2023-01-25
    • 2020-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多