TreeBuilder Get embedded nodes - html

Basically, I need to get the names and emails from all of these people in the HTML code.
<thead>
<tr>
<th scope="col" class="rgHeader" style="text-align:center;">Name</th><th scope="col" class="rgHeader" style="text-align:center;">Email Address</th><th scope="col" class="rgHeader" style="text-align:center;">School Phone</th>
</tr>
</thead><tbody>
<tr class="rgRow" id="ctl00_ContentPlaceHolder1_rg_People_ctl00__0">
<td>
Michael Bowen
</td><td>mbowen#cpcisd.net</td><td>903-488-3671 ext3200</td>
</tr><tr class="rgAltRow" id="ctl00_ContentPlaceHolder1_rg_People_ctl00__1">
<td>
Christian Calixto
</td><td>calixtoc#cpcisd.net</td><td>903-488-3671 x 3430</td>
</tr><tr class="rgRow" id="ctl00_ContentPlaceHolder1_rg_People_ctl00__2">
<td>
Rachel Claxton
</td><td>claxtonr#cpcisd.net</td><td>903-488-3671 x 3450</td>
</tr>
</tbody>
</table><input id="ctl00_ContentPlaceHolder1_rg_People_ClientState" name="ctl00_ContentPlaceHolder1_rg_People_ClientState" type="hidden" autocomplete="off"> </div>
<br>
I know how to use treebuilder with the nodes and such, and I'm using this code in some of my script.
my ($file) = #_;
my $html = path($file)-> slurp;
my $tree = HTML::TreeBuilder->new_from_content($html);
my #nodes = $tree->look_down(_tag => 'input');
my $val;
foreach my $node (#nodes) {
$val = $node->look_down('name', qr/\$txt_Website/)->attr('value');
}
return $val;
I was going to use the same code for this function, but I realized that I don't have much to search for, since the <td> tag is in so many other places in the script. I'm sure there's a better way to approach this problem, but I can't seem to find it.
LINK TO HTML CODE: http://pastebin.com/qLwu80ZW
MY CODE: https://pastebin.com/wGb0eXmM
Note: I did look on google as much as possible, but I'm not quite sure what I should search for.

The table element that encloses the data you need has a unique class rgMasterTable so you can search for that in look_down
I've written this to demonstrate. It pulls the HTML directly from your pastebin
use strict;
use warnings 'all';
use LWP::Simple 'get';
use HTML::TreeBuilder;
use constant URL => 'http://pastebin.com/raw/qLwu80ZW';
my $tree = HTML::TreeBuilder->new_from_content(get URL);
my ($table) = $tree->look_down(_tag => 'table', class => 'rgMasterTable');
for my $tr ( $table->look_down(_tag => 'tr') ) {
next unless my #td = $tr->look_down(_tag => 'td');
my ($name, $email) = map { $_->as_trimmed_text } #td[0,1];
printf "%-17s %s\n", $name, $email;
}
output
Michael Bowen mbowen#cpcisd.net
Christian Calixto calixtoc#cpcisd.net
Rachel Claxton claxtonr#cpcisd.net

Related

My foreach loop is not working as the previous I've done

I'm new ton Laravel (also to StackOverflow), and I'm trying to show data in my home.blade.php table from PhpMyAdmin using a foreach loop. However, it's not working correctly, and I can't figure out where the problem is. I have other tables working with foreach, and I've followed the same steps with this table.
User Model
protected $table = 'users';
protected $fillable = ['id','name','edad','direccion_personal','celular','foto','email','direccion_sucursal_id'];
UserController
public function index()
{
$Usuarios = User::all();
$array = ['usuarios' => $Usuarios];
return view('home')->with($array);
}
Finally, here's my tbody:
<tbody>
#foreach ($usuarios as $Usuarios)
<div>
<tr>
<th scope="row" style="text-align:center;">{{ $Usuarios->id }}</th>
<td style="text-align:center;">{{ $Usuarios->nombre }}</td>
.
.
.
</tr>
</div>
</tbody>
#endforeach
Why the array?
public function index(){
$usuarios = User::all();
return view('home', compact('usuarios'));
}
Then:
<tbody>
#foreach ($usuarios as $us)
<div>
<tr>
<th scope="row" style="text-align:center;">{{$us->id}}</th>
<td style="text-align:center;">{{$us->nombre}}</td>
.
.
.
</tr>
</div>
#endforeach
</tbody>
I see you're having troubles with the foreach loop. is not working correctly... but, I'm not sure what kind of problem is... if my answer does not work for you, please update your question so you can get more help
I see you close your inside the foreach loop.
That way you will end with lots of closing tags with just one opening...
Try moving that close tag outside the loop
<tbody>
#foreach ($usuarios as $Usuarios)
<div>
<tr>
<th scope="row" style="text-align:center;">{{$Usuarios->id}}</th>
<td style="text-align:center;">{{$Usuarios->nombre}}</td>
.
.
.
</tr>
</div>
#endforeach
</tbody>
Your foreach closes outside the </tbody> tag, and opens inside it. Your table body is thus closed after the first iteration of the loop, and never opened again, so with each iteration you now have an additional </tbody> line. This is invalid markup, and will break your site's output.

How can I populate an HTML <select> element with values from a database?

I am trying to get values from a database and place them in a dropdown list within an HTML <select> tag.
I'm able to get the values in a long string and display all of them within a single option but I want to put each value in a separate <option> tag. I just don't know what logic I could use to do this.
Here's what I have so far:
#!c:\perl\bin\perl.exe
use CGI;
require ("data_eXchangeSubs.pm");
$query = new CGI;
print $query->header(-expires=>'-1d');
print $query->start_html(
-title=>'Dex Vendor Testing',
-bgcolor=>'white'
);
$user = $query->param("user");
my $dataX = ${ConnectToDatabase($main::DBone, $main::dataENV)};
$resultSet = $dataX->Execute("select vendor from dex_vendor_info group by vendor");
while(!$resultSet->EOF) {
$vendors .= $resultSet->Fields("vendor")->Value."\n";
$resultSet->MoveNext;
}
print <<ONE;
<table width=75% border=0>
<th colspan=2 align=left><strong><font size=5pt color=#FF6633 face=garamond>Vendor Information</strong</font><hr size=4pt color=midnightblue></th>
<tr>
<td align=left nowrap><font size=4pt face=garamond><label id=lVendor for=vendor><strong>Company Name</strong></font></label></td>
<td align=left nowrap><font size=4pt face=garamond><label id=lVendor for=vendor><strong>Contact's Name</strong></font></label></td>
</tr>
<tr>
<td align=left nowrap><select id="vendors">
<option>$vendors</option>
</td>
</td>
<td align=left nowrap><input type=text name="contact" id=contact value="" size=25></td>
</tr>
</table>
<br>
ONE
print $vendors;
print $query->end_html;
If you're using CGI, then use CGI.
print $query->popup_menu(
-name => 'vendors'
, -values => \#list_of_vendors
, -default => $default_vendor
);
And you get #list_of_vendors in your row processing loop:
my #list_of_vendors;
while(!$resultSet->EOF) {
push #list_of_vendors, $resultSet->Fields("vendor")->Value;
$resultSet->MoveNext;
}
If you want labels to be a different text value from values include -labels tag in the call and point it to an array ref containing the text you want visible.

Creating multiple records with the v10 REST API in SugarCRM

In the old v4.x API's it was possible to create or update multiple records in one POST request, but in the new v10 REST API this is no longer documented. Does anyone know how to do it? Or if it's even possible?
I tried a few things, like POSTing the records as a JSON array, but that will only create one empty record.
[{"name":"Case 2"},{"name":"Case 3"}]
Alternatively if there's a use case in SugarCRM where more than one record is created or updated, that's fine as well. I can easily use Fiddler to read how they format the JSON and then use that myself.
The v10 API has a "bulk" endpoint that allows you to submit multiple API calls at once.
view {url}/rest/v10/help and scroll down to /bulk for more details
I recently ran into this myself, and also found no documentation on this or any API function available in v10. I personally had a real need for this and found that the best solution would be to create a custom API entry point.
Here is the code that I wrote in order to accomplish multiple entry submission. It does not provide any error handling and was written to be specific to my needs, but this should cover most cases. Once these files are created you must run a quick repair rebuild from the Administration dashboard "Admin >> Repair >> Quick Repair and Rebuild" This is required to register the new entry point.
File: custom/clients/base/api/SetEntriesApi.php
<?php
/*
* Copyright (C) 2014 DirectPay
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
if (!defined('sugarEntry') || !sugarEntry)
die('Not A Valid Entry Point');
class SetEntriesApi extends SugarApi {
public function registerApiRest() {
return array(
//POST
'SetEntries' => array(
//request type
'reqType' => 'POST',
//endpoint path
'path' => array('record', 'set_entries'),
//method to call
'method' => 'setEntriesMethod',
//short help string to be displayed in the help documentation
'shortHelp' => 'Provides functionality to create & update multiple records.',
//long help to be displayed in the help documentation
'longHelp' => 'custom/clients/base/api/help/SetEntriesApi_help.html',
),
);
}
public function setEntriesMethod($api, $args) {
if (empty($args)) {
return false;
}
$results = array();
foreach ($args as $module => $records) {
if (is_array($records)) {
foreach ($records as $fieldsArray) {
$sugarBean = $this->_processEntry($module, $fieldsArray);
$results[$module][] = $sugarBean->id;
}
}
}
return $results;
}
private function _processEntry($module, $fieldsArray) {
if (array_key_exists('id', $fieldsArray)) {
$sugarBean = BeanFactory::retrieveBean($module, $fieldsArray['id']);
} else {
$sugarBean = BeanFactory::newBean($module);
}
if (is_null($sugarBean)) {
return null;
}
foreach ($fieldsArray as $field => $data) {
$sugarBean->$field = $data;
}
$sugarBean->save();
return $sugarBean;
}
}
?>
File: custom/clients/base/api/help/SetEntriesApi_help.html
<h2>Overview</h2>
<span class="lead">
This is a custom setEntries endpoint. This is used to create or update
multiple modules and records with one call. This was originally available in
the older versions of the API, but was removed in v10. This is not a ported
version from v4.1 and rather a quick recreation of that functionality modified
slightly to allow for multiple modules.
</span>
<h2>Path Variables</h2>
<span class="lead">
This endpoint does not accept any path variables.
</span>
<h2>Input Parameters</h2>
<table class="table table-hover">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
args
</td>
<td>
Array
</td>
<td>
Data array to pass to the endpoint.
</td>
</tr>
</tbody>
</table>
<h2>Result</h2>
<table class="table table-hover">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
results
</td>
<td>
Array
</td>
<td>
Array of modules that contain a nested array of the IDs of the updated records and/or newly created record.
</td>
</tr>
</tbody>
</table>
<h3>Output Example</h3>
<pre class="pre-scrollable">
{
"Accounts": [
"92e26a99-9e7a-3dca-9ab0-53c6d6833d5f",
"991b8007-a517-0c8b-6b69-53c6d6fd70fb",
"9a129144-0f61-e808-00c2-53c6d674bd04",
"addc4404-ae4a-c031-586b-53c6d60f70dd"
]
}
</pre>
<h2>Change Log</h2>
<table class="table table-hover">
<thead>
<tr>
<th>Version</th>
<th>Change</th>
</tr>
</thead>
<tbody>
<tr>
<td>
v10
</td>
<td>
Added <code>/record/set_entries</code> POST endpoint.
</td>
</tr>
</tbody>
</table>
The custom entry point iterates through the multidimensional array and creates or updates the records individually using the CRUD handling in BeanFactory. In order to update an existing record an id must be passed with the record. Here is an example of the json code that is passed to the endpoint.
JSON code:
{
"Contacts": {
"id": "9a129144-0f61-e808-00c2-53c6d674bd04",
"name": "Contact Name"
},
"Accounts": {
"name": "Account Name"
}
}
I hope this helps!
The response of #TO_web really helped me a lot, but the json that is passed to the endpoint must be this way:
{"Contacts":
[
{
"id":"89905d08-5c98-604e-9f49-55d5e670161b",
"custom_field":"Testing"
}
],
"Accounts":
[
{
"name":"Testing"
}
]
}

How to read the values of a table in HTML file and Store them in Perl?

I read many questions and many answers but I couldn't find a straight answer to my question. All the answers were either very general or different from what I want to do. I got so far that i need to use HTML::TableExtract or HTML::TreeBuilder::XPath but I couldn't really use them to store the values. I could somehow get table row values and show them with Dumper.
Something like this:
foreach my $ts ($tree->table_states) {
foreach my $row ($ts->rows) {
push (#fir , (Dumper $row));
} }
print #sec;
But this is not really doing what I'm looking for. I will add the structure of the HTML table that I want to store the values:
<table><caption><b>Table 1 </b>bla bla bla</caption>
<tbody>
<tr>
<th ><p>Foo</p>
</th>
<td ><p>Bar</p>
</td>
</tr>
<tr>
<th ><p>Foo-1</p>
</th>
<td ><p>Bar-1</p>
</td>
</tr>
<tr>
<th ><p>Formula</p>
</th>
<td><p>Formula1-1</p>
<p>Formula1-2</p>
<p>Formula1-3</p>
<p>Formula1-4</p>
<p>Formula1-5</p>
</td>
</tr>
<tr>
<th><p>Foo-2</p>
</th>
<td ><p>Bar-2</p>
</td>
</tr>
<tr>
<th ><p>Foo-3</p>
</th>
<td ><p>Bar-3</p>
<p>Bar-3-1</p>
</td>
</tr>
</tbody>
</table>
It would be convenient if I can store the row values as pairs together.
expected output would be something like an array with values of:
(Foo , Bar , Foo-1 , Bar-1 , Formula , Formula-1 Formula-2 Formula-3 Formula-4 Formula-5 , ....)
The important thing for me is to learn how to store the values of each tag and how to move around in the tag tree.
Learn XPath and DOM manipulation.
use strictures;
use HTML::TreeBuilder::XPath qw();
my $dom = HTML::TreeBuilder::XPath->new;
$dom->parse_file('10280979.html');
my %extract;
#extract{$dom->findnodes_as_strings('//th')} =
map {[$_->findvalues('p')]} $dom->findnodes('//td');
__END__
# %extract = (
# Foo => [qw(Bar)],
# 'Foo-1' => [qw(Bar-1)],
# 'Foo-2' => [qw(Bar-2)],
# 'Foo-3' => [qw(Bar-3 Bar-3-1)],
# Formula => [qw(Formula1-1 Formula1-2 Formula1-3 Formula1-4 Formula1-5)],
# )

HTML form with Zend Form filters/validators

I'm creating a simple contact form within my ZF application. It doesn't feel like it's worth the trouble to manipulate decorators for only a few form elements.
My Question is: am I able to still use Zend Form Filters on elements that are not created with Zend Form:
For Example:
The Form:
<!-- Standard HTML - not generated with ZF -->
<form id="contact-form" method="post" action="/contact/submit">
<input type="text" name="name" />
<input type="email" name="email" />
<input type="submit" name="submit" />
</form>
The Controller:
public function submitAction()
{
$params = $this->_request->getParams();
//Am I able to apply filters/validators to the data I get from the request?
//What is the best way to handle this?
}
I took a look at this (the answer from Darcy Hastings) - and it seems like it would work, it just feels a bit hacky.
Any and all advice appreciated.
Thanks,
Ken
yes, you can use Zend_Filter_Input, here is an example of how to set it up.
//set filters and validators for Zend_Filter_Input
$filters = array(
'trackid' => array('HtmlEntities', 'StripTags')
);
$validators = array(
'trackid' => array('NotEmpty', 'Int')
);
//assign Input
$input = new Zend_Filter_Input($filters, $validators);
$input->setData($this->getRequest()->getParams());
//check input is valid and is specifically posted as 'Delete Selected'
if ($input->isValid()) {
also you may consider using the viewscript decorator to render a Zend Form, The control is absolute (or almost).:
//in your controller action
public function indexAction() {
//a normally constructed Zend_Form
$form = new Member_Form_Bid();
$form->setAction('/member/bid/preference');
//attach a partial to display the form, this is the decrator
$form->setDecorators(array(
array('ViewScript', array('viewScript' => '_bidForm.phtml'))
));
$this->view->form = $form;
//the view
<?php echo $this->form?>
//the partial
//use a normal Zend_Form and display only the parts you want
//processing in an action is done like any other Zend_Form
form action="<?php echo $this->element->getAction() ?>"
method="<?php echo $this->element->getMethod() ?>">
<table id="sort">
<tr>
<th colspan="2">Sort By Shift</th>
<th colspan="2">Sort By Days Off</th>
<th colspan="2">Sort By Bid Location</th>
</tr>
<tr></tr>
<tr>
<td class="label"><?php echo $this->element->shift->renderLabel() ?></td>
<td class="element"><?php echo $this->element->shift->renderViewHelper() ?></td>
<td class="label"><?php echo $this->element->weekend->renderLabel() ?></td>
<td class="element"><?php echo $this->element->weekend->renderViewHelper() ?></td>
<td class="label"><?php echo $this->element->bidlocation->renderLabel() ?></td>
<td class="element"><?php echo $this->element->bidlocation->renderViewHelper() ?></td>
</tr>
<tr></tr>
<tr>
<td colspan="6" style="text-align: center"><?php echo $this->element->submit ?></td>
</tr>
</table>
</form>
Yes, you definitely can use Zend_Form on self-rendered forms.
You can do this in two ways:
Use a Zend_Form object, but don't render it. You create a Zend_Form instance as usual, with all the elements named correctly and attach validators and filters as per normal. In your action, you can then check the form's isValid() and use getValues() to ensure that you collect the filtered data.
The second option is to use Zend_Filter_Input which is a chain of validators and filters. You set up your validators and filters at construction and then call setData to populate the filter with the information from the request. Again, you have isValid() to test and then you use getUnescaped() to retrieve the data. The manual page has more details.