问题
I am looping through a XML file with SimpleXML and trying to pull a specific piece of data (specifically, the series->displayname attribute) from the Previous and Next nodes each time.
Here is a sample of the XML structure:
<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>
And here is a sample of the structure I am using in the loop:
$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>';
However, the 'nextIssue' and 'prevIssue' variables are not working. They are returning a blank result. What am I doing wrong?
Any guidance is greatly appreciated.
回答1:
Try the below code
$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 ...
[Edited]
The others have already explained why the code did not work
One is that the xpath()
method returns an array of SimpleXMLElement objects. If no matching node is found, an empty array is returned.
The other is that without the predicate [1]
or [position()=1]
in the location path, all the preceding or succeeding comic
nodes would be returned.
Alternatively you can use the location path 'following-sibling::comic[1]/mainsection/series'
to get just the required series
node from the immediate succeeding sibling. If there were multiple series
nodes, the position would have to be given or all of them would be returned.
So using this location path
$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 : '';
回答2:
The problem is here:
preceding-sibling::*
Selects all preceding sibling elements.
following-sibling::*
Selects all following sibling elements.
You want just one -- the direct preceding sibling or the direct following sibling -- respectively:
preceding-sibling::*[1]
and:
following-sibling::*[1]
回答3:
Part of the problem, as touched on by other answers but not explicitly explained, is that unlike most operations on SimpleXML objects, ->xpath()
returns an array, not another SimpleXML object. (This is presumably to avoid having a SimpleXML object that could contain completely unrelated nodes from throughout the document.)
Thus this line will fail, because you are treating an array as an object:
$prevIssue = $comic->xpath('preceding-sibling::*')->mainsection->series->displayname;
In PHP 5.4, the following is valid syntax (indexing into the array immediately after it is returned):
$prevIssue = $comic->xpath('preceding-sibling::*')[0]->mainsection->series->displayname;
But for earlier versions of PHP, or if the XPath might sometimes return 0 results, you need an intermediate variable:
$prevSiblings = $comic->xpath('preceding-sibling::*');
$prevIssue = (
( count($prevSiblings) > 0 )
? $prevSiblings[0]->mainsection->series->displayname
: NULL
);
来源:https://stackoverflow.com/questions/12659004/grabbing-a-specific-part-of-the-previous-next-nodes