2013-03-15 78 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