1
$\begingroup$

I haven't found an answer that solves my problem, although I think it's actually a simple one. It seems hard to me because I don't have a lot of experience with string patterns.

I have a Web Code like

...<td, class=test, >strings1</td>...<td, class=test, >strings2</td>...

that I have imported using

v = Import[*url*, "Table"]

I want to find these strings string1, string2, etc., but when I use StringCases like

StringCases[ToString[v], "class=test, >" ~~ x__ ~~ "</td>" -> x]

The code will return everything between the first class=test, > and the last </td>, resulting in something like

strings1</td>...<td, class=test, >strings2`

But I want all the strings between each paired class=test, > and </td>, I have tried to use Overlap without success.

$\endgroup$
3
  • 2
    $\begingroup$ It is a widely (and justifiably) held view that one should not use regular expressions (or equivalent, as in this case) to parse [X]HTML. You will probably be better off importing as HTML or XML and then manipulating these results symbolically using the XML package. $\endgroup$ Commented Mar 17, 2013 at 22:30
  • $\begingroup$ @OleksandrR. Agree, but I recall XML import and parsing in Mathematica is very time consuming. So I have used regular expressions in the past out of speed necessity. $\endgroup$
    – Jens
    Commented Mar 18, 2013 at 3:58
  • $\begingroup$ Your web code has syntax errors in it. The commas after <td aren't correct. $\endgroup$
    – Jens
    Commented Mar 18, 2013 at 4:12

2 Answers 2

4
$\begingroup$

You can use Shortest if the sub-strings of the form <td, class=test, >...</td> don't contain nested sub-strings of the form <td, class=test, > or </td>. If they do, follow this link.

v = "...<td, class=test, >strings1</td>...<td, class=test, >strings2</td>..";
StringCases[v, Shortest["<td, class=test, >" ~~ x__ ~~ "</td>"] -> x]

{"strings1", "strings2"}

$\endgroup$
1
  • 1
    $\begingroup$ Not sure, but I would rather say : You can use Shortest if the 2 following conditions are respected : 1) Your targeted <td, class=test, >...</td> doesn't contain nested sub-strings of the form <td, class=test, > or </td> 2) Your targeted <td, class=test, >...</td> is not enclosed in another <td, class=test, >...</td>. If it is the case and if 1) is respected follow the link $\endgroup$
    – andre314
    Commented Mar 17, 2013 at 22:26
0
$\begingroup$

Using my Excel mindset and assuming all the "class=test, >" are matched with a "<\td" I would do something like:

str = "...<td, class=test, >strings1</td>...<td, class=test, >strings2</td>..."

starts = StringPosition[str, "class=test, >"]
startpositions = Flatten@Take[starts, All, {2}] + 1
ends = StringPosition[str, "</td"]
endpositions = Flatten@Take[ends, All, {1}] - 1
segments = Transpose[{startpositions, endpositions}]

strings = StringTake[str, segments]
propersentence = "I found " <> Riffle[strings, {" and "}] <> "."
Speak[propersentence]

or similar.

$\endgroup$

Not the answer you're looking for? Browse other questions tagged or ask your own question.