from this html code I have to extract two values, two separate fields: the first in 'name' and the second in 'value'
<table>
<tbody>
<tr>
<td>
<span><strong>CPU & Dissipatore </strong></span>
</td>
<td>
<span>Intel i7-11700K Dissipatore a Liquido 240mm </span>
</td>
</tr>
</table>
Xpath code:
array(
'name' => ".//table//tr//td[1]",
'value' => ".//table//tr//td[2]",
),
So I get nothing. What am I doing wrong?
Like this:
//tr//td/span
Output
CPU & Dissipatore
Intel i7-11700K Dissipatore a Liquido 240mm
Name/value pairs in XPath (3.1) would be maps not arrays so in XPath 3.1 you can use e.g.
map {
'name' : //table//tr//td[1]/string(),
'value' : //table//tr//td[2]/string()
}
Online sample.
Related
I have a json object that I'm trying to map into a table within a react component. I'm having difficulty accessing the 'title' and the 'tooltip' from within the json object. The console log successfully shows me the entire the json object, but
this.props.selectedProducts.products.title
Which I thought would map to the 'title' part of the json data simply doesn't work. Can anyone tell me what I'm doing wrong & possibly how to correct it? Thanks in advance!
JSON:
selectedProducts: [
{
“start”: “Tue Jun 19 16:55:40 BST 2018”,
“products”: [
{
“title”: “SL Primary - Alaska (Westlaw PRO™)“,
“price”: “”
},
{
“title”: “SL Ninth Circuit Primary Law (Westlaw PRO™)“,
“price”: “”
}
]
}
],
React:
renderProducts() {
const selected = this.props.selectedProducts;
return this.props.selectedProducts.map((selected, i) => {
return (
<tr className="product-cells" key={i}>
<td> {selected.title} </td>
<td> {selected.price}</td>
</tr>
);
});
}
selectedProducts is an array, so you have to access the first object in the array, and map over products:
renderProducts() {
return this.props.selectedProducts[0].products.map((selected, i) => {
return (
<tr className="product-cells" key={i}>
<td> {selected.title} </td>
<td> {selected.price}</td>
</tr>
);
});
}
You should use first element of your selectedProducts array as answered before or use a second map if there will be more objects:
renderProducts() {
return (
this.props.selectedProducts.map(el =>
el.products.map(selected =>
<tr className="product-cells" key={selected.title}>
<td> {selected.title} </td>
<td> {selected.price}</td>
</tr>)
)
)
}
Do not use indexes as your keys. There could be some problems if you do so.
I have values in a database for example: 830,400,000 and in the view I want to display it as $830.4
In the view I thought to use the pattern option but I was unclear how to use it:
<td class="nonBulletList">
<?= $this->Number
->currency($currentExpenses,
'USD',
['places' => 1],
['pattern' => '###.#']) ?>
</td>
I am using the HTML Table Class of CodeIgniter, and attempting to create a table template. The example given in the documentation is the following:
$tmpl = array (
'table_open' => '<table border="0" cellpadding="4" cellspacing="0">',
'heading_row_start' => '<tr>',
'heading_row_end' => '</tr>',
'heading_cell_start' => '<th>',
'heading_cell_end' => '</th>',
'row_start' => '<tr>',
'row_end' => '</tr>',
'cell_start' => '<td>',
'cell_end' => '</td>',
'row_alt_start' => '<tr>',
'row_alt_end' => '</tr>',
'cell_alt_start' => '<td>',
'cell_alt_end' => '</td>',
'table_close' => '</table>'
);
$this->table->set_template($tmpl);
When I apply this template to my query, this is the resulting HTML:
<table data-hide-table="false" data-orientation="vertical" class="chart">
<thead>
<tr>
<th></th><th>Rate per SF</th></tr>
</thead>
<tbody>
<tr>
<td>2008</td><td>48</td></tr>
<tr>
<td>2009</td><td>32</td></tr>
<tr>
<td>2010</td><td>32</td></tr>
<tr>
<td>2011</td><td>32</td></tr>
<tr>
<td>2012</td><td>40</td></tr>
<tr>
<td>2013</td><td>41</td></tr>
</tbody>
</table>
The problem with this example is that each row contains two data elements (<td></td><td></td>), instead of one header element and one data element (<th></th><td></td>).
How can I change the template so that my resulting table will have one header element and one data element (<th></th><td></td>) on each row like this:
<table data-hide-table="false" data-orientation="vertical" class="chart">
<thead>
<tr>
<th></th><th>Rate per SF</th></tr>
</thead>
<tbody>
<tr>
<th>2008</th><td>48</td></tr>
<tr>
<th>2009</th><td>32</td></tr>
<tr>
<th>2010</th><td>32</td></tr>
<tr>
<th>2011</th><td>32</td></tr>
<tr>
<th>2012</th><td>40</td></tr>
<tr>
<th>2013</th><td>41</td></tr>
</tbody>
</table>
Thanks.
The answer is no you can't change template like this but yes you can somewhere achieve this kind of functionality
If you see the http://ellislab.com/codeigniter/user-guide/libraries/table.html there is a option to add a callable function so I suggest you are creating a table make some flag if you are using that table is generating than create a helper function and add that to the table function than before generating table set a flag to determine the first cell may be using cookie. Than from helper for every 1, 3....(2n+1) add some custom html tag or style. Than after generating the table remove all the flags.
I'm trying to parse text out of two lines of HTML.
Dim PattStats As New Regex("class=""head"">(.+?)</td>"+
"\n<td>(.+?)</td>")
Dim makor As MatchCollection = PattStats.Matches(page)
For Each MatchMak As Match In makor
ListView3.Items.Add(MatchMak.Groups(1).Value)
Next
I added the \n to match the next line, but for some reason it won't work. Here's the source I'm running the regex against.
<table class="table table-striped table-bordered table-condensed">
<tbody>
<tr>
<td class="head">Health Points:</td>
<td>445 (+85 / per level)</td>
<td class="head">Health Regen:</td>
<td>7.25</td>
</tr>
<tr>
<td class="head">Energy:</td>
<td>200</td>
<td class="head">Energy Regen:</td>
<td>50</td>
</tr>
<tr>
<td class="head">Damage:</td>
<td>53 (+3.2 / per level)</td>
<td class="head">Attack Speed:</td>
<td>0.694 (+3.1 / per level)</td>
</tr>
<tr>
<td class="head">Attack Range:</td>
<td>125</td>
<td class="head">Movement Speed:</td>
<td>325</td>
</tr>
<tr>
<td class="head">Armor:</td>
<td>16.5 (+3.5 / per level)</td>
<td class="head">Magic Resistance:</td>
<td>30 (+1.25 / per level)</td>
</tr>
<tr>
<td class="head">Influence Points (IP):</td>
<td>3150</td>
<td class="head">Riot Points (RP):</td>
<td>975</td>
</tr>
</tbody>
</table>
I'd like to match the first <td class...> and the following line in one regex :/
Description
This regex will find td tags and return them in groups of two.
<td\b[^>]*>([^<]*)<\/td>[^<]*<td\b[^>]*>([^<]*)<\/td>
Summary
<td\b[^>]*> find the first td tag and consume any attributes
([^<]*) capture the first inner text, this can be greedy but we assume the cell has no nested tags
<\/td> find the close tag
[^<]* move past all the rest of the text until you, this assumes there are no additional tags between the first and second td tag
<td\b[^>]*> find the second td tage and consume any attributes
([^<]*) capture the second inner text, this can be greedy but we assume the cell has no nested tags
<\/td> find the close tag
Groups
Group 0 will get the entire string
will have the first td group
will have the second td group
VB.NET Code Example:
Imports System.Text.RegularExpressions
Module Module1
Sub Main()
Dim sourcestring as String = "replace with your source string"
Dim re As Regex = New Regex("<td\b[^>]*>([^<]*)<\/td>[^<]*<td\b[^>]*>([^<]*)<\/td>",RegexOptions.IgnoreCase OR RegexOptions.Singleline)
Dim mc as MatchCollection = re.Matches(sourcestring)
Dim mIdx as Integer = 0
For each m as Match in mc
For groupIdx As Integer = 0 To m.Groups.Count - 1
Console.WriteLine("[{0}][{1}] = {2}", mIdx, re.GetGroupNames(groupIdx), m.Groups(groupIdx).Value)
Next
mIdx=mIdx+1
Next
End Sub
End Module
$matches Array:
(
[0] => Array
(
[0] => <td class="head">Health Points:</td>
<td>445 (+85 / per level)</td>
[1] => <td class="head">Health Regen:</td>
<td>7.25</td>
[2] => <td class="head">Energy:</td>
<td>200</td>
[3] => <td class="head">Energy Regen:</td>
<td>50</td>
[4] => <td class="head">Damage:</td>
<td>53 (+3.2 / per level)</td>
[5] => <td class="head">Attack Speed:</td>
<td>0.694 (+3.1 / per level)</td>
[6] => <td class="head">Attack Range:</td>
<td>125</td>
[7] => <td class="head">Movement Speed:</td>
<td>325</td>
[8] => <td class="head">Armor:</td>
<td>16.5 (+3.5 / per level)</td>
[9] => <td class="head">Magic Resistance:</td>
<td>30 (+1.25 / per level)</td>
[10] => <td class="head">Influence Points (IP):</td>
<td>3150</td>
[11] => <td class="head">Riot Points (RP):</td>
<td>975</td>
)
[1] => Array
(
[0] => Health Points:
[1] => Health Regen:
[2] => Energy:
[3] => Energy Regen:
[4] => Damage:
[5] => Attack Speed:
[6] => Attack Range:
[7] => Movement Speed:
[8] => Armor:
[9] => Magic Resistance:
[10] => Influence Points (IP):
[11] => Riot Points (RP):
)
[2] => Array
(
[0] => 445 (+85 / per level)
[1] => 7.25
[2] => 200
[3] => 50
[4] => 53 (+3.2 / per level)
[5] => 0.694 (+3.1 / per level)
[6] => 125
[7] => 325
[8] => 16.5 (+3.5 / per level)
[9] => 30 (+1.25 / per level)
[10] => 3150
[11] => 975
)
)
Disclaimer
Parsing html with a regex is really not the best solution as there a ton of edge cases what we can't predict. However in this case if input string is always this basic, and you're willing to accept the risk of the regex not working 100% of the time, then this solution would probably work for you.
I am following Steven Sanderson's blog post here to create an editable and variable length list of items. In his post he uses divs to display a new item in the list but I am using a table. Thus, my partial view for each item is rendering a tr tag with the various fields to edit. Right now my partial view looks something like this:
<tr>
#using (Html.BeginCollectionItem("LineItems"))
{
<td>
#Html.TextBoxFor(m => m.Description)
#Html.ValidationMessageFor(m => m.Description)
</td>
<td>
#Html.TextBoxFor(m => m.Quantity)
#Html.ValidationMessageFor(m => m.Quantity)
</td>
<td>
#Html.TextBoxFor(m => m.Amount)
#Html.ValidationMessageFor(m => m.Amount)
</td>
}
</tr>
This actually renders correctly on all browsers I have tested but the problem is that this really generates invalid HTML as it places a hidden input tag right after the opening tr tag.
<tr>
<input type="hidden" name="LineItems.index" .... />
<td>
...
</td>
...
</tr>
There is a comment by another user on the linked post that says you can move the using statement into the first tag and it works but I haven't been able to get this to work using ASP.NET MVC 3 and the Razor view engine.
Does anyone have any idea how to use the logic presented by Steven Sanderson but get the hidden index input field inside the first td so as not to generate invalid HTML?
Thanks
After a bit of experimenting I came up with:
<tr>
<td>
#using (Html.BeginCollectionItem("LineItems"))
{
#Html.TextBoxFor(m => m.Description)
#Html.ValidationMessageFor(m => m.Description)
#:</td>
#:<td>
#Html.TextBoxFor(m => m.Quantity)
#Html.ValidationMessageFor(m => m.Quantity)
#:</td>
#:<td>
#Html.TextBoxFor(m => m.Amount)
#Html.ValidationMessageFor(m => m.Amount)
}
</td>
</tr>
that did the trick for me.