use*_*327 2 php xml xmlreader simplexml
我正在尝试从[此URL(加载相当长的时间)] [1]中获取以下节点的值。我感兴趣的元素是:
title, g:price and g:gtin
Run Code Online (Sandbox Code Playgroud)
XML开始如下:
<rss xmlns:g="http://base.google.com/ns/1.0" version="2.0">
<channel>
<title>PhotoSpecialist.de</title>
<link>http://www.photospecialist.de</link>
<description/>
<item>
<g:id>BEN107C</g:id>
<title>Benbo Trekker Mk3 + Kugelkopf + Tasche</title>
<description>
Benbo Trekker Mk3 + Kugelkopf + Tasche Das Benbo Trekker Mk3 ist eine leichte Variante des beliebten Benbo 1. Sein geringes Gewicht macht das Trekker Mk3 zum idealen Stativ, wenn Sie viel draußen fotografieren und viel unterwegs sind. Sollten Sie in eine Situation kommen, in der maximale Stabilität zählt, verfügt das Benbo Trekker Mk3 über einen Haken an der Mittelsäule. An diesem können Sie das Stativ mit zusätzlichem Gewicht bei Bedarf beschweren. Dank der zwei besonderen Kamera-Befestigungsschrauben können Sie mit dem Benbo Trekker Mk3 sehr nah am Boden fotografieren. So nah, dass in vielen Fällen die einzige Einschränkung die Größe Ihrer Kamera darstellt. In diesem Set erhalten Sie das Benbo Trekker Mk3 zusammen mit einem Kugelkopf, Socket und einer Tasche für den sicheren und komfortablen Transport.
</description>
<link>
http://www.photospecialist.de/benbo-trekker-mk3-kugelkopf-tasche?dfw_tracker=2469-16
</link>
<g:image_link>http://static.fotokonijnenberg.nl/media/catalog/product/b/e/benbo_trekker_mk3_tripod_kit_with_b__s_head__bag_ben107c1.jpg</g:image_link>
<g:price>199.00 EUR</g:price>
<g:condition>new</g:condition>
<g:availability>in stock</g:availability>
<g:identifier_exists>TRUE</g:identifier_exists>
<g:brand>Benbo</g:brand>
<g:gtin>5022361100576</g:gtin>
<g:item_group_id>0</g:item_group_id>
<g:product_type>Tripod</g:product_type>
<g:mpn/>
<g:google_product_category>Kameras & Optik</g:google_product_category>
</item>
...
</channel>
</rss>
Run Code Online (Sandbox Code Playgroud)
为此,我编写了以下代码:
$z = new XMLReader;
$z->open('https://my.datafeedwatch.com/static/files/1248/8222ebd3847fbfdc119abc9ba9d562b2cdb95818.xml');
$doc = new DOMDocument;
while ($z->read() && $z->name !== 'item')
;
while ($z->name === 'item')
{
$node = new SimpleXMLElement($z->readOuterXML());
$a = $node->title;
$b = $node->price;
$c = $node->gtin;
echo $a . $b . $c . "<br />";
$z->next('item');
}
Run Code Online (Sandbox Code Playgroud)
这仅返回标题...价格和gtin未显示。
您要询问的元素不是默认名称空间的一部分,而是在另一个名称空间中。您会看到这是因为它们的名称中有一个前缀,并用冒号分隔:
...
<channel>
<title>PhotoSpecialist.de</title>
<!-- title is in the default namespace, no colon in the name -->
...
<g:price>199.00 EUR</g:price>
...
<g:gtin>5022361100576</g:gtin>
<!-- price and gtin are in a different namespace, colon in the name and prefixed by "g" -->
...
Run Code Online (Sandbox Code Playgroud)
命名空间带有前缀,此处为“ g”。命名空间代表的前缀在以下文档元素中定义:
<rss xmlns:g="http://base.google.com/ns/1.0" version="2.0">
Run Code Online (Sandbox Code Playgroud)
因此名称空间为“ http://base.google.com/ns/1.0”。
当您像现在一样使用SimpleXMLElement通过子元素的名称访问子元素时:
$a = $node->title;
$b = $node->price;
$c = $node->gtin;
Run Code Online (Sandbox Code Playgroud)
您只在默认名称空间中查找。因此,只有第一个元素实际包含文本,其他两个元素则是即时创建的,但仍为空。
要访问带名称空间的子元素,您需要使用方法显式告知SimpleXMLElementchildren()。它创建一个新的SimpleXMLElement,其中包含该命名空间中的所有子项,而不是默认的子项:
$google = $node->children("http://base.google.com/ns/1.0");
$a = $node->title;
$b = $google->price;
$c = $google->gtin;
Run Code Online (Sandbox Code Playgroud)
对于孤立的示例来说已经足够了(是的,已经足够了)。
这样,一个完整的示例可能看起来像(包括读取器上的节点扩展,您所拥有的代码有些生锈):
<?php
/**
* How to parse an XML node with a colon tag using PHP
*
* @link http://stackoverflow.com/q/29876898/367456
*/
const HTTP_BASE_GOOGLE_COM_NS_1_0 = "http://base.google.com/ns/1.0";
$url = 'https://my.datafeedwatch.com/static/files/1248/8222ebd3847fbfdc119abc9ba9d562b2cdb95818.xml';
$reader = new XMLReader;
$reader->open($url);
$doc = new DOMDocument;
// move to first item element
while (($valid = $reader->read()) && $reader->name !== 'item') ;
while ($valid) {
$default = simplexml_import_dom($reader->expand($doc));
$googleBase = $default->children(HTTP_BASE_GOOGLE_COM_NS_1_0);
printf(
"%s - %s - %s<br />\n"
, htmlspecialchars($default->title)
, htmlspecialchars($googleBase->price)
, htmlspecialchars($googleBase->gtin)
);
// move to next item element
$valid = $reader->next('item');
};
Run Code Online (Sandbox Code Playgroud)
我希望这既可以提供解释,也可以拓宽XMLReader用法的视野。