2012-09-30 106 views
0

我通過用SimpleXML一個XML文件進行循環並試圖拉特定數據片的特定部分(具體地,系列 - >顯示名稱屬性)從上一個和下一個節點每次。抓取的一個/下一個節點

下面是XML結構的一個樣本:

<comic> 
     <id>117</id> 
     <index>1</index> 
     <mainsection> 
     <pagecount>33</pagecount> 
     <series> 
      <displayname>Amazing Story</displayname> 
      <sortname>Amazing Story</sortname> 
     </series> 
     </mainsection> 
</comic> 
<comic> 
     <id>102</id> 
     <index>1</index> 
     <mainsection> 
     <pagecount>33</pagecount> 
     <series> 
      <displayname>Fantastic Tale</displayname> 
      <sortname>Fantastic Tale</sortname> 
     </series> 
     </mainsection> 
</comic> 
<comic> 
     <id>85</id> 
     <index>1</index> 
     <mainsection> 
     <pagecount>33</pagecount> 
     <series> 
      <displayname>The Great Tale</displayname> 
      <sortname>The Great Tale</sortname> 
     </series> 
     </mainsection> 
</comic> 

這裏是結構的樣品,我使用的循環:

$prevIssue = $comic->xpath('preceding-sibling::*')->mainsection->series->displayname; 
$nextIssue = $comic->xpath('following-sibling::*')->mainsection->series->displayname; 

echo ' 
<li class="issue" id="' . $seriesCat . '"> 
<h3>' . $comicSeriresName . '</h3> 
    <div id="details"> 
    <span id="publisher">' . $comicPublisher . '</span><br> 
    The last series was called "' . $prevIssue . '<br> 
    The next series is called "' . $nextIssue . '<br> 
    </div> 
</li>'; 

然而,「 nextIssue'和'prevIssue'變量不起作用。他們返回空白結果。我究竟做錯了什麼?

任何指導非常感謝。

回答

2

試試下面的代碼

$prevIssue_arr = $comic->xpath('preceding-sibling::*[1]'); 
$prevIssue = (isset($prevIssue_arr[0])) ? $prevIssue_arr[0]->mainsection->series->displayname : ''; 
$nextIssue_arr = $comic->xpath('following-sibling::*[1]'); 
$nextIssue = (isset($nextIssue_arr[0])) ? $nextIssue_arr[0]->mainsection->series->displayname : ''; 

echo ... 

[編輯]

其他人已經解釋了爲什麼代碼沒有工作

之一是,xpath()方法返回的SimpleXMLElement對象的數組。如果找不到匹配的節點,則返回一個空數組。

另一種情況是,如果位置路徑中沒有謂詞[1][position()=1],則將返回所有之前或之後的comic節點。

或者,您可以使用位置路徑'following-sibling::comic[1]/mainsection/series'從緊接着的後繼兄弟中獲取所需的series節點。如果有多個series節點,則必須給出該位置,否則將返回所有位置。

因此,使用此位置路徑

$prevIssue_arr = $comic->xpath('preceding-sibling::comic[1]/mainsection/series'); 
$prevIssue = (isset($prevIssue_arr[0])) ? $prevIssue_arr[0]->displayname : ''; 
$nextIssue_arr = $comic->xpath('following-sibling::comic[1]/mainsection/series'); 
$nextIssue = (isset($nextIssue_arr[0])) ? $nextIssue_arr[0]->displayname : ''; 
+3

這可能是正確的答案,但如果你解釋了*爲什麼會解決這個問題,那麼答案可以應用於不止一種情況。 – IMSoP

+0

@IMSoP的權利。現在添加一些解釋。 – air4x

+0

這似乎很好。謝謝 :) – Batfan

2

的問題是在這裏:

preceding-sibling::* 

選擇所有兄弟元素前面。

following-sibling::* 

選擇所有以下同級元素。

你想只有一個 - 直接前面的兄弟姐妹或直接下面的兄弟 - 分別

preceding-sibling::*[1] 

:問題的

following-sibling::*[1] 
1

一部分,感動通過其他答案,但沒有明確解釋,是不同於大多數在SimpleXML對象上的操作,->xpath()返回一個數組,而不是另一個SimpleXML對象。 (推測這是爲了避免具有SimpleXML對象可能包含來自整個文件完全無關的節點。)

因此,該線會失敗,因爲你是治療數組作爲對象:

$prevIssue = $comic->xpath('preceding-sibling::*')->mainsection->series->displayname; 

在PHP 5.4,以下是有效的語法(索引到數組則返回後立即):

$prevIssue = $comic->xpath('preceding-sibling::*')[0]->mainsection->series->displayname; 

但對於之前版本的PHP,或者如果XPath有時會返回0的結果,你需要一箇中間變量:

$prevSiblings = $comic->xpath('preceding-sibling::*'); 
$prevIssue = (
    (count($prevSiblings) > 0) 
    ? $prevSiblings[0]->mainsection->series->displayname 
    : NULL 
); 
相關問題