Search code examples
phpxmlxpathsimplexml

Getting an XML value from a named field


Sorry to be asking this, but it's driving me crazy. I've been using the php SimpleXMLElement as my XML go to parser, and I've looked at many examples, and have given up on this many times. But, now, I just need to have this working. There are many examples on how to get simple fields, but not so many with values in the fields...

I'm trying to get the "track_artist_name" value from this XML as a named variable in php.

<nowplaying-info-list>
  <nowplaying-info >
    <property name="track_title"><![CDATA[Song Title]]></property>
    <property name="track_album_name"><![CDATA[Song Album]]></property>
    <property name="track_artist_name"><![CDATA[Song Artist]]></property>
  </nowplaying-info>
</nowplaying-info-list>

I've tried using xpath with:

$sxml->xpath("/nowplaying-info-list[0]/nowplaying-info/property[@name='track_artist_name']"));

But, I know it's all mucked up and not working.

I originally tried something like this too, thinking it made sense - but no:

attrs = $sxml->nowplaying_info[0]->property['@name']['track_artist_name'];
echo $attrs . "\n\n";

I know I can get the values with something such as this:

$sxml->nowplaying_info[0]->property[2];

Sometimes there are more lines in the XML results than other times, and so because of this, it is breaks the calculations with the wrong data.

Can someone shed some light on my problem? I'm just trying to the name of the artist to a variable. Many thanks.

*** WORKING UPDATE: **

I was unaware there were different XML interpreter methods, and was using the following XML interpreter version:

// read feed into SimpleXML object
$sxml = new SimpleXMLElement($json);

That didn't work, but have now updated to the following (for that section of code) thanks to the help here.

$sxml_new = simplexml_load_string($json_raw);
if ( $sxml_new->xpath("/nowplaying-info-list/nowplaying-info/property[@name='track_artist_name']") != null )
{
    $results = $sxml_new->xpath("/nowplaying-info-list/nowplaying-info/property[@name='track_artist_name']");
    //print_r($results);
    $artist = (string) $results[0];
   // var_dump($artist); 
    echo "Artist: " . $artist . "\n";
}

Solution

  • Your xpath expression is pretty much right, but you don't need to specify an index for the <nowplaying-info-list> element - it'll deal with that itself. If you were to supply an index, it would need to start at 1, not 0.

    Try

    $results = $sxml->xpath("/nowplaying-info-list/nowplaying-info/property[@name='track_artist_name']");
    
    echo (string) $results[0];
    

    Song Artist

    See https://3v4l.org/eH4Dr

    Your second approach:

    $sxml->nowplaying_info[0]->property['@name']['track_artist_name'];
    

    Would be trying to access the attribute named @name of the first property element, rather than treating it as an xpath-style @ expression. To do this without using xpath, you'd need to loop over each of the <property> elements, and test their name attibrute.