1

我在访问 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 语句,但没有任何结果。所以它没有执行那个循环。我已经在这工作了几个小时,也用谷歌搜索,只是无法得到它。

如果一切都失败了,我将回到使用两个循环。

问候,斯蒂芬

4

1 回答 1

2

这很难理解。我已经简化了结构,所以我们可以看到我们关心的层次结构的部分。

简化的 XML 层次结构

似乎具有Duid属性的 NewsComponent 定义/包含一个完整的新闻。在它的两个子项中,第一个子 NewsComponent 包含摘要和文本,而第二个子 NewsComponent 包含图像。

您的初始 XPath 查询是 for '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 "; 
    }
}
于 2011-04-30T22:13:01.313 回答