I am using simple html dom to extract data from a website and pharse it. I cannot however change one of the realative paths in the style tag to a full one. I have tried many combinations.
I found a post here to use a PEAR script with simple html dom and it has worked on all links except below.
require_once 'includes/URL2.php';
$uri = new Net_URL2('http://www.stormcinemas.ie'); // URI of the resource
$baseURI = $uri;
foreach ($htmlcss->find('background[url]') as $elem) {
$elem->url = $baseURI->resolve($elem->url)->__toString();
}
foreach ($html->find('*[src]') as $elem) {
$elem->src = $baseURI->resolve($elem->src)->__toString();
}
foreach ($html->find('*[href]') as $elem) {
if (strtoupper($elem->tag) === 'BASE') continue;
$elem->href = $baseURI->resolve($elem->href)->__toString();
}
foreach ($html->find('form[action]') as $elem) {
$elem->action = $baseURI->resolve($elem->action)->__toString();
}
style.css
<style>
div.spriteImgSmall { background: url(/images/css_sprites/film_sprites/smallimages_sprite.jpg); }
</style>
Thanks
The solution was provided here but was deleted unfortunately. Thanks again, it actualy did solve my question.
Here it is for future ref.
$htmlcss = preg_replace('/url\(\s*[\'"]?\/?(.+?)[\'"]?\s*\)/i', 'url('.
$baseURI.'/$1)', $htmlcss);
I would still be interested if someone know's how to use simple html dom on css as there is nothing anywhere on the net. It may not even be possible.
Related
I have a Book Now button on each page of my website. I would like to know which button is selected and don't really want to add 25+ blocks to the site to add the class manually. I can use Google Analytics if I can make the button unique (add an additional class based on the page URL). But I'm not a coder although I'm familiar with both PHP and jQuery.
Hye Michael, after reading your question i have tested your scenario on my local test drupal site. And it's really easy to achieve it. Here is a piece of PHP code you need to put into your block you created.
<?php
$url = current_path();
$class_from_url = explode("/", $url);
echo "<a href=[link_to_whatever] class='". $class_from_url[0] ."'>[Link Title]</a>";
?>
Make sure your "PHP filter" module is enabled which will allow you to select PHP code from "Text formats" under the block body.
For Drupal 7, the best way to accomplish your goal would be to copy the theme_button() function to your theme's template.php file and add some custom code to check the URL and add the class.
YOURTHEME_button($vars) {
$element = $variables ['element'];
$element ['#attributes']['type'] = 'submit';
element_set_attributes($element, array('id', 'name', 'value'));
$element ['#attributes']['class'][] = 'form-' . $element ['#button_type'];
if (!empty($element ['#attributes']['disabled'])) {
$element ['#attributes']['class'][] = 'form-button-disabled';
}
// Check URL to determine what button class to add
$button_class = null;
$current_path = base_path() . request_path();
switch ($current_path) {
'/form1':
$button_class = 'button-for-form1';
break;
'/form2':
$button_class = 'button-for-form2';
break;
}
if ($button_class !== null) {
$element ['#attributes']['class'][] = $button_class;
}
return '<input' . drupal_attributes($element ['#attributes']) . ' />';
}
Note that this method will add the class only for URLs that you explicitly specify, and it ignores any user-supplied parameters that might be included as part of the URL.
I have a lot of php included pages inside a template.
<h1> tag is also inside an included page, but I need to change them dynamically:
<div id='xnavact'>abc</div>
js
var a = $('#xnavact').html();
$('h1').html(a);
This works but I've heard that Google Search does not include changed content via javascript.
Am I right about this, and how could I make the same thing using php?
Something like:
<h1><?php echo $content_of_xnavact ?></h1>
But how to get content of a div inside a php variable?
You can parse your HTML content in PHP with some packages like Symfony 2 Dom Crawler.
If your just want to use a value many time through your script, I think you should consider saving this value in a variable and use it instead of store the whole HTML elements in a static file and use any parser.
An example of using Dom Crawler library for you:
use Symfony\Component\DomCrawler\Crawler;
use Symfony\Component\CssSelector\CssSelector;
CssSelector::disableHtmlExtension();
function getInnerHtml( $node ) {
$innerHTML= '';
$children = $node->childNodes;
foreach ($children as $child) {
$innerHTML .= $child->ownerDocument->saveHtml( $child );
}
return $innerHTML;
}
$html = <<<'HTML'
<div>
<div>foo</div>
<div id="xnavact"><span>bar</span></div>
</div>
HTML;
$crawler = new Crawler($html);
$crawler = $crawler->filter('#xnavact');
foreach ($crawler as $domElement) {
print getInnerHtml($domElement); //result: <span>bar</span>
}
You can use preg_replace or I don't understand your question correctly
I have this following XML
<Logs>
<UnplugDate>
<Date>2013-09-10T09:20:00</Date>
<Date>2013-09-09T16:03:00</Date>
</UnplugDate>
What I'm trying to do here is to read the values of both variables under <UnplugDate> tag.
I try to use the hasChildNodes() but when I debug It doesn't go inside
foreach($unplug_date as $node)
block.
Any Idea how can I read these values? Thanks in advance
$logs = $key->getElementsByTagName(tag_constants::TAG_LOGS);
$unplug_date = $logs->item(0)->getElementsByTagName(tag_constants::TAG_UNPLUG_DATE)->item(0);
foreach($unplug_date as $node) {
if($node->hasChildNodes()) {
foreach ($node->childNodes as $unplug_date_value) {
$unplug_date_value = $unplug_date->getElementsByTagName(tag_constants::TAG_DATE)->item(0)->nodeValue;
}
}
}
NOTE:
tag_constants::TAG_LOGS -> Logs
tag_constants::TAG_UNPLUG_DATE -> UnplugDate
tag_constants::TAG_DATE -> Date
I've finally find the solution. Writing :
$test = $unplug_date->getElementsByTagName(tag_constants::TAG_DATE);
instead of
$unplug_date = $logs->item(0)->getElementsByTagName(tag_constants::TAG_UNPLUG_DATE)->item(0);
solves the problem.
I am writing some code for an IRC bot written in php and running on the linux cli. I'm having a little trouble with my code to retrieve a websites title tag and display it using DOMDocument NodeList. Basically, on websites with two or more tags (and you would be surprised how many there actually are...) I want to process for only the first title tag. As you can see from the code below (which is working fine for processing one, or more tags) there is a foreach block where it iterates through each title tag.
public function onReceivedData($data) {
// loop through each message token
foreach ($data["message"] as $token) {
// if the token starts with www, add http file handle
if (strcmp(substr($token, 0, 4), "www.") == 0) {
$token = "http://" . $token;
}
// validate token as a URL
if (filter_var($token, FILTER_VALIDATE_URL)) {
// create timeout stream context
$theContext['http']['timeout'] = 3;
$context = stream_context_create($theContext);
// get contents of url
if ($file = file_get_contents($token, false, $context)) {
// instantiate a new DOMDocument object
$dom = new DOMDocument;
// load the html into the DOMDocument obj
#$dom->loadHTML($file);
// retrieve the title from the DOM node
// if assignment is valid then...
if ($title = $dom->getElementsByTagName("title")) {
// send a message to the channel
foreach ($title as $theTitle) {
$this->privmsg($data["target"], $theTitle->nodeValue);
}
}
} else {
// notify of failure
$this->privmsg($data["target"], "Site could not be reached");
}
}
}
}
What I'd prefer, is to somehow limit it to only processing the first title tag. I'm aware that I can just wrap an if statement around it with a variable so it only echos one time, but I'm more looking at using a "for" statement to process a single iteration. However, when I do this, I can't access the title attribute with $title->nodeValue; it says it's undefined, and only when i use the foreach $title as $theTitle can I access the values. I've tried $title[0]->nodeValue and $title->nodeValue(0) to retrieve the first title from the list, but unfortunately to no avail. A bit stumped and a quick google didn't turn up a lot.
Any help would be greatly appreciated! Cheers, and I'll keep looking too.
You can solve this with XPath:
$dom = new DOMDocument();
#$dom->loadHTML($file);
$xpath = new DOMXPath($dom);
$title = $xpath->query('//title')->item(0)->nodeValue;
Try something like this:
$title->item(0)->nodeValue;
http://www.php.net/manual/en/class.domnodelist.php
I'm working on a new class to wrap XML handling. I want my class to use simplexml if it's installed, and the built in XML functions if it's not. Can anyone give me some suggestions on a skeleton class to do this? It seems "wrong" to litter each method with a bunch of if statements, and that also seems like it would make it nearly impossible to correctly test.
Any upfront suggestions would be great!
EDIT: I'm talking about these built-in xml functions.
Which built-in xml functions are you referring to? SimpleXml is a standard extension, which uses libxml underneath - just as the dom extension does. So if the dom extension is installed, chances are that so is SimpleXml.
I've made a class which wraps SimpleXml functionality... take what you may from it...
bXml.class.inc
There is one weird thing... it's that SimpleXml doesn't allow its constructor to be overloaded, so you can't do things at initiation ... like override the input value (i.e. so you can accept XML as in input). I got around that limitation by using an ArrayObject class to wrap the new SimpleXml class.
I use something like this for doing xml translations and content:
Assuming xml structure something like this (important to use a regular structure, means you can pull off some nice agile tricks!):
<word name="nameofitem">
<en>value</en>
<pt>valor</pt>
<de>value_de</de>
</word>
and then a class to handle the xml:
class translations
{
public $xml = null;
private $file = null;
private $dom = null;
function __construct($file="translations") {
// get xml
$this->file = $file;
$this->haschanges = false;
$this->xml = file_get_contents($_SERVER['DOCUMENT_ROOT']."/xml/".$file.".xml");
$this->dom = new DOMdocument();
$this->dom->loadXML($this->xml);
}
function updateNode($toupdate, $newvalue, $lang="pt",$rootnode="word"){
$this->haschanges = true;
$nodes = $this->dom->getElementsByTagName($rootnode);
foreach ($nodes as $key => $value) {
if ($value->getAttribute("name")==$toupdate) {
$nodes->item($key)->getElementsByTagName($lang)->item(0)->nodeValue = htmlspecialchars($newvalue,ENT_QUOTES,'UTF-8');
}
}
}
function saveUpdated(){
$toSave = $this->dom->saveXML();
if ($this->haschanges === true) {
file_put_contents($_SERVER['DOCUMENT_ROOT']."/xml/".$this->file.".xml", $toSave);
return true;
}
else {
return false;
}
}
}
I took out a few of the methods I have, for brevity, but I extend this with things to handle file and image uploads etc too.
Once you have all this you can do:
$xml = new translations();
// loop through all the language posts
foreach ($_POST["xml"]["en"] as $key => $value) {
$xml->updateNode($key, stripslashes($value), "en");
}
Or something ;) hope this gives you some ideas!