这里有两种观点来解决这个问题。一种是迭代所有city 元素并找到它之前的country 兄弟。
$data = new SimpleXMLElement($xml);
$cities = [];
foreach ($data->xpath('//city') as $city) {
$country = (string)($city->xpath('preceding-sibling::country')[0] ?? '');
$cities[] = $city.', '.$country;
}
var_dump($cities);
另一种方法是同时迭代所有 country 和 city 元素并存储当前的 country。
$data = new SimpleXMLElement($xml);
$country = '';
$cities = [];
foreach ($data->xpath('//*[self::country or self::city]') as $node) {
if ($node->getName() == 'country') {
$country = (string)$node;
} else {
$cities[] = $node.', '.$country;
}
}
var_dump($cities);
这将避免为每个 city 元素执行第二个 Xpath 表达式。
对于 DOM 用户来说,这看起来并没有太大的不同。首先使用二级表达式:
$document = new DOMDocument();
$document->loadXML($xml);
$xpath = new DOMXpath($document);
$cities = [];
foreach ($xpath->evaluate('//city') as $city) {
$country = $xpath->evaluate('string(preceding-sibling::country)', $city);
$cities[] = $city->textContent.', '.$country;
}
var_dump($cities);
存储当前国家:
$document = new DOMDocument();
$document->loadXML($xml);
$xpath = new DOMXpath($document);
$country = '';
$cities = [];
foreach ($xpath->evaluate('//*[self::country or self::city]') as $node) {
if ($node->localName == 'country') {
$country = $node->textContent;
} else {
$cities[] = $node->textContent.', '.$country;
}
}
var_dump($cities);