VaN
VaN

Reputation: 2210

simplexml and xpath, read sibling

I have the following XML file :

<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
    <item>
        [...]
        <wp:postmeta>
            <wp:meta_key>_wp_old_slug</wp:meta_key>
            <wp:meta_value><![CDATA[item-1-slug]]></wp:meta_value>
        </wp:postmeta>
        <wp:postmeta>
            <wp:meta_key>_yoast_wpseo_title</wp:meta_key>
            <wp:meta_value><![CDATA[item-1-title]]></wp:meta_value>
        </wp:postmeta>
        [...]
    </item>
    <item>
        [...]
        <wp:postmeta>
            <wp:meta_key>_wp_old_slug</wp:meta_key>
            <wp:meta_value><![CDATA[item-2-slug]]></wp:meta_value>
        </wp:postmeta>
        <wp:postmeta>
            <wp:meta_key>_yoast_wpseo_title</wp:meta_key>
            <wp:meta_value><![CDATA[item-2-title]]></wp:meta_value>
        </wp:postmeta>
        [...]
    </item>
</channel>
</rss>

I'm looping through my items with

$xmlurl = file_get_contents($xmlFile);
$xml = simplexml_load_string($xmlurl, null, LIBXML_NOCDATA);
$items = $xml->channel->item;
foreach( $items as $item ) {

}

Inside this loop, i'd like to read the value of the sibling of the <wp:meta_key>_yoast_wpseo_title</wp:meta_key> node. For example, for item 1, i'd like to get "item-1-title". I probably have to use xpath, but i really dont know how to proceed.

How can I do this ?

Upvotes: 0

Views: 681

Answers (2)

Tomalak
Tomalak

Reputation: 338316

This solution includes reference to the Wordpress XML namespace:

$doc = new SimpleXmlElement($xml);
$doc->registerXPathNamespace ('wp', 'http://wordpress.org/export/1.0/');

$wp_meta_title = $doc->xpath("//wp:postmeta[wp:meta_key = '_yoast_wpseo_title']/wp:meta_value");

foreach ($wp_meta_title as $title) {
    echo (string)$title . "\n";
}

result:

item-1-title
item-2-title

See http://ideone.com/qjOfIW

The path //wp:postmeta[wp:meta_key = '_yoast_wpseo_title']/wp:meta_value is pretty straight-forward, I don't think it needs special explanation.

Upvotes: 3

Amadan
Amadan

Reputation: 198436

$xpath = './/wp:meta_key[text()="_yoast_wpseo_title"]/following-sibling::wp:meta_value[1]/text()';
$items = $xml->channel->item;
foreach( $items as $item ) {
  $result = $item->xpath($xpath);
  print "$result[0]\n";
}

// => item-1-title
// => item-2-title

Explanation of the XPath expression:

.                               - from the current node...
//wp:meta_key                   - get all descendant wp:meta_key nodes
[text()="_yoast_wpseo_title"]   - whose text content is _yoast_wpseo_title
/following-sibling::            - then get the siblings that come after this
wp:meta_value[1]                - with tag wp:meta_value; only take the first
/text()                         - and read its text

Upvotes: 3

Related Questions