Query Microformats like XPath

I find php-mf2's output difficult to work with when searching deeply nested properties. Traversing the tree requires testing if keys are present, and dealing with multiple values. So I created the following solution to query microformats similar to XPath.

The first path element must be an h-* root class name; the rest are properties. If any path element fails to match, mfpath() will return an empty array.

<?php
function type($type) {
    return function ($elt) use ($type) {
        return in_array($type, $elt["type"]);
    };
}

function prop($mfs, $prop) {
    $props = array();
    foreach ($mfs as $mf) {
        if (gettype($mf) == "array"
            && array_key_exists("properties", $mf)
            && array_key_exists($prop, $mf["properties"]))
            $props = array_merge($props, $mf["properties"][$prop]);
    }
    return $props;
}

function mfpath($mf, $path) {
    $elts = array_filter(explode("/", $path), function($e){return $e!="";});
    $result = array_filter($mf["items"], type(array_shift($elts)));
    while (count($elts) > 0) {
        $result = prop($result, array_shift($elts));
    }
    return $result;
}

// example usage:

require("Mf2/Parser.php");

$mf = Mf2\Parse(<<<EOT
<div class="h-entry">
    <div class="p-in-reply-to h-cite">
        <a class="u-url" href="http://megapony.io/2014/03/04/1/"></a>
    </div>
    <div class="p-in-reply-to h-cite">
        <a class="u-url" href="http://rocklobster.me/2014/03/02/2/"></a>
    </div>
</div>
EOT
);

print_r(mfpath($mf, "/h-entry/in-reply-to/url"));
//Array
//(
//    [0] => http://megapony.io/2014/03/04/1/
//    [1] => http://rocklobster.me/2014/03/02/2/
//)
?>
 
more...

Have you written a reply to this?

Barnaby WaltersQuery microformats2 like XPath — @notenoughneon created this nifty function for handling #microformats data more easily

Query microformats2 like XPath — @notenoughneon created this nifty function for handling #microformats data more easily