2015-03-08 2 views
1

У меня есть файл XML со следующим:Итерация через XML файл с PHP

<property> 
    <id>1</id> 
    <type>type</type> 
    <town>town</town> 
    <province>province</province> 
    <images> 
    <image id="1"> 
    <url> 
     http://www.test.com 
    </url> 
    <image id="2"> 
    <url> 
     http://www.test.com 
    </url> 
    <image id="3"> 
    <url> 
     http://www.test.com 
    </url> 
    </image> 

Я могу перебирать файл и получить значение, кроме URL изображения. Я борюсь с элементом после элемента с атрибутом.

$count=0; 
$id=0; 
foreach($xml->children() as $properties) { 
    echo "<h1>" . $xml->property[$count]->type . " for sale in " .$xml->property[$count]->town . ", " . $xml->property[$count]->province . "</h1>" . "<br>"; 
    echo $xml->property[$count]->id . "<br>"; 
    echo $xml->property[$count]->desc->en . "<br>"; 

    foreach($xml->property[$count]->children() as $images) { 
     echo $xml->property[$count]->images -> image[$id++] -> url; 
     $id++; 
} 
    $count++; 
} 

, но вторая петля не близка к правильной. Буду признателен за помощь.

+2

Что конечный результат вас хотеть? –

+0

мои извинения, это поможет! Я хочу отображать каждое изображение. Мне просто нужен код, который возвращает значение для изображений -> image [id ..] -> url. – sharon

+0

Я не знаю правильной терминологии xml, но каждый элемент содержит элемент с под элементом и который как элемент . Я хочу URL-адрес каждого изображения. HTTP: // HTTP: // http: // sharon

ответ

0

Вы не разделили всю структуру 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); 

Более родственные транслитерации вопросы:

+0

большое спасибо это работает. Я попытался добавить комментарий, но не смог. Я также попытался отметить это как правильно. – sharon

+0

Кодирующая часть мне сложна. Вы знаете, как я могу изменить специальные символы, такие как ó и á как «o» и «a», или, если нет, по крайней мере, их правильно отобразить. $ output = "property_for_sale_in_". $ Собственность-> город. «_». $ Собственность-> провинция "_" граф $... "HTML."; Я пробовал с различными методами, включая заголовки, и не преуспел. – sharon

+0

Мне удалось отобразить как - используя charset = ISO-8859-1, но не удается отформатировать - как o. – sharon

0

Нечто подобное возможно:

foreach($xml->property[$count]->images as $image) { 
    echo $image->url; 
}