0

I am really confused with regular expressions for PHP.

Anyway, I cant read the whole tutorial thing now because I have a bunch of files in html which I have to find links in there ASAP. I came up with the idea to automate it with a php code which it is the language I know.

so I think I can user this script :

$address = "file.txt"; 
$input = @file_get_contents($address) or die("Could not access file: $address");
$regexp = "??????????"; 
if(preg_match_all("/$regexp/siU", $input, $matches)) { 
    // $matches[2] = array of link addresses 
   // $matches[3] = array of link text - including HTML code 
} 

My problem is with $regexp

My required pattern is like this:

href="/content/r807215r37l86637/fulltext.pdf" title="Download PDF

I want to search and get the /content/r807215r37l86637/fulltext.pdf from above lines which I have many of them in the files.

any help?

==================

edit

title attributes are important for me and all of them which I want, are titled

title="Download PDF"

Gray
  • 7,050
  • 2
  • 29
  • 52
Alireza
  • 5,444
  • 9
  • 38
  • 50

5 Answers5

5

Once again regexp are bad for parsing html.

Save your sanity and use the built in DOM libraries.

$dom = new DOMDocument();
@$dom->loadHTML($html);
$x = new DOMXPath($dom);
    $data = array();
foreach($x->query("//a[@title='Download PDF']") as $node)
{
    $data[] = $node->getAttribute("href");
}

Edit Updated code based on ircmaxell comment.

Community
  • 1
  • 1
Byron Whitlock
  • 52,691
  • 28
  • 123
  • 168
  • uhhh. Why xpath if you're going to do only a nodename search? Why not just `$dom->getElementsByTagName('a');`? I could understand xpath if you did `$x->query('//a[contains(@title, "Download Pdf")]');` which would return the exact match... ;-) – ircmaxell Feb 11 '11 at 20:31
  • @ircmaxell, you are exactly right.`getElementsByTagName()` is probably a more efficient way to do it.. – Byron Whitlock Feb 11 '11 at 20:35
  • @safaali in the query, change `@title='Download Pdf'` to `@class='nameOfClass'` or use `contains(@title, 'Download PDF')`. Contains will grab them even if they have extra stuff in them. – Byron Whitlock Feb 11 '11 at 20:46
  • thank you! should I install The DOMDocument class? I am using xampp 1.7.3 on my localhost. – Alireza Feb 11 '11 at 21:10
  • @safaali, all the dom libraries are built in. No need to install anything. – Byron Whitlock Feb 11 '11 at 21:18
1

try something like this. If it does not work, show some examples of links you want to parse.

<?php
$address = "file.txt"; 
$input = @file_get_contents($address) or die("Could not access file: $address");
$regexp = '#<a[^>]*href="([^"]*)"[^>]*title="Download PDF"#'; 

if(preg_match_all($regexp, $input, $matches, PREG_SET_ORDER)) { 
  foreach ($matches as $match) {
    printf("Url: %s<br/>", $match[1]);
  }
} 

edit: updated so it searches for Download "PDF entries" only

Ondrej Skalicka
  • 3,046
  • 9
  • 32
  • 53
1

That's easier with phpQuery or QueryPath:

foreach (qp($html)->find("a") as $a) { 
    if ($a->attr("title") == "PDF") {
        print $a->attr("href");
        print $a->innerHTML();
    }
}

With regexps it depends on some consistency of the source:

preg_match_all('#<a[^>]+href="([^>"]+)"[^>]+title="Download PDF"[^>]*>(.*?)</a>#sim', $input, $m);

Looking for a fixed title="..." attribute is doable, but more difficult as it depends on the position before the closing bracket.

mario
  • 144,265
  • 20
  • 237
  • 291
  • @Byron: Some people have aversions to needlessly cumbersome APIs. – mario Feb 11 '11 at 21:14
  • @mario Have you actually tried dom parsing with the built in libs? I'll admit, the php site docs on dom are cumbersome. I resisted at first too until I saw the light. It really is easy. If you know xquery, `DOMXPath::xquery` is all you need. – Byron Whitlock Feb 11 '11 at 21:22
  • @Byron: Tried and used. But much like raw Javascript DOM methods, I'm avoiding it. – mario Feb 11 '11 at 21:27
  • @mario fair enough. Just curious, do either of those libs use the built in php dom under the hood? – Byron Whitlock Feb 11 '11 at 21:57
  • @Byron: Actually all of them do (phpQuery, QueryPath, FluentDom) as far as I'm aware. Though QP comes with its own alternative parser for more quirky HTML. – mario Feb 11 '11 at 22:01
1

The best way is to use DomXPath to do the search in one step:

$dom = new DomDocument();
$dom->loadHTML($html);
$xpath = new DomXPath($dom);

$links = array();
foreach($xpath->query('//a[contains(@title, "Download PDF")]') as $node) {
    $links[] = $node->getAttribute("href");
}

Or even:

$links = array();
$query = '//a[contains(@title, "Download PDF")]/@href';
foreach($xpath->evaluate($query) as $attr) {
    $links[] = $attr->value;
}
ircmaxell
  • 163,128
  • 34
  • 264
  • 314
0

href="([^]+)" will get you all the links of that form.

Blindy
  • 65,249
  • 10
  • 91
  • 131
  • Thank you, But there are many herfs in the file, I want that links which are titled "Download PDF" – Alireza Feb 11 '11 at 20:24