我在访问XML中的属性时遇到了一些麻烦。我的代码如下。最初我有两个循环,这没有问题。
我首先会获取图像名称,然后使用第二个循环来获取故事标题和故事详细信息。然后将所有内容插入数据库。我想整理代码并只使用一个循环。我的图像名称存储在Href属性中。 ()
示例XML布局(http://pastie.org/1850682)。 XML布局有点乱,所以这就是使用两个循环的原因。
$xml = new SimpleXMLElement('entertainment/Showbiz.xml', null, true);
// Get story images
//$i=0;
//$image = $xml->xpath('NewsItem/NewsComponent/NewsComponent/NewsComponent/NewsComponent/NewsComponent/ContentItem');
// foreach($image as $imageNode){
// $attributeArray = $imageNode->attributes();
// if ($attributeArray != ""){
// $imageArray[$i] = $attributeArray;
// $i++;
// }
//}
// Get story header & detail
$i=0;
$story = $xml->xpath('NewsItem/NewsComponent/NewsComponent/NewsComponent');
foreach($story as $contentItem){
//$dbImage = $imageArray[$i]['Href'];
foreach($contentItem->xpath('ContentItem/DataContent/nitf/body/body.head/hedline/hl1') as $headline){
$strDetail = "";
foreach($contentItem->xpath('ContentItem/DataContent/nitf/body/body.content/p') as $detail){
$strDetail .= '<p>'.$detail.'</p>';
foreach($contentItem->xpath('NewsComponent/NewsComponent/ContentItem') as $imageNode){
$dbImage = $imageNode->attributes();
}
}
$link = getUnique($headline);
$sql = "INSERT INTO tablename (headline, detail, image, link) VALUES ('".mysql_real_escape_string($headline)."', '".mysql_real_escape_string($strDetail)."', '".mysql_real_escape_string($dbImage)."', '".$link."')";
if (mysql_query($sql, $db) or die(mysql_error())){
echo "Loaded ";
}else{
echo "Not Loaded ";
}
}
$i++;
}
我想我已经接近了。我尝试在第四个嵌套的foreach循环中放入一些echo语句,但没有任何结果。所以它没有执行那个循环。我已经在这里待了几个小时并且也用Google搜索,但是无法得到它。
如果所有其他方法都失败了,我会回到使用两个循环。
此致 斯蒂芬
答案 0 :(得分:2)
这很难理解。我简化了结构,因此我们可以看到我们关心的层次结构部分。
具有 Duid 属性的NewsComponent似乎是定义/包含一个完整新闻片段的内容。在它的两个子节点中,第一个子节点NewsComponent包含摘要和文本,而第二个子节点NewsComponent包含图像。
您的初始XPath查询是针对'NewsItem/NewsComponent/NewsComponent/NewsComponent'
的,这是第一个NewsComponent子级(具有正文文本的子级)。您无法从该点找到图像,因为图像不在该NewsComponent中;你已经走得太深了一层。 (我得到了一个PHP 通知:未定义的变量:dbImage 。)因此,将初始XPath查询放回一个级别,并在需要的时候将额外的级别添加到后续的XPath查询中
由此:
$story = $xml->xpath('NewsItem/NewsComponent/NewsComponent/NewsComponent');
foreach($story as $contentItem){
foreach($contentItem->xpath('ContentItem/DataContent/nitf/body/body.head/hedline/hl1') as $headline){
foreach($contentItem->xpath('ContentItem/DataContent/nitf/body/body.content/p') as $detail){
foreach($contentItem->xpath('NewsComponent/NewsComponent/ContentItem') as $imageNode){ /* ... */ }}}}
到此:
$story = $xml->xpath('NewsItem/NewsComponent/NewsComponent');
foreach($story as $contentItem){
foreach($contentItem->xpath('NewsComponent/ContentItem/DataContent/nitf/body/body.head/hedline/hl1') as $headline){
foreach($contentItem->xpath('NewsComponent/ContentItem/DataContent/nitf/body/body.content/p') as $detail){
foreach($contentItem->xpath('NewsComponent/NewsComponent/NewsComponent/ContentItem') as $imageNode){ /* ... */ }}}}
然而,之后图像仍然不起作用。因为您正在使用循环(有时不必要),$dbImage
会被重新分配给空字符串。第一个ContentItem具有 Href 属性,该属性被分配给$dbImage
。但是它循环到下一个没有属性的ContentItem,因此用空值覆盖$dbImage
。我建议修改该XPath查询以仅查找具有 Href 属性的ContentItem,如下所示:
->xpath('NewsComponent/NewsComponent/NewsComponent/ContentItem[@Href]')
应该这样做。
重构以清除此代码,如果/在可能的情况下。
正如我所提到的,有时候你不需要循环和嵌套,它最终会更难以遵循并可能引入逻辑错误(如图像错误)。看来这个文件的结构总是一致的。如果是这样,您可以放弃一些循环并直接查找您正在寻找的数据。你可以这样做:
// Get story header & detail
$stories = $xml->xpath('/NewsML/NewsItem/NewsComponent/NewsComponent');
foreach ($stories as $story) {
$headlineItem = $story->xpath('NewsComponent/ContentItem/DataContent/nitf/body/body.head/hedline/hl1');
$headline = $headlineItem[0];
$detailItems = $story->xpath('NewsComponent/ContentItem/DataContent/nitf/body/body.content/p');
$strDetail = '<p>' . implode('</p><p>', $detailItems) . '</p>';
$imageItem = $story->xpath('NewsComponent/NewsComponent/NewsComponent/ContentItem[@Href]');
$imageAtts = $imageItem[0]->attributes();
$dbImage = $imageAtts['Href'];
$link = getUnique($headline);
$sql = "INSERT INTO tablename (headline, detail, image, link) VALUES ('".mysql_real_escape_string($headline)."', '".mysql_real_escape_string($strDetail)."', '".mysql_real_escape_string($dbImage)."', '".$link."')";
if (mysql_query($sql, $db) or die(mysql_error())) {
echo "Loaded ";
} else {
echo "Not Loaded ";
}
}