2013-03-15 52 views
0

我试图根据xmldata构建一个数组结构。我相信这个问题与我如何处理$finalData有关。我最终想要一个包含三个记录数组的扁平数组,但我想我需要先正确解析XML数据,然后再展开数据数组。我想修复代码来解析XML数据,所以我最初的问题是如何修复这个代码来解析XML数据,但是接下来我要研究如何平铺最终的数据数组(我需要个人record包含相关信息,我最终需要的结构。我想你可以说我试着去处理数据的用户导入,最终只检索包含数据的各个组件。PHP递归收集SimpleXMLElement数据并压扁数组数组

public function processXml($xmldata,$finalData=array()) 
{ 
    $finalData = array(); 
    if($xmldata instanceof SimpleXMLElement){ 
     foreach($xmldata as $idata){ 
      $this->processXml($idata,$finalData); 
     } 
    } else { 
     array_push($finalData,$xmldata); 
    } 
    return $finalData; 
} 

这里的XML数据(注意,我不知道用户将在他的XML数据中导入什么,这只是我创建的测试数据):

`<?xml version="1.0" encoding="UTF-8"?> 
    <configdata> 
     <records> 
      <somekey> 
       <record> 
        <firstname>Jonathan</firstname> 
        <lastname>Kushner</lastname> 
       </record> 
       <record> 
        <firstname>Dustin</firstname> 
        <lastname>Kushner</lastname> 
       </record> 
       <record> 
        <firstname>Cameron</firstname> 
        <lastname>Kushner</lastname> 
       </record> 
      </somekey> 
     </records> 
    </configdata>` 

注意:提供的答案使用xpath和domdocument。我试图学习递归和展平,所以虽然这是一个更好的方法,但我仍然想知道如何使用递归和展平来实现这一点。

+0

请出示输入XML和结果数组你想(注:一个XML文档转换成一个阵列通常会导致数据的语义损失)。此外,可能的快速修复,你会希望通过引用传递'$ finalData',或者将递归调用的结果与它合并,尝试'public function processXml($ xmldata,&$ finalData = null){if(!isset $ finalData)){$ finalData = array(); }/*其余的方法代码* /}' – DaveRandom 2013-03-15 16:18:11

+0

修复了这个问题。另外,我试过你的解决方案,它没有工作。 – jkushner 2013-03-15 16:34:48

+0

那么你想从这个XML中得到什么?只是一个3个字符串的数组? – DaveRandom 2013-03-15 16:35:47

回答

1

与使用递归循环地毯式炸弹方法相比,使用XPath仅以精确的方式提取所需的数据要好得多。

这里是你如何acheive你想要什么:

// Create the document object 
$xml = simplexml_load_string($xmlData); 

$result = array(); 

// Get the <record> nodes and loop them 
foreach ($xml->xpath('//record') as $record) { 
    // to get the text data from a node in SimpleXML, just cast it to a string 
    $result[] = array(
     'firstname' => (string) $record->firstname, 
     'lastname' => (string) $record->lastname, 
    ); 
} 

print_r($result); 

See it working

采取从$record所有子元素不知道它的名字,你可以使用:

$result[] = array_map(
    'strval', 
    iterator_to_array($record->children()) 
); 

取注意同名元素(这在XML中是可能的)在数组中不起作用。这里只有最后一个具有相同名称的元素才能存活。

编辑

这也仍然使用XPath可以做到,但你需要使用的,而不是SimpleXML的DOM(这不应该是一个问题,它是随处可见)。你可以做这样的事情:

// Create the document object 
$doc = new DOMDocument; 

// This is required in order to ignore the pretty-print whitspace 
$doc->preserveWhiteSpace = false; 

// load the data into the object 
$doc->loadXML($xmlData); 
$xpath = new DOMXpath($doc); 

$result = array(); 

// Get the text nodes and loop them 
foreach ($xpath->query('//text()') as $record) { 
    $result[] = $record->data; 
} 

print_r($result); 

See it working

+0

我没有说清楚,我没有知道键是什么,所以我不能做一个键的xpath。我会更新这个问题。 – jkushner 2013-03-15 16:43:42

+0

修复了问题 – jkushner 2013-03-15 16:45:21

+0

@jkushner:工作原理基本相同,您只需使用'$ record-> children()'获取所有(未知的已命名的)子元素。把这些放入数组中,你应该没问题。你可以在答案中找到一个编辑。 – hakre 2013-03-15 16:51:03