2017-07-19 177 views
0

我看到了很多的教程在這裏溢出,但我不明白我錯過了什麼。所以我需要一些幫助..XML獲取屬性

我有一個XML,它是在網上,我想解析這樣的:

<products> 
    <product> 
    <id>13389</id> 
    <name><![CDATA[ product name ]]></name> 
    <category id="14"><![CDATA[ Shoes > test1 ]]></category> 
    <price>41.30</price> 
</products> 

據,我讀XML和解析它像這樣:

$reader = new XMLReader(); 
$reader->open($product_xml_link); 
while($reader->read()) { 
if($reader->nodeType == XMLReader::ELEMENT && $reader->name == 'product') { 
    $product = new SimpleXMLElement($reader->readOuterXml()); 
    $pid = $product->id; 
    $name = $product->name; 
    $name = strtolower($name); 
    $link = $product->link; 
    $price = $product->Price; 
    ... 
    ... 
} 
} //end while loop 

正如你所看到的,有類別標籤的ID。這是我想抓住並接受我的代碼..

我做了這樣的事情:

echo "prodcut= " . (string)$product->category->getAttribute('id'); 

我得到的錯誤是: 調用未定義的方法的SimpleXMLElement ::的getAttribute()

我需要這個ID,以便插入之前對其進行測試它在DB ..因此,

if($id = 600) { 
//insert DB 
} 

回答

1

這裏有幾件事。第一個$product = new SimpleXMLElement($reader->readOuterXml());意味着您正在將所有內容作爲單獨的XML文檔進行讀取並再次解析。這裏是expand(),它將直接返回一個DOM節點,並且DOM節點可以被導入到SimpleXML中。

對於屬性使用數組語法..

$reader = new XMLReader(); 
$reader->open($product_xml_link); 

// an document to expand to 
$document = new DOMDocument(); 

// find the first product node 
while ($reader->read() && $reader->localName !== 'product') { 
    continue; 
} 

while ($reader->localName === 'product') { 
    $product = simplexml_import_dom($reader->expand($document)); 
    $data = [ 
    'id' => (string)$product->id, 
    'name' => (string)$product->name, 
    'category_id' => (string)$product->category['id'], 
    // ... 
    ]; 
    var_dump($data); 
    // move to the next product sibling 
    $reader->next('product'); 
} 
$reader->close(); 

輸出:

array(3) { 
    ["id"]=> 
    string(5) "13389" 
    ["name"]=> 
    string(14) " product name " 
    ["category_id"]=> 
    string(2) "14" 
} 

當然可以直接使用DOM和使用XPath表達式獲取詳細數據:

$reader = new XMLReader(); 
$reader->open($product_xml_link); 

// prepare a document to expand to 
$document = new DOMDocument(); 
// and an xpath instance to use 
$xpath = new DOMXpath($document); 

// find the first product node 
while ($reader->read() && $reader->localName !== 'product') { 
    continue; 
} 

while ($reader->localName === 'product') { 
    $product = $reader->expand($document); 
    $data = [ 
    'id' => $xpath->evaluate('string(id)', $product), 
    'name' => $xpath->evaluate('string(name)', $product), 
    'category_id' => $xpath->evaluate('string(category/@id)', $product), 
    // ... 
    ]; 
    var_dump($data); 
    // move to the next product sibling 
    $reader->next('product'); 
} 
$reader->close(); 
+0

您好, 謝謝您的回答..請問是否有任何更簡單的方法,沒有任何陣列? 我的代碼是這樣的,是否有可能獲得該ID?沒有 $ document = new DOMDocument(); //使用xpath實例 $ xpath = new DOMXpath($ document);或什麼? –

+0

該數組只是一種收集讀取數據的方法。使用變量,調用函數,...以及,您可以使用我的FluentDOM庫。它擴展了XMLReader/DOM並摘錄了一些內容:https://github.com/FluentDOM/FluentDOM/blob/master/examples/XMLReader/sitemap.php :-) – ThW

+0

我保持我的解決方案的狀態,並對其進行了一些更改告訴關於: $ document = ... $ xpath =。 。 。我刪除了代碼行: 我刪除了代碼行: $ product = new SimpleXMLElement($ reader-> readOuterXml()); 並將您的所有數據都轉換爲數組。 現在,我看到解析XML有點慢...... XML有5.500個產品(不是很多)。 在進行任何更改之前,XML相對更快一些。有什麼建議嗎? –

0

你想循環所有的產品,並提取子元素id,namelinkprice的文字內容?可以像做:

foreach((@DOMDocument::loadHTML($xml))->getElementsByTagName("product") as $product){ 
    $vars=array('id','name','link','price'); 
    foreach($vars as $v){ 
     ${$v}=$product->getElementsByTagName($v)->item(0)->textContent; 
    } 
    unset($v,$vars); 
    //now you have $id , $name , $link , $price as raw text, and $product is the DOMNode for the <product> tag. 
} 

,如果你只想進程ID 600,添加未設置後if($id!=600){continue;}(); - 如果你想保存一些CPU,你也應該插入一個break;在這種情況下,在foreach循環結束時。 (然後它會停止循環,一旦發現ID 600)

編輯:固定打破錯字一個代碼,該代碼沒有錯字行不通修復

編輯:如果你想使用XPath找到正確的元素,這將會是$product=(new DOMXpath((@DOMDOcument::loadHTML($xml))))->query('//product/id[text()=\'600\']')->item(0)->parentNode;

編輯:固定另一個密碼破譯錯字(items(0) - >item(0)