2017-07-19 153 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)