我有一个包含10条记录的xml,结构为:
<entry>
<title>My Title</title>
<link rel="alternate" type="text/html" href="http://myweb.com/posts/one.html"/>
<published>2014-07-07T00:34:00+00:00</published>
<updated>2014-07-07T00:34:00+00:00</updated>
<id>http://myweb.com/posts/one.html</id>
<author>
<name>Myweb.com</name>
</author>
<content>
Some Content Here
</content>
<link rel="enclosure" href="http://myweb.com/uploads/300px-300px.jpg" type="image/jpeg" length=""/>
</entry>
我正在使用下面的代码解析它,它几乎工作得很好,除了我无法获取重复行中的图像网址:
<link rel="enclosure" href="http://myweb.com/uploads/300px-300px.jpg" type="image/jpeg" length=""/>
我的代码是:
$url = "http://myweb.com/posts.xml";
$xml = simplexml_load_file($url);
foreach($xml->entry as $PRODUCT) {
$my_title = trim($PRODUCT->title);
$url = trim($PRODUCT->id);
$im = (string)$PRODUCT->xPath('//link[@rel="enclosure"]');
echo $my_title . " " . $url . " " . $im;
echo "<br>";
}
这:$im = (string)$PRODUCT->xPath('//link[@rel="enclosure"]');
返回&#34;数组&#34;而不是网址inisde href。
由于
答案 0 :(得分:2)
这:
$im = (string)$PRODUCT->xPath('//link[@rel="enclosure"]');
返回“Array”而不是url inisde href。
每当你在PHP中看到一个包含单词“Array”的字符串时,你需要别的东西,你需要想一下“嗯,我好像把一个数组转换为一个字符串,这是怎么发生的?” (同样,如果您意外地看到字符串“A”,请考虑它是“Array”的单字母子字符串的可能性。)
在这种情况下,原因很简单:如果你查找the manual page for the SimpleXMLElement::xpath()
method,你会看到它返回一个数组,除非有错误(找不到匹配不是错误,并且会给你一个空数组。)
这是令人惊讶的唯一原因是,大多数methods on that class返回同一个类的另一个实例,对于像(string)
强制转换这样的事情具有魔术重载。然而,所有这些对象表示XML文档的或多或少的连贯片段(例如,一个或多个连续节点,或由特定标签名称过滤的兄弟姐妹),并且永远不能表示“无”。 XPath结果可能为空,或者包含来自整个文档的各种类型的节点;我不确定,但我怀疑这就是为什么在这里选择数组返回而不是另一种SimpleXMLElement
对象的原因。
因此,$PRODUCT->xPath('//link[@rel="enclosure"]')[0]
将为您提供第一个结果(如果您不能依赖至少PHP 5.4,或者想要在没有匹配的节点之间插入检查,那么$xpath_results = $PRODUCT->xPath('//link[@rel="enclosure"]'); $im = $xpath_results[0]
。< / p>
但这里有一些额外的捕获量:
$product->registerXpathNamespace('atom', 'http://www.w3.org/2005/Atom');
然后在您的XPath表达式中使用它(例如//atom:link
而不是//link
)。href
属性:更改您的XPath表达式以选择它(//link[@rel="enclosure"]/@href
)或更改您从SimpleXMLElement
返回的抓取它的访问权限( $xpath_results[0]['href']
)。坚持下去(并摆脱那个丑陋和不寻常的全帽变量名称),紧凑版本(没有错误检查,最低可读性)将是:
$product->registerXpathNamespace('atom', 'http://www.w3.org/2005/Atom');
(string)$product->xPath('//atom:link[@rel="enclosure"]')[0]['href']
或
$product->registerXpathNamespace('atom', 'http://www.w3.org/2005/Atom');
(string)$product->xPath('//atom:link[@rel="enclosure"]/@href')[0]
答案 1 :(得分:1)
看起来它是Atom提要的一部分。这意味着它有一个命名空间。要在具有命名空间的XML上使用Xpath,您必须在命名空间中注册别名/前缀。这与SimpleXML有点复杂,你必须在每个元素上执行它,你正在调用xpath()方法,它将始终返回一个SimpleXMLElement对象数组。
$feed = simplexml_load_string($xml);
foreach($feed->entry as $product) {
$product->registerXpathNamespace('atom', 'http://www.w3.org/2005/Atom');
var_dump((string)$product->xpath('//atom:link[@rel="enclosure"]')[0]['href']);
}
使用DOMXpath这更容易,命名空间只需要在DOMXpath对象上注册一次,DOMXpath :: evaluate()可以返回标量值。第二个参数是Xpath表达式的上下文:
$dom = new DOMDocument();
$dom->loadXml($xml);
$xpath = new DOMXpath($dom);
$xpath->registerNamespace('atom', 'http://www.w3.org/2005/Atom');
foreach($xpath->evaluate('//atom:entry') as $product) {
var_dump($xpath->evaluate('string(atom:link[@rel="enclosure"]/@href)', $product));
}