Отображение определенных данных из файла XML на основе атрибута в PHP

Я новичок в PHP и XML и застрял в одной конкретной проблеме с xml-каналом. В данных XML есть одно поле «article_content» с уникальным атрибутом (id) для каждой новости. Мне нужно иметь возможность просто отображать эту историю на странице на основе URL-адреса, созданного на странице индекса, которая показывает все истории (пример URL-адреса: путь/к/файлу/newsstory.php?storyid=19837775), где идентификатор истории соответствует идентификатору атрибут в поле содержания статьи.

Может ли кто-нибудь помочь, поскольку я бьюсь головой о стену здесь!


Обновить:

XML в этом формате ниже (Новый article_content для каждой истории)

<channel>
    <article_content id="19837775" status="A">
        <title>title of article 1</title>
        <date>20120127</date>
        <time>10:18:00</time>
        <body>main body of story 1 here</body>
        <introduction>intro text here</introduction>
        <abstract></abstract>
        <by_line></by_line>
        <category_id>0103</category_id>
    </article_content>
    [...]

php-код, который у меня есть:

<?php
$xml = new SimpleXMLElement($rss);
$results = array ();
foreach ($xml->channel->article_content[id] as $item) {
    echo "<h3>".$item->title."</h3>";
    echo nl2br ($item->body->asXML());
}
?>

person Pablo100    schedule 27.01.2012    source источник
comment
Пожалуйста, добавьте XML и код, который у вас есть... SimpleXML, вероятно, путь вперед ....   -  person Manse    schedule 27.01.2012
comment
Формат XML приведен ниже (Новый article_content для каждой статьи) ‹channel› ‹article_content id=19837775 status=A› ‹title›название статьи 1‹/title› ‹date›20120127‹/date› ‹time›10: 18:00‹/время› ‹тело›основная часть истории 1 здесь‹/тело› ‹введение›вступительный текст здесь‹/введение› ‹аннотация›‹/аннотация› ‹по_строке›‹/по_строке› ‹category_id›0103‹/ category_id› ‹/article_content› php-код, который у меня есть: ‹?php $xml = new SimpleXMLElement($rss); $результаты = массив (); foreach ($xml-›channel-›article_content[id] as $item) {echo ‹h3›.$item-›title.‹/h3›; echo nl2br ($item-›body-›asXML()); } ?›   -  person Pablo100    schedule 27.01.2012


Ответы (2)


Без вашего XML я могу показать только этот пример (взято отсюда):

$xmlstr = <<<XML
<?xml version='1.0' standalone='yes'?>
<movies>
 <movie>
  <rating type="thumbs">7</rating>
  <rating type="stars">5</rating>
 </movie>
</movies>
XML;

Чтобы вывести атрибут типа:

$movies = new SimpleXMLElement($xmlstr);
echo $movies->movie[0]->rating[0]['type']

Пример здесь

person Manse    schedule 27.01.2012

Сначала пример того, как это может быть выполнено (используя XPath и расширение php DOM

<?php
$id = '19837775'; // this is the parameter you'd fetch from the url

$doc = new DOMDocument;
//$doc->load('feed.xml');
$doc->loadxml( getData() );

$xpath = new DOMXPath($doc);
foreach ( $xpath->query('story[@article_content="'.$id.'"]') as $story ) {
    echo $doc->savexml($story); 
}


function getData() {
    return <<< eox
<stories>
    <story article_content="1">content 1</story>
    <story article_content="2">content 2</story>
    <story article_content="19837775">content 19837775</story>
    <story article_content="22222222">content 22222222</story>
</stories>  
eox;
}

отпечатки

<story article_content="19837775">content 19837775</story>

....но это не может быть хорошим решением в конце концов. Это зависит от того, чего вы на самом деле пытаетесь достичь (и насколько масштабируемым должно быть решение).
Пожалуйста, уточните.


update: пример использования фактической структуры данных.

<?php
$id = '19837775'; // the parameter fetched from the request

$doc = new DOMDocument;
//$doc->load('feed.xml');
$doc->loadxml( getData() );

$xpath = new DOMXPath($doc);

$article = firstNode( $xpath->query('article_content[@id="'.$id.'"]') );
if ( !$article ) {
    die('no such article');
}

$title = firstNode( $xpath->query('title', $article) );
$date = firstNode( $xpath->query('date', $article) );
$body = firstNode( $xpath->query('body', $article) );

// TODO: check $title, $data and $body

echo 'title: ', $title->nodeValue, "\n";
echo 'date: ', $title->nodeValue, "\n";
echo 'body: ', $doc->savexml($body), "\n";
echo 'body->nodeValue: ', $body->nodeValue;
die;

function firstNode($nodelist) {
    if ( $nodelist instanceof DOMNodeList && 0<$nodelist->length ) {
        return $nodelist->item(0);
    }
    return false;
}

function getData() {
    return <<< eox
<channel>
    <article_content id="1" status="X"></article_content>
    <article_content id="19837775" status="A">
        <title>title of article 1</title><date>20120127</date><time>10:18:00</time>
        <body><h1>main body of story 1</h1><p>Not just plain text</p></body>
        <introduction>intro text here</introduction><abstract></abstract><by_line></by_line><category_id>0103</category_id>
    </article_content>
    <article_content id="20000000" status="X"></article_content>
    <article_content id="20000001" status="X"></article_content>
</channel>
eox;
}

отпечатки

title: title of article 1
date: title of article 1
body: <body><h1>main body of story 1</h1><p>Not just plain text</p></body>
body->nodeValue: main body of story 1Not just plain text

Вас также может заинтересовать https://en.wikipedia.org/wiki/XSLTXSL, который также использует XPath для выбора узлов, но позволяет преобразовать вывод (например, из вашего представления xml в удобный для пользователя формат html).

person VolkerK    schedule 27.01.2012
comment
Извините, что не сделал это слишком ясным (я новичок в этом!) У узла article_content есть дочерние узлы под ним, поэтому я пытаюсь выбрать только узел содержимого статьи (и дочерние элементы), где атрибут id взят из URL-адреса, чтобы я мог отображать содержимое различных узлов под этим (имеет ли это смысл?) - person Pablo100; 27.01.2012
comment
Да, и пример делает это...более или менее. Переменная $story — это элемент истории, который вы ищете (это дескриптор/ссылка на DOM-представление этого элемента DOME). т.е. вы можете получить доступ к дочернему узлу оттуда. Но есть некоторые проблемы, особенно. относительно масштабируемости. Загрузка данных xml требует времени. И помещение его в объект DOM также требует времени. Если ваше приложение должно быть масштабируемым, вы должны рассмотреть действительно хороший механизм кэширования. Или выбрал другой формат хранения. Или используйте систему баз данных на основе xml/document. Или смесь всего вышеперечисленного. - person VolkerK; 27.01.2012
comment
Спасибо за это, я думал, что подача XML в базу данных будет лучшим вариантом! - person Pablo100; 27.01.2012
comment
Теперь я потерялся, я пробовал это и получаю следующую ошибку: Ошибка синтаксического анализа: синтаксическая ошибка, неожиданный конец $, ожидание T_VARIABLE или T_END_HEREDOC или T_DOLLAR_OPEN_CURLY_BRACES или T_CURLY_OPEN в C:\xampp\htdocs\testfeed\newsflow\newsstory. php в строке 66 - person Pablo100; 27.01.2012
comment
Странно... так как демо-скрипт даже не имеет 66 строк ;-) Если вы используете функцию getData(), убедитесь, что перед eox; нет символов (даже пробелов) и никаких символов, кроме разрыва строки/каретки. - вернуться после него. см. docs.php.net /ручной/de/ - person VolkerK; 27.01.2012
comment
Перед сценарием есть несколько дополнительных строк кода, которые извлекают файл xml для хранения и получают значение идентификатора из URL-адреса $cache_time = 180; $cache_file = 'кэш/newsflow.xml'; $timedif = @(time() - filemtime($cache_file)); if (file_exists($cache_file) && $timedif ‹ $cache_time) { $string = file_get_contents($cache_file); } else { $string = file_get_contents(расположение файла xml) if ($f = @fopen($cache_file, 'w')) { fwrite ($f, $string, strlen($string)); fclose($f); }} if (isset($_GET[storyid])) { $id = intval($_GET[storyid]);} $rss = simplexml_load_file('cache/newsflow.xml'); - person Pablo100; 27.01.2012