3

这是我正在使用的示例 xml:

<contact id="43956">
 <personal>
      <name>
           <first>J</first>
           <middle>J</middle>
           <last>J</last>
           Some text...
      </name>
      <title>Manager</title>
      <employer>National</employer>
      <dob>1971-12-22</dob>
 </personal>
</contact>

我得到了,Some text...但现在我需要我的代码来读取整个 xml 文档。它也没有读取 xml 中的值......正如你所知道的那样,我以前从未使用XMLReader过。

这就是我得到的:

Array ( [contact] => Array ( [id] => 43956 [value] => some sample value ) [first] => [middle] => [last] => [#text] => Some text... [name] => [title] => [employer] => [dob] => [personal] => )

这是我现在拥有的代码:

function xml2array($file, array $result = array()) {
$lastElementNodeType = '';
$xml = new XMLReader();
if(!$xml->open($file)) {
    die("Failed to open input file");
}
while($xml->read()) {
    switch ($xml->nodeType) {
        case $xml::END_ELEMENT:
            $lastElementNodeType = $xml->nodeType;
        case $xml::TEXT:
            $tag = $xml->name;
            if($lastElementNodeType == 15) {
                $result[$tag] = $xml->readString();                 
            }
        case $xml::ELEMENT:
            $lastElementNodeType = $xml->nodeType;
            $tag = $xml->name;
            if($xml->hasAttributes) {
                while($xml->moveToNextAttribute()) {
                    $result[$tag][$xml->name] = $xml->value;
                }
            }
    }
}
print_r($result);
}

我想过让这个函数递归,但是当我尝试这样做时,它使数组变得非常混乱。

我有一个版本,但它仍然没有输出Jfirst等等:

function xml2assoc($xml) { 
$tree = null; 
while($xml->read()) 
    switch ($xml->nodeType) { 
        case XMLReader::END_ELEMENT: return $tree; 
        case XMLReader::ELEMENT: 
            $node = array('tag' => $xml->name, 'value' => $xml->isEmptyElement ? '' : xml2assoc($xml)); 
            if($xml->hasAttributes) 
                while($xml->moveToNextAttribute()) 
                    $node['attributes'][$xml->name] = $xml->value; 
            $tree[] = $node; 
        break; 
        case XMLReader::TEXT: 
        case XMLReader::CDATA: 
            $tree .= $xml->value; 
    } 
return $tree; 
}
4

1 回答 1

0

拿 1

我认为您需要做的是保存最近节点的类型或至少最后一个节点的类型,以便对其进行测试。简而言之,至少当您在示例 XML 中呈现它时,您将遇到一个ELEMENT_END节点类型、一个TEXT带有您要查找的文本的节点类型,然后是另一个ELEMENT_END节点类型。

因此,您将需要一个case $xml::TEXT,并且您还需要保存以前的节点类型,以便您的解析器知道,在正常情况下,它应该期待一个新ELEMENT事件或一个END_ELEMENT事件,但已经收到文本。这将是您需要将文本捕获到临时变量readString()并保存它以供您使用的信号,或者等待查看下一个节点是否也是一个ELEMENT_END,此时您可以保存它并清除临时变量。

拿 2

现在我们对您希望得到的结果有了更多了解(即,由于您希望捕获整个树,而不仅仅是从中获取特定信息),我建议您坚持使用函数的递归版本. 我稍微修改了你的那个(请参阅 TEXT 和 CDATA 案例以了解主要的实质性变化)。

function xml2assoc($xml)
{
    $tree = null;
    while($xml->read())
    {
        switch ($xml->nodeType)
        {
            case XMLReader::END_ELEMENT:
                return $tree;
            case XMLReader::ELEMENT: 
                $node = array('tag' => $xml->name, 'value' => $xml->isEmptyElement ? '' : xml2assoc($xml));
                if($xml->hasAttributes)
                    while($xml->moveToNextAttribute()) 
                        $node['attributes'][$xml->name] = $xml->value; 
                $tree[] = $node;
                break;
            case XMLReader::TEXT:
                $tree["text"] = $xml->value;
                break;
            case XMLReader::CDATA:
                $tree["cdata"] = $xml->value;
                break;
        }
    }
    return $tree;
}

这种情况下的输出如下所示:

Array
(
    [0] => Array
        (
            [tag] => contact
            [value] => Array
                (
                    [0] => Array
                        (
                            [tag] => personal
                            [value] => Array
                                (
                                    [0] => Array
                                        (
                                            [tag] => name
                                            [value] => Array
                                                (
                                                    [0] => Array
                                                        (
                                                            [tag] => first
                                                            [value] => Array
                                                                (
                                                                    [text] => J
                                                                )
                                                        )
                                                    [1] => Array
                                                        (
                                                            [tag] => middle
                                                            [value] => Array
                                                                (
                                                                    [text] => J
                                                                )
                                                        )
                                                    [2] => Array
                                                        (
                                                            [tag] => last
                                                            [value] => Array
                                                                (
                                                                    [text] => J
                                                                )
                                                        )
                                                    [text] => Some text...
                                                )
                                        )
                                    [1] => Array
                                        (
                                            [tag] => title
                                            [value] => Array
                                                (
                                                    [text] => Manager
                                                )
                                        )
                                    [2] => Array
                                        (
                                            [tag] => employer
                                            [value] => Array
                                                (
                                                    [text] => National
                                                )
                                        )
                                    [3] => Array
                                        (
                                            [tag] => dob
                                            [value] => Array
                                                (
                                                    [text] => 1971-12-22
                                                )
                                        )
                                )
                        )
                )
            [attributes] => Array
                (
                    [id] => 43956
                )
        )
)

我认为这就是您要做的小修改,尽管我们实际上只是在这里重新发明轮子。我希望您需要解析的 XML 不是特别大。

于 2012-12-23T03:24:23.640 回答