/** * Returns a guaranteed valid HTML attribute. Removes illegal characters. * Allows for 'naked' attributes, without a value. * @param string $name * @param string|array|bool $value * @return string */ public static function attribute($name, $value) { if ($name === $value) { return ' ' . self::name($name); } else { if (is_numeric($name)) { return ' ' . self::name($value); } else { return \arc\xml::attribute($name, $value); } } }
function testNamespacedAttributes() { $xmlString = <<<EOF <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/"> <channel rdf:about="http://slashdot.org/"> <title>Slashdot</title> <link>http://slashdot.org/</link> <description>News for nerds, stuff that matters</description> <dc:language>en-us</dc:language> <dc:rights>Copyright 1997-2016, SlashdotMedia. All Rights Reserved.</dc:rights> <dc:date>2016-01-30T20:38:08+00:00</dc:date> <dc:publisher>Dice</dc:publisher> <dc:creator>help@slashdot.org</dc:creator> <dc:subject>Technology</dc:subject> </channel> </rdf:RDF> EOF; $xml = \arc\xml::parse($xmlString); $xml->registerNamespace('dc', 'http://purl.org/dc/elements/1.1/'); $xml->registerNamespace('foo', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'); $xml->registerNamespace('rdf', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'); $about = $xml->channel['rdf:about']; $this->assertEquals('http://slashdot.org/', $about); $xml->channel['rdf:about'] = 'About tests'; $this->assertEquals('About tests', $xml->channel['rdf:about']); unset($xml->channel['rdf:about']); $this->assertEquals('', $xml->channel['rdf:about']); $xml->channel['foo:about'] = 'About foo'; $this->assertEquals('About foo', $xml->channel['foo:about']); $this->assertEquals('About foo', $xml->channel['rdf:about']); $xml->registerNamespace('bar', 'http://arc.muze.nl/'); $xml->channel['bar:foo'] = 'Bar Foo'; $this->assertEquals('Bar Foo', $xml->channel['bar:foo']); }
<?php require __DIR__ . '/../vendor/autoload.php'; use arc\html as h; use arc\xml as x; $client = \arc\cache::proxy(\arc\http::client(), function ($params) { return \arc\http\headers::parseCacheTime($params['target']->responseHeaders); }); $feed = $client->get('https://www.nasa.gov/rss/dyn/breaking_news.rss'); try { $rss = x::parse($feed); } catch (\Exception $e) { $rss = h::parse($feed); } $items = $rss->find('item'); foreach ($items as $item) { echo h::article(h::h2(h::a(['href' => $item->link->nodeValue], $item->title->nodeValue)), h::div(['class' => 'body'], $item->description->nodeValue)); }
function aggregator($client) { $aggregator = \arc\lambda::prototype(); $aggregator->renderItem = function ($item) { if ($item->enclosure['url']) { $img = h::a(['href' => $item->link->nodeValue], h::img(['src' => $item->enclosure['url'], 'alt' => ''])); } else { $img = ''; } $pubDate = h::time(relativeTime(strtotime(current($item->xpath('.//pubDate|.//dc:date'))))); return h::article(['class' => 'white-panel'], $img, h::h2(h::a(['href' => $item->link->nodeValue], $item->title->nodeValue)), $pubDate, h::p(['class' => 'description'], h::raw(strip_tags($item->description->nodeValue)))); }; $aggregator->renderItems = function ($items) { $itemsString = ''; if (count($items)) { foreach ($items as $item) { $itemsString .= $this->renderItem($item); } } else { $itemsString = h::div(['class' => 'warning'], 'No articles in this feed.'); } return h::raw($itemsString); }; $aggregator->renderFeeds = function ($feeds) { return implode(array_map(function ($feed, $index) { return h::div(['class' => 'feed'], h::h2($feed->channel->title->nodeValue), h::form(['class' => 'remove', 'method' => 'POST'], h::button(['name' => 'removeFeed', 'value' => $index], 'Remove')), h::a(['href' => $feed->channel->link->nodeValue], $feed->channel->link->nodeValue)); }, $feeds, array_keys($feeds))); }; $aggregator->getPubDate = function ($item) { return strtotime(current($item->xpath('.//pubDate|.//dc:date'))); }; $aggregator->getItems = function ($feeds) { $allitems = call_user_func_array('array_merge', array_map(function ($rss) { return array_map(function ($item) use($rss) { $item->appendChild($rss->channel->cloneNode()); return $item; }, $rss->getElementsByTagName('item')); }, $feeds)); usort($allitems, function ($a, $b) { return $this->getPubDate($a) < $this->getPubDate($b); }); return $allitems; }; $aggregator->getFeed = function ($url) use($client) { $feed = $client->get($url); try { $rss = \arc\xml::parse($feed); } catch (\Exception $e) { $rss = \arc\html::parse($feed); } $rss->registerXPathNamespace('dc', 'http://purl.org/dc/elements/1.1/'); return $rss; }; $aggregator->render = function ($feeds) { $feeds = array_map(function ($feed) { return $this->getFeed($feed); }, $feeds); $items = $this->getItems($feeds); return h::section(['class' => 'items'], h::raw($this->renderItems($items))) . h::section(['class' => 'feeds'], h::raw($this->renderFeeds($feeds))); }; return $aggregator; }
protected function getAttributes($attributes) { $result = ''; if (count($attributes)) { foreach ($attributes as $name => $value) { $result .= \arc\xml::attribute($name, $value); } } return $result; }
/** * Search through the XML DOM with a single CSS selector * @param string $query the CSS selector, most CSS 2 selectors work * @return Proxy */ public function find($query) { $xpath = \arc\xml::css2Xpath($query); return $this->_proxyResult($this->target->xpath($xpath)); }
public static function comment($content) { return \arc\xml::comment($content); }