XML获取属性

时间:2017-07-19 09:22:45

标签: php xml xml-attribute

我在这里看到很多教程溢出,但我无法理解我所缺少的东西..所以我需要一些帮助..

我有一个在线的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
}

2 个答案:

答案 0 :(得分: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();

答案 1 :(得分:0)

您想循环所有产品,并提取子元素idnamelinkprice的文字内容?可以这样做:

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,请在unset()之后添加if($id!=600){continue;}; - 如果你想保存一些CPU,你也应该插入一个休息时间;在那种情况下,在foreach循环结束时。 (一旦找到id 600,它就会停止循环)

编辑:修正了破解错误的代码,代码在没有拼写错误修复的情况下无法正常工作

编辑:如果你想使用XPath找到正确的元素,那就是$product=(new DOMXpath((@DOMDOcument::loadHTML($xml))))->query('//product/id[text()=\'600\']')->item(0)->parentNode;

编辑:修正了另一个破译错误的拼写错误(items(0) - &gt; item(0)