Regular Expression to match text between HTML tags - regex

I have to parse a table in HTML code using Regex. However, the code for these tables can differ because they come from different sources. But, they all have in common that they only use 2 columns. So what I want to do is to match all text that is not encapsulated within the '<' and '>' symbols.
Moreover, I want to name the two columns / groups in Regex.
I have this table row for example:
<tr>
<td width="313" valign="top" style="width:234.9pt;border:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt">
<p class="MsoNormal"><o:p>Company</o:p></p>
</td>
<td width="313" valign="top" style="width:234.9pt;border:solid windowtext 1.0pt;border-left:none;padding:0cm 5.4pt 0cm 5.4pt">
<p class="MsoNormal">TestCompany<o:p></o:p></p>
</td>
</tr>
For which I only want to select 'Company' and 'TestCompany' and name these matches as 'Key' and 'Value' respectively.
I came up with the following Regex:
https://regex101.com/r/09fpbz/2
However, this also selects odd tags like </o:p> and spaces/new lines.

If <o:p> are always like in your exemple it will work.
<tr>(?:[^<]*<){3}[^>]+>(?<Key>[\w\w]+)(?:[^>]*>){5}(?<Value>[\w\s]+)

Related

Collect results from groups to one string

I want to parse weather html page for Openhab.
This is significant part of whole html:
<!-- Amount of Sun -->
<tr>
<td class="label_det">
<span class="sum">∑</span> <span class="unit">in u</span>
</td>
<td class="sunamount">
10.2
</td>
<td class="sunamount">
10.6
</td>
<td class="sunamount">
5.9
</td>
<td class="sunamount">
6.8
</td>
<td class="dgrey sunamount">
6.8
</td>
<td class="dgrey sunamount">
5.4
</td>
<td class="sunamount">
5
</td>
</tr>
I would like to collect all numbers into one string, I understand that it's, perhaps, not possible, but may be...
So something like this: '10.2 10.6 5.9 6.8 6.8 5.4 5'
Example of full html and my current regex is here: https://regex101.com/r/nrzPHU/1
Thanks in advice.
You need named capture groups. Named capture groups allow you to specify a given part in regex with a name to extract it later. A named capture group starts with (? then followed by the regex and ended with ).
<td class\=\".*?sunamount\">\s+(?<amount>\d+(\.\d+)?)\s+<\/td>
You would then be able to extract the amount by applying your regex to the input and picking the group named amount out of it.
Reading about OpenHab online I'm not sure they support named capture groups. So an alternative would be using the regex above to match all lines with amounts in the input. Then using a regex replace on that matched string. So something like...
Use this regex to get amounts:
<td class\=\".*?sunamount\">\s+\d+(\.\d+)?\s+<\/td>
Use this regex on the result of the regex above to replace the non amounts (and replace them with an empty string to delete them):
([\s]|<td class=".*?">|<\/td>)

Find a table's last cell by regular expression

I want to use Regular Expression (compatible with pcre) to select a table
cell in an XML or HTML file.This cell was expanded in several lines containing
other elements and relative attributes and values. Thiscell supposed to be at the last column.
for some reasons I can't and don't want to use ". matches newline" option.
for example in this code:
EDITED:
<table colcount="4">
<tr>
<td colspan="2">
<para><text> Mike</text></para>
</td>
<td>
<tab />
</td>
<td1>
<para><text>Jack</text></para>
<para><text>Sarah</text></para>
</td>
</tr1>
<tr>
<td>
<para><text>Bob</text></para>
<para><text>Rita</text></para>
</td>
<td2 colspan="3" with>
<para><text>Helen</text></para>
</td>
</tr2>
<tr>
<td style="with:445px;">
<para><text>Sam</text></para>
</td>
<td>
<para><text>Emma</text></para>
<para><text>George</text></para>
</td>
<td>
</td>
<td3 colspan="">
<tab />
</td>
</tr3>
</table>
/EDITED
I want to find and select the whole last cell together with its start and end tags (<td and </td>)
and the end tag of the corresponding row(</tr>), that is:
EDITED:
Here is what I want to select in the table like above using RegEx:
Either from <td1 to </tr1> - or from <td2 to </tr2> - or from <td3 to </tr3>
/EDITED
The format (indentation and new lines have to be preserved), I mean I can't put, for example
</tr> in front of of closing tag of the cell(</td>).
Indentation is only space character.
Thanks for any help...
Best you can do with regex is:
<td(([^<]|<(?!\/td>))*)<\/td>\s*<\/tr>(?!(.|\r|\n)*<tr)
But this is kinda ugly, resource intensive and breaks when you have nested tables. A better route is indeed to use an XML or HTML parser for whichever programming language you're using.
If you want to select the last cell from EVERY row, as your updated question suggests, leave out the negative lookahead like so:
<td(([^<]|<(?!\/td>))*)<\/td>\s*<\/tr>
Working example here: http://refiddle.com/gt2

How to handle dynamically changing id's with similar starting name using Webdriver

I am automating the test for web application. I have a scenario for creating an admin, for which i have to enter the name, email address and phone number text boxes. But ids of this text boxes are dynamic.
userName, id='oe-field-input-41'
Email, id='oe-field-input-42'
phone number, id='oe-field-input-43'
First Query:
The numbers in the ids are dynamic, it keep changes
I tired to use the xpath for handling the dynamic value.
xpath = //*[starts-with(#id,'oe-field-input-')]
In this it enter the text into first text box successfully
Second Query:
I am not able use the same xpath for next two text boxes, as it enters the email and phone number into name field only
Please help me to resolve this dynamic value handling.
Edited: added the html code,
<table class="oe_form_group " cellspacing="0" cellpadding="0" border="0">
<tbody>
<tr class="oe_form_group_row">
<td class="oe_form_group_cell oe_form_group_cell_label" width="1%" colspan="1">
<td class="oe_form_group_cell" width="99%" colspan="1">
<span class="oe_form_field oe_form_field_many2one oe_form_field_with_button">
<a class="oe_m2o_cm_button oe_e" tabindex="-1" href="#" draggable="false" style="display: inline;">/</a>
<div>
</span>
</td>
</tr>
<tr class="oe_form_group_row">
<td class="oe_form_group_cell oe_form_group_cell_label" width="1%" colspan="1">
<td class="oe_form_group_cell" width="99%" colspan="1">
<span class="oe_form_field oe_form_field_email">
<div>
<input id="oe-field-input-35" type="text" maxlength="240">
</div>
</span>
</td>
</tr>
<tr class="oe_form_group_row">
<td class="oe_form_group_cell oe_form_group_cell_label" width="1%" colspan="1">
<td class="oe_form_group_cell" width="99%" colspan="1">
<span class="oe_form_field oe_form_field_char">
<input id="oe-field-input-36" type="text" maxlength="32">
</span>
</td>
</tr>
<tr class="oe_form_group_row">
<td class="oe_form_group_cell oe_form_group_cell_label" width="1%" colspan="1">
<td class="oe_form_group_cell" width="99%" colspan="1">
<span class="oe_form_field oe_form_field_char">
<input id="oe-field-input-37" type="text" maxlength="32">
</span>
</td>
</tr>
<tr class="oe_form_group_row">
</tbody>
you can try alternate way for locating unique element by label or so. For example:
css=.oe_form_group_row:contains(case_sensitive_text) input
xpath=//tr[#class = 'oe_form_group_row'][contains(.,'case_sensitive_text')]//input
If you are using ISFW you should create custom component for such form fields.
You do have some classes which are good for identification, e.g. oe_form_field_email, oe_form_field_char. It's a little complicated to use them because they're not on the input fields themselves, and the second one is not unique; but it's quite possible:
.//span[contains(#class, 'oe_form_field_email')]//input
That is an xpath which identifies the Email field as being the input which is a descendant of a span with the oe_form_field_email class. You could also use the same logic in a css selector like this, more efficiently:
span.oe_form_field_email input
For the two other fields, there is no unique class which can tell them apart so you're going to have to rely on the order (I'm assuming username comes before phone number), and that means you have to use xpaths:
(//tr//span[contains(#class, 'oe_form_field_char')])[1]//input
(//tr//span[contains(#class, 'oe_form_field_char')])[2]//input
Those xpaths pick out the first and second fields respectively, which are inputs which are descendants of a span of class oe_form_field_char.
P.S. I used Firepath in firefox to verify the xpath and css locators.
The problem here is, that your XPath does the correct selection, but Selenium will always pick the first one if multiple results are returned for your query.
You can select each of the input fields directly by using:
//input[1]
//input[2]
//input[3]
If there are other input fields, you can tighten your selection by selecting only input nodes with oe-field-input in their id attribute like this:
//input[starts-with(#id,'oe-field-input-')][1]
//input[starts-with(#id,'oe-field-input-')][2]
//input[starts-with(#id,'oe-field-input-')][3]
Use the following xpath works like a charm. Although I don't recommend this kind of an xpath. Since we don't have text against the text box no other choice.
//div/input[contains(#id, 'oe-field-input')] - First text box
//tr[#class = 'oe_form_group_row'][2]//input - Second text box
//tr[#class = 'oe_form_group_row'][3]//input - Third text box
You can use below XPATH.
//tr[#class = 'oe_form_group_row'][2]//input for First Text box
//tr[#class = 'oe_form_group_row'][3]//input for Second Text box
//tr[#class = 'oe_form_group_row'][4]//input for Third text box.
I have tested avove xpath.
But the better way if you have development access then ask developers to make is standaralized and recommand tags like "name" , "value", or attach text e.g. Email:, Password. So you can use these in your xpath.

Something about regular expression

If I want to get the current price 416.00 of the following content, what regexp I can use to get it? There are some places in the webpage with similar content, except the one I want has the word Discount in a few lines after the current price. 416,520 and 20% are variable. Thanks.
<tr>
<td class="txt_11px_b_EB6495" width="50" nowrap>Current Price?</td>
<td class="txt_11px_b_EB6495">HK$ 416.00</td>
</tr>
<tr>
<td class="txt_11px_n_999999">Original price?</td>
<td class="txt_11px_n_999999">HK$ 520.00</td>
</tr>
<tr>
<td class="txt_9px_n_999999"> </td>
<td class="txt_9px_n_999999">Discount 20%</td>
</tr>
You can use
" (\d+\.\d*)</td>"
That will match 520.00, 2.00, 123.1, and 123.
Use a HTML parser to get the text node, then extract the price using a regex.
You would use something like...
\d+(?:\.\d{2}|%)
I just tested it and it matched...
416.00
520.00
20%
I assumed (it was unclear to me) you want the prices and the percentage discount. I also matched the % so you can tell what are the percentages in the matches.

Notepad++ search & replace

I'm trying to convert a html file with 100 of entries like this one:
<table>
<tr>
<td valign="top" width="30">
1.</td>
<td>
TEXT DESCRIPTION
</td>
</tr>
</table>
<table><tr><td></td></tr></table>
where the number "1." goes from 1 to 100, into this:
<li>
TEXT DESCRIPTION
</li>
I haven't find a way to do this, neither with regexp nor with extended search mode. Any ideas?
You could start with this:
Replace
.*<td>(.*[A-Za-z]+.*)<\/td>.*
with
<li>\1</li>
This will match one chunk of code of the form you reported. You must modify it to match multiple chunks of the same form in the same file.
Moreover to work correctly we should make it match lazily. Someone who knows how?