Разобрать атрибут xml в зависимости от дочернего содержимого

Я загружаю внешний xml-файл, содержащий пользовательские метаданные, которые выглядят следующим образом:

<?xml version="1.0" encoding="utf-8"?>
<user_information>
<user url="http://usersweb.com">
<name>Arnold</name>
<lastname>
<name>Arnoldson</name>
</lastname>
<age>42</age>
</user>
<user url="http://anotheruserweb.com">
<name>Arnold</name>
<lastname>
<name>Arichson</name>
</lastname>
<age>42</age>
</user>
And so on....
</user_information>

Я знаю форматирование с помощью

<lastname> 

действительно глупо, но я не могу изменить источник.

Я хочу загрузить атрибут "url" из

<user>

, но только если

<name> 

и

<lastname> 

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

Я знаю, как распарсить остальную часть с помощью PHP, но только совпадающая последовательность кажется мне сложной. Любая помощь приветствуется!


EDIT: Поскольку я не могу предоставить вам исходный XML, я нашел аналогичную структуру кода в API метаданных Spotify. Мы можем поработать с возвращаемым XML-файлом из поиска по треку "Танец домино": ws.spotify.com/search/1/track?q=Domino Dancing

Он имеет точно такую ​​же структуру, за исключением того, что в нем используются другие слова. Возвращаемый файл выглядит так:

<?xml version="1.0" encoding="utf-8"?> 
<tracks xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/" xmlns="http://www.spotify.com/ns/music/1"> 
<opensearch:Query role="request" startPage="1" searchTerms="Domino Dancing"/> 
<opensearch:totalResults>39</opensearch:totalResults> 
<opensearch:startIndex>0</opensearch:startIndex> 
<opensearch:itemsPerPage>100</opensearch:itemsPerPage> 
<track href="spotify:track:2aV5vCNH5tOOe0GGKqfx5Z"> 
<name>Domino dancing</name> 
<artist href="spotify:artist:2ycnb8Er79LoH2AsR5ldjh"> 
<name>Pet Shop Boys</name> 
</artist> 
<id type="isrc">GBAYE0301704</id> 
<album href="spotify:album:0BAfuhzkGjckMhsL2gVbzR"> 
<name>Ultimate</name> 
<released>2010</released> 
<availability> 
<territories>AT BE CH CY CZ DE DK EE ES FI FR GB GR HR HU IE IT LT LU NL NO PL PT RO SE SI SK</territories> 
</availability> 
</album> 
<track-number>7</track-number> 
<length>258.106000</length> 
<popularity>0.57092</popularity> 
</track> 
<track href="spotify:track:4mVLzFbc3gaCoWCEENLouc"> 
<name>Domino Dancing</name> 
<artist href="spotify:artist:2ycnb8Er79LoH2AsR5ldjh"> 
<name>Pet Shop Boys</name> 
</artist> 
<id type="isrc">GBAYE8800056</id> 
<album href="spotify:album:0Jt2LzWgtGxy3GZH5i2Kcy"> 
<name>Discography - Complete Singles Collection</name> 
<released>1991</released> 
<availability> 
<territories>AT BE CH CY CZ DE DK EE ES FI FR GB GR HR HU IE IT LT LU NL NO PL PT RO SE SI SK</territories> 
</availability> 
</album> 
<track-number>10</track-number> 
<length>258.333000</length> 
<popularity>0.56159</popularity> 
</track> 
<track href="spotify:track:72kgJ1brMxxeDiPNdH6qqW"> 
<name>Viva la vida/Domino dancing</name> 
<artist href="spotify:artist:2ycnb8Er79LoH2AsR5ldjh"> 
<name>Pet Shop Boys</name> 
</artist> 
<id type="isrc">GBCEW0900049</id> 
<album href="spotify:album:4DZfMTDyBwnJQ0k1PaT6U4"> 
<name>Pet Shop Boys Christmas</name> 
<released>2009</released> 
<availability> 
<territories>AT BE CH CY CZ DE DK EE ES FI FR GB GR HR HU IE IT LT LU NL NO PL PT RO SE SI SK</territories> 
</availability> 
</album> 
<track-number>4</track-number> 
<length>333.507000</length> 
<popularity>0.51961</popularity> 
</track>
</tracks>

Если мы притворимся, что user_information=tracks user=track url=href lastname=artist.

Надеюсь это поможет!

EDIT2: я решил это, используя документ Xpath и пространства имен. Всем спасибо за попытку!


person Eddie Fernberg    schedule 31.12.2010    source источник


Ответы (2)


Этот XPATH выбирает @url для Арнольда Арчисона:

/user_information/user[name='Arnold' and lastname/name='Arichson']/@url

ИЗМЕНИТЬ

Два вопроса о вашем решении: 1. Могу ли я использовать xpath с simplexml_load_file вместо simplexmlelement? 2. Могу ли я заменить значения Arnold Arichson на переменную типа $users_firstname и $users_lastname=

Я не специалист по PHP, но я считаю, что вы должны быть в состоянии сделать что-то подобное (вам может потребоваться по-разному объединить строку XPATH или, возможно, не нужно экранировать одинарные кавычки, не уверен):

<?php

$first = "Arnold";
$last = "Arichson";

$userInfo =  simplexml_load_file('http://your.website.com/user_information.xml');

foreach ($userInfo->xpath("/user_information/user[name=\'$first\' and lastname/name=\'$last\']/@url") as $url) {
  echo "<h2>" . $url . "</h2>";
}
?>
person Mads Hansen    schedule 31.12.2010
comment
Два вопроса о вашем решении: 1. Могу ли я использовать xpath с simplexml_load_file вместо simplexmlelement? 2. Могу ли я заменить значения Arnold Arichson на переменную типа $users_firstname и $users_lastname= - person Eddie Fernberg; 02.01.2011
comment
Я так думаю. Я обновил свой ответ, используя код из этой статьи в качестве шаблона: ibm.com/developerworks/library/x-simplexml.html#N10228 - person Mads Hansen; 03.01.2011
comment
Когда я пробую это решение, сервер выдает мне предупреждение: недопустимый аргумент для foreach(). Я что-то не так? Просто скопипастил. - person Eddie Fernberg; 05.01.2011
comment
Я не тестировал код, просто взял его из статьи. Мне может не понравиться, как я пытался избежать одинарных кавычек в XPATH. Вам может понадобиться соединить строку XPATH следующим образом: foreach ($userInfo->xpath("/user_information/user[name='" . $first . "' and lastname/name='" . $last . "']/@url") as $url) - person Mads Hansen; 05.01.2011
comment
Я все еще получаю вышеуказанную ошибку. Принимает ли xpath, что вы включаете переменные в синтаксис? - person Eddie Fernberg; 05.01.2011

$xml = new SimpleXMLElement($xml_string);
foreach ($xml->user as $value) {
   if ($value->name == $x && $value->lastname->name == $y) {
      $attr = $value->attributes();
      echo $attr['url'];
   }
}

Это загрузит строку xml в простой объект xml, затем сравнит значения узлов, и если они соответствуют желаемому имени ($x и $y), напечатайте URL-адрес. Вы также можете загрузить XML-файл вместо строки, чтобы создать объект simplexml, если это необходимо. см. simplexml документацию для получения дополнительной информации.

ДОБАВЛЕНИЕ

Использование строки (проверено и работает):

<?php
    $xml_input = <<<XML
<user_information> <user url="http://usersweb.com"> <name>Arnold</name> <lastname> <name>Arnoldson</name> </lastname> <age>42</age> </user> <user url="http://anotheruserweb.com"> <name>Arnold</name> <lastname> <name>Arichson</name> </lastname> <age>42</age> </user></user_information>
XML;

$xml = new SimpleXMLElement($xml_input); 
foreach ($xml->user as $value) {
    if ($value->name == 'Arnold' && $value->lastname->name == 'Arnoldson') {
        $attr = $value->attributes();
        echo $attr['url'];
    }
} 
?>

Использование файла (должно работать точно так же):

<?php
    $xml = new SimpleXMLElement($xml_file_path, 0, true); 
    foreach ($xml->user as $value) {
        if ($value->name == 'Arnold' && $value->lastname->name == 'Arnoldson') {
            $attr = $value->attributes();
            echo $attr['url'];
        }
    } 
?>

В конструкцию объекта я добавил аргументы 0 и true, что позволяет использовать путь к файлу в качестве первого аргумента вместо строки. Но да, вы также можете использовать функцию загрузки файла.

person dqhendricks    schedule 31.12.2010
comment
Кажется, это хорошее решение, но могу ли я использовать его с simplexml_load_file? Я не знаком с симплексным элементом. Потому что у меня не получилось... - person Eddie Fernberg; 02.01.2011
comment
отредактировано выше, чтобы показать больше примера кода (рабочий пример для строки и для пути к файлу). - person dqhendricks; 02.01.2011
comment
если это решение работает для вас, установите флажок рядом с моим ответом. Спасибо! - person dqhendricks; 02.01.2011
comment
Извините, но я не мог сделать эту работу. Я делаю что-то неправильно? Просто копипаст. - person Eddie Fernberg; 05.01.2011
comment
я имею в виду, вам нужно будет установить $xml_file_path равным любому фактическому пути к файлу xml файла... и вам нужно будет убедиться, что все пути узлов верны... вы не можете просто скопировать-вставить.. , вам придется попытаться понять, что вы делаете. - person dqhendricks; 05.01.2011
comment
Хорошо, плохое описание от меня! Конечно, я указал путь к моему фактическому файлу. - person Eddie Fernberg; 05.01.2011
comment
что происходит? есть ли ошибка? что происходит, когда вы отбрасываете $xml после его создания? Вы можете оставить ссылку на фактический xml-файл, который вы используете? - person dqhendricks; 05.01.2011
comment
возвращает ли simplexml_load_file($filepath) false? - person dqhendricks; 06.01.2011