Вы не разделили всю структуру XML, так что неясно, где корень документа является (элемент документа).
Предполагая, что корневой элемент не <property>
но все <property>
элементов являются потомками корневого элемента вы можете перебрать все эти <property>
элементов просто просто итерация над ними:
$xml = simplexml_load_file('example.xml');
foreach ($xml->property as $property) {
printf(
"<h1>%s for sale in %s, %s</h1>\n", htmlspecialchars($property->id),
htmlspecialchars($property->town), htmlspecialchars($property->province)
);
Как вы можете видеть, вы не нужно явно использовать переменную $count
. Вы можете, но вам это не нужно. Просто говорю.
Теперь вы ищете URL-адреса изображений. Каждый <property>
элемента имеет один дочерний элемент с именем <images>
и они опять Mulitple <url>
элементов вы заинтересованы в
Это можно сделать с помощью запроса XPATH (как вы идете вниз глубже более чем на один уровень):.
$urls = $property->xpath('images/image/url');
foreach ($urls as $url) {
printf(" - %s\n", htmlspecialchars(trim($url)));
}
Если вы не используете xpath здесь, вам понадобится сделать foreach для каждого уровня, который содержит больше одного ребенка. Как встречный пример:
foreach ($property->images->image as $image) {
foreach ($image->url as $url) {
printf(" - %s\n", htmlspecialchars(trim($url)));
}
}
Надеюсь, это покажет вам, как обход работает в simplexml. В руководстве по PHP есть еще один замечательный материал: Basic SimpleXML usage, который показывает базовый обход, а также ссылки на более продвинутую тему xpath.
И не забывайте, когда вы отправляете динамические данные в HTML, чтобы правильно закодировать HTML-код. Я использовал функцию htmlspecialchars
для этого, вам нужно предоставить правильные параметры кодирования, которые я оставил для краткости в своем ответе.
Пример в полном объеме:
<?php
/**
* @link https://stackoverflow.com/questions/28929239/iterating-through-xml-file-with-php
*/
$buffer = <<<XML
<root>
<property>
<id>1</id>
<type>type</type>
<town>town</town>
<province>province</province>
<images>
<image id="1">
<url>
http://www.test.com
</url>
</image>
<image id="2">
<url>
http://www.test.com
</url>
</image>
<image id="3">
<url>
http://www.test.com
</url>
</image>
</images>
</property>
<property>
<id>1</id>
<images>
<image id="1">
<url>
http://www.test.com
</url>
</image>
</images>
</property>
</root>
XML;
$xml = simplexml_load_string($buffer);
foreach ($xml->property as $property) {
printf(
"<h1>%s for sale in %s, %s</h1>\n",
htmlspecialchars($property->id), htmlspecialchars($property->town), htmlspecialchars($property->province)
);
$urls = $property->xpath('images/image/url');
foreach ($urls as $url) {
printf(" - %s\n", htmlspecialchars(trim($url)));
}
}
Примерный выход (обычный текст):
<h1>1 for sale in town, province</h1>
- http://www.test.com
- http://www.test.com
- http://www.test.com
<h1>1 for sale in , </h1>
- http://www.test.com
транслитерации и выход Кодирование с SimpleXML
Один из способов глобально применять транслитерации (удаление акцентов) и HTML-кодирование (htmlspecialchars
) для каждого строкового значения SimpleXMLElement может быть достигнуто расширяя его.Существует shortcomming: a SimpleXMLElement не может иметь приватные свойства (потому что свойства все волшебные), однако вы можете создавать статические глобальные переменные. Для хранения экземпляра Transliterator этого достаточно. И для манипулирования строковых значений, то __toString()
magic method хорошо работает с SimpleXMLElement:
/**
* Transliterate and HTML encode
*
* Class XMLTransliterated
*/
class XMLTransliterated extends SimpleXMLElement
{
public static $transliterator;
public function __toString()
{
$transliterator = &self::$transliterator;
$transliterator || $transliterator = Transliterator::create("Latin-ASCII");
$transliterated = $transliterator->transliterate($this);
return htmlspecialchars(trim($transliterated), ENT_QUOTES | ENT_HTML5, 'UTF-8');
}
}
Все, что вам нужно сделать, чтобы извлечь выгоду из строковых манипуляций либо использовать это имя класса XMLTransliterated
(или в зависимости от того вы назвали бы класс) при создании SimpleXMLElement:
$xml = simplexml_load_string($buffer, 'XMLTransliterated');
- или - и это очень особенное SimpleXML, вы можете изменить класс позже с небольшим трюком преобразования:
$xml = simplexml_import_dom(dom_import_simplexml($xml), 'XMLTransliterated');
Это позволит сделать следующее использование кода с XMLTransliterated вместо прежнего менее специфичного SimpleXMLElement поэтому код в основном остается тем же самым (обратите внимание, что htmlspecialchars
и trim
звонки могут быть безопасно удалены, как сейчас автоматически вызывается при доступе строковых значений из SimpleXMLElement):
$xml = simplexml_load_string($buffer, 'XMLTransliterated');
foreach ($xml->property as $property) {
printf(
"<h1>%s (%s) for sale in %s, %s</h1>\n",
$property->id, $property->type, $property->town, $property->province
);
$urls = $property->xpath('images/image/url');
foreach ($urls as $url) {
printf(" - %s\n", $url);
}
}
Но выход получится «Schloß
» в "schloss
"," tôwn
"в" town
"и" provincé
"в" province
".
Для переводчика требуется PHP 5.4, и у вас включен Intl extension (который вы должны иметь, если его не включить).
В качестве альтернативы вы также можете использовать transliteration from the iconv library. Но будьте осторожны, это приводит к несколько иной вывод:
$transliterated = iconv('UTF-8', 'ASCII//IGNORE//TRANSLIT', $this);
Более родственные транслитерации вопросы:
Что конечный результат вас хотеть? –
мои извинения, это поможет! Я хочу отображать каждое изображение. Мне просто нужен код, который возвращает значение для изображений -> image [id ..] -> url. –
sharon
Я не знаю правильной терминологии xml, но каждый элемент содержит элемент с под элементом и который как элемент . Я хочу URL-адрес каждого изображения. HTTP: // HTTP: // http: // –
sharon