retrieval logic is like this... there is a collection USERS, with each user i associate an array [] which contains, ID of files.
I have another collection TraceInfo, which contains actual Files with their Respective IDs.
and i was retrieving info about files using this logic.. which works absolutely fine.
$doc = $this->col_users->findOne(array('_id'=>$this->options['user_id']), array($array_name=>True));
$doc[$array_name] = (isset($doc[$array_name])) ? $doc[$array_name] : array();
$cursor = $this->col_trace_info ->find(array('_id'=>array('$in'=>$doc[$array_name])),
array('name'=>True, 'size'=>True, 'notes'=>True, 'shared_flag'=>True, 'is_radius'=>True))
->sort(array('_id'=>-1));
$file_list = array();
if($cursor->count() > 0)
foreach ($cursor as $doc) {
if ($iteration_method == 'get_file_object') {
if ($shared_in) $doc['shared_in'] = True;
else $doc['shared_in'] = False;
$file_list[] = $doc;
}
else if ($iteration_method == 'is_valid_file_object') {
$file_list[] = $doc['_id'];
}
}
return array_values(array_filter(array_map(
array($this, $iteration_method),
$file_list
)));
Only change that i made is, now i want to store same file ID [] is Customer Collection as well, n retrieve files belonging to same customer.
for which, this is the section of code i have changed, but it seem to not, work... i guess mistake might be in query, i checked in UMONGO, customer's associative array which contains file ID got updated.
Here is the Code for that.
Can anybody tell be what is wrong with query, or what changes do i need to make in order do, what i desire. (retrieve files which belong to particular customer)
$doc = $this->col_customers->findOne(array('cust_id'=>$this->options['cust_id']), array($array_name=>True));
$doc[$array_name] = (isset($doc[$array_name])) ? $doc[$array_name] : array();
$cursor = $this->col_trace_info ->find(array('cust_id'=>array('$in'=>$doc[$array_name])),
array('name'=>True, 'size'=>True, 'notes'=>True, 'shared_flag'=>True, 'is_radius'=>True))
->sort(array('cust_id'=>-1));
$file_list = array();
if($cursor->count() > 0)
foreach ($cursor as $doc) {
if ($iteration_method == 'get_file_object') {
$file_list[] = $doc;
}
else if ($iteration_method == 'is_valid_file_object') {
$file_list[] = $doc['cust_id'];
}
}
return array_values(array_filter(array_map(
array($this, $iteration_method),
$file_list
)));
$cursor = $this->col_trace_info ->find(array('_id'=>array('$in'=>$doc[$array_name])),
array('name'=>True, 'size'=>True, 'notes'=>True, 'shared_flag'=>True, 'is_radius'=>True))
->sort(array('_id'=>-1));
sillly mistake, was searching the col_trace_info by cust_id, whereas needed to search it by _Id, this is primary key for collection of traces.
Related
As you can see I have a majority of the step done. My goal is to create a basic shopping list using 0 for not checked off, and 1 for checked off. If a user inputs the name of the list and the item they wish check off the list the 0 will be replaced by a 1. I know I have to loop over each row in the csv and then edit the item the user inputs in the terminal. However I think I did something slightly wrong in the while loop and need help on where to fix. Here is my code:
<?php
$args = $argv;
if(!isset($args[2])) {
echo 'Not given a shopping list title or item to edit!' . PHP_EOL;
exit(1);
}
$listName = $args[1];
$fileName = $listName . '.csv';
$path = __DIR__ . '/../storage/' . $fileName;
$resource = fopen($path, 'a+');
$item = $args[2];
$rows = [];
while(($row = fgetcsv($resource)) !== false) {
$rows[] = $row;
if($rows === $item) {
$item[1] = 1;
}
while($rows == 0) {
fputcsv($resource, $rows);
}
}
fclose($resource);
Here is my csv:
bananas,0
apples,0
lettuce,0
potatoes,0
pasta,0
rice,0
tofu,0
tempeh,0
berries,0
For example if the user wishes to check off rice the 0 will be replaced with a 1.
Edit: The code works up until if($rows === $item) statement. What I am doing with while(($row=fgetcsv($resource)) !== false) { $rows[] = $row; } is get each row of the csv in one array because when I ran the code I only got the first line of the code. And then I add it to the empty rows array to make each entry (there are 9 of them to be in the same array. So when a user wishes to check an item off the list each item will be in the same array and easier to refer to.
This part
if($rows === $item) {
$item[1] = 1;
}
while($rows == 0) {
fputcsv($resource, $rows);
}
I am unsure about because I want to target the 1st index point of whatever item the user types in and wants to check off.
I'm working on a project in which I pull various statistics about the NHL and inserting them into an SQL table. Presently, I'm working on the scraping phase, and have found an XML parser that I've implemented, but I cannot for the life of me figure out how to pull information from it. The table can be found here -> http://www.tsn.ca/datafiles/XML/NHL/standings.xml.
The parser supposedly generates a multi-dimmensional array, and I'm simply trying to pull all the stats from the "info-teams" section, but I have no idea how to pull that information from the array. How would I go about pulling the number of wins Montreal has? (Solely as an example for the rest of the stats)
This is what the page currently looks like -> http://mattegener.me/school/standings.php
here's the code:
<?php
$strYourXML = "http://www.tsn.ca/datafiles/XML/NHL/standings.xml";
$fh = fopen($strYourXML, 'r');
$dummy = fgets($fh);
$contents = '';
while ($line = fgets($fh)) $contents.=$line;
fclose($fh);
$objXML = new xml2Array();
$arrOutput = $objXML->parse($contents);
print_r($arrOutput[0]); //This print outs the array.
class xml2Array {
var $arrOutput = array();
var $resParser;
var $strXmlData;
function parse($strInputXML) {
$this->resParser = xml_parser_create ();
xml_set_object($this->resParser,$this);
xml_set_element_handler($this->resParser, "tagOpen", "tagClosed");
xml_set_character_data_handler($this->resParser, "tagData");
$this->strXmlData = xml_parse($this->resParser,$strInputXML );
if(!$this->strXmlData) {
die(sprintf("XML error: %s at line %d",
xml_error_string(xml_get_error_code($this->resParser)),
xml_get_current_line_number($this->resParser)));
}
xml_parser_free($this->resParser);
return $this->arrOutput;
}
function tagOpen($parser, $name, $attrs) {
$tag=array("name"=>$name,"attrs"=>$attrs);
array_push($this->arrOutput,$tag);
}
function tagData($parser, $tagData) {
if(trim($tagData)) {
if(isset($this->arrOutput[count($this->arrOutput)-1]['tagData'])) {
$this->arrOutput[count($this->arrOutput)-1]['tagData'] .= $tagData;
}
else {
$this->arrOutput[count($this->arrOutput)-1]['tagData'] = $tagData;
}
}
}
function tagClosed($parser, $name) {
$this->arrOutput[count($this->arrOutput)-2]['children'][] = $this->arrOutput[count($this- >arrOutput)-1];
array_pop($this->arrOutput);
}
}
?>
add this search function to your class and play with this code
$objXML = new xml2Array();
$arrOutput = $objXML->parse($contents);
// first param is always 0
// second is 'children' unless you need info like last updated date
// third is which statistics category you want for example
// 6 => the array you want that has wins and losses
print_r($arrOutput[0]['children'][6]);
//using the search function if key NAME is Montreal in the whole array
//result will be montreals array
$search_result = $objXML->search($arrOutput, 'NAME', 'Montreal');
//first param is always 0
//second is key name
echo $search_result[0]['WINS'];
function search($array, $key, $value)
{
$results = array();
if (is_array($array))
{
if (isset($array[$key]) && $array[$key] == $value)
$results[] = $array;
foreach ($array as $subarray)
$results = array_merge($results, $this->search($subarray, $key, $value));
}
return $results;
}
Beware
this search function is case sensitive it needs modifications like match to
a percentage the key or value changing capital M in montreal to lowercase will be empty
Here is the code I sent you working in action. Pulling the data from the same link you are using also
http://sjsharktank.com/standings.php
I have actually used the same exact XML file for my own school project. I used DOM Document. The foreach loop would get the value of each attribute of team-standing and store the values. The code will clear the contents of the table standings and then re-insert the data. I guess you could do an update statement, but this assumes you never did any data entry into the table.
try {
$db = new PDO('sqlite:../../SharksDB/SharksDB');
$db->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
} catch (Exception $e) {
echo "Error: Could not connect to database. Please try again later.";
exit;
}
$query = "DELETE FROM standings";
$result = $db->query($query);
$xmlDoc = new DOMDocument();
$xmlDoc->load('http://www.tsn.ca/datafiles/XML/NHL/standings.xml');
$searchNode = $xmlDoc->getElementsByTagName( "team-standing" );
foreach ($searchNode as $searchNode) {
$teamID = $searchNode->getAttribute('id');
$name = $searchNode->getAttribute('name');
$wins = $searchNode->getAttribute('wins');
$losses = $searchNode->getAttribute('losses');
$ot = $searchNode->getAttribute('overtime');
$points = $searchNode->getAttribute('points');
$goalsFor = $searchNode->getAttribute('goalsFor');
$goalsAgainst = $searchNode->getAttribute('goalsAgainst');
$confID = $searchNode->getAttribute('conf-id');
$divID = $searchNode->getAttribute('division-id');
$query = "INSERT INTO standings ('teamid','confid','divid','name','wins','losses','otl','pts','gf','ga')
VALUES ('$teamID','$confID','$divID','$name','$wins','$losses','$ot','$points','$goalsFor','$goalsAgainst')";
$result= $db->query($query);
}
Let's assume we want to process this Feed: http://tools.forestview.eu/xmlp/xml_feed.php?aid=1094&cid=1000
I'm trying to show the nodes of an XML file this way:
deals->deal->dealsite
deals->deal->deal_id
deals->deal->deal_title
This is in order to be able to process feeds that we don't know what their XML tags are. So we will let the user choose that deals->deal->deal_title is the Deal Title and will recognize it that way.
I have been trying ages to do this with this code:
class HandleXML {
var $root_tag = false;
var $xml_tags = array();
var $keys = array();
function parse_recursive(SimpleXMLElement $element)
{
$get_name = $element->getName();
$children = $element->children(); // get all children
if (empty($this->root_tag)) {
$this->root_tag = $this->root_tag.$get_name;
}
$this->xml_tags[] = $get_name;
// only show children if there are any
if(count($children))
{
foreach($children as $child)
{
$this->parse_recursive($child); // recursion :)
}
}
else {
$key = implode('->', $this->xml_tags);
$this->xml_tags = array();
if (!in_array($key, $this->keys)) {
if (!strstr('>', $key) && count($this->keys) > 0) { $key = $this->root_tag.'->'.$key; }
if (!in_array($key, $this->keys)) {
$this->keys[] = $key;
}
}
}
}
}
$xml = new SimpleXMLElement($feed_url, null, true);
$handle_xml = new HandleXML;
$handle_xml->parse_recursive($xml);
foreach($handle_xml->keys as $key) {
echo $key.'<br />';
}
exit;
but here's what I get instead:
deals->deal->dealsite
deals->deal_id
deals->deal_title
See on 2nd and 3rd line the deal-> part is missing.
I have also tried with this code: http://pastebin.com/FkPWXF64 but it's definitely not the best way to go and it doesn't always work.
No matter how many times I couldn't do it.
In one of my sites I use a little different approach to handle xml feed. In your case it would look like:
$xml = simplexml_load_file("http://tools.forestview.eu/xmlp/xml_feed.php?aid=1094&cid=1000");
foreach($xml->{'deal'} as $deal)
{
$dealsite = $deal->{'dealsite'};
$dael_id = $deal->{'dael_id'};
$deal_title = $deal->{'deal_title'};
$deal_url = $deal->{'deal_url'};
$deal_city = $deal->{'deal_city'};
$deal_category = $deal->{'deal_category'};
// and so on for the rest
// do some stuff with the variables like insert into MySQL
}
This is going to be my first time building an associative array. And if anyone can help me I would be grateful.
Basically, I want to loop through a directory of XML files. I want to find out if a certain editor was the editor of this file, and if the query is true, I would like to grab two pieces of information and achieve the result of an associate array with those two pieces of information for every case where the editor's name is found.
So here's what I have got so far:
function getTitleandID($editorName) {
$listofTitlesandIDs = array();
$filename = readDirectory('../editedtranscriptions');
foreach($filename as $file)
{
$xmldoc = simplexml_load_file("../editedtranscriptions/$file");
$xmldoc->registerXPathNamespace("tei", "http://www.tei-c.org/ns/1.0");
if ($editorName == $xmldoc->xpath("//tei:editor[#role='PeerReviewEditor']/text()"))
{
$title = $xmldoc->xpath("//tei:teiHeader/tei:title[1]");
$id = $xmldoc->xpath("//tei:text/tei:body/tei:div/#xml:id[1]");
$listofTitlesandIDs[] = //I don't know what to do here
}
else
{
$listofTitlesandIDs = null;
}
}
return $listofTitlesandIDs
}
This is about where I get stuck. I'd like to be able have $listofTitlesandIDs as an associative array where I could call up the values for two different keys, e.g. $listofTitlesandIDs['title'] and $listofTitlesandIDs[$id]
So that's about it. I'm grateful for any help you have time to provide.
Well I'm sure this is a little clumsy (the result of an amateur) but it has given me the result I want.
function getTitlesandIDs($EditorName) //gets titles and IDs for given author
{
$list = array();
$filename = readDirectory('../editedtranscriptions');
foreach($filename as $file)
{
$xmldoc = simplexml_load_file("../editedtranscriptions/$file");
$xmldoc->registerXPathNamespace("tei", "http://www.tei-c.org/ns/1.0");
$title = $xmldoc->xpath("//tei:teiHeader/tei:fileDesc/tei:titleStmt/tei:title[1]");
$id = $xmldoc->xpath("//tei:text/tei:body/tei:div/#xml:id");
$editorName = $xmldoc->xpath("//tei:editor[#role='PeerReviewEditor']/text()")
if ($editorName[0] == "$EditorName")
{
$result = array("title"=>$title[0], "id"=>$id[0]);
$list[] = $result;
}
}
return $list;
}
With this I can call the function $list = getTitlesandIDs('John Doe') and then access both the title and id in the associative array for each instance. Like so:
foreach ($list as $instance)
{
echo $instance['title'];
echo $instance['id'];
}
Maybe that will help somebody some day -- let me know if you have any advice on making this more elegant.
$listofTitlesandIDs[$id] = $title;
You should loop over the array then using the foreach loop.
I have a set of structured data, that I'm trying to merge together, based on a set of conditions.
There is a set of rows, returned from the db. Each row has a course id, and a discipline id. There's an equal amount of disciplines in each course, but some disciplines are repeated in both courses.
I want to build a data structure where if the discipline is in both courses, then it only appears once on a line in a new data structure, and nothing else, but if there are two unmatched disciplines, then they are both included in a new course.
The code I'm using so far, is filtering and removing the keys that are duplicated, and adding them to a new array. This works fine.
However, because I can't control the order in which the data comes (don't ask) I'm having troubles making sure that each line has either a discipline that appears in both courses, or one of each.
I think I need some techniques to help deal with this, and was wondering if anyone had come across this before. I want to avoid making many consecutive loops, if possible.
Thanks.
edit: messy and horrible code below:
function buildDisciplineMap(){
$sql = "SELECT [idcurso]
,[idversao]
,[ordem]
,[bloco]
,[obsbloco]
,[iddisciplina] as idd
,cast([iddisciplina] as TEXT) as iddisciplina
,[descdisciplina]
,[iddepartamento]
,[descdepartamento]
,[ects]
,[horas]
,[idregente]
,[regente]
,[idregente1]
,[regente1]
,[idregente2]
,[regente2]
,[idregente3]
,[regente3]
,cast([objectivos] as TEXT) as objectivos
,cast([programa] as TEXT) as programa
,[descdisciplina_en]
,cast([objectivos_en] as TEXT) as objectivos_en
,cast([programa_en] as TEXT) as programa_en
FROM [proffile2].[dbo].[vw_site_CursosDisciplinas_FEG]
where idcurso = '3512 GE' or idcurso = '3513 ECON' order by idcurso desc ";
$discs = $this->returnObject($sql);
$map = new stdClass();
// find blocos, and titles
foreach ($discs as $key => $value) {
if (isset($map->bloco[$value->bloco])) {
// block already exists
} else {
#echo "making new block";
$map->bloco[$value->bloco] = new stdClass();
}
if (strlen($value->obsbloco)>1) {
$map->bloco[$value->bloco]->title = $value->obsbloco;
}
}
foreach ($map->bloco as $keybloco => $value) {
$map->bloco[$keybloco]->lines = array();
$processed_ids = array();
foreach ($discs as $kd => $vd) {
if ($vd->bloco == $keybloco) {
// check if this discipline occurs more than once in this block
foreach ($discs as $kdd => $vdd) {
if ($vdd->iddisciplina == $vd->iddisciplina && $kdd != $kd && !in_array($kd,$processed_ids) && !in_array($kdd,$processed_ids)) {
// this discipline is for both courses
$details = array();
$details['both'] = $vd;
$map->bloco[$keybloco]->lines[] = $details;
array_push($processed_ids, $kd, $kdd);
unset($discs[$kdd]);
unset($discs[$kd]);
break;
}
}
}
}
}
$processed_ids = array();
foreach ($discs as $key => $value) {
echo $value->idcurso."\n";
}
foreach ($discs as $kd => $vd) {
$bloco = $vd->bloco;
$lastidx =sizeof($map->bloco[$bloco]->lines)-1;
$line = $map->bloco[$bloco]->lines[$lastidx];
echo sizeof($map->bloco[$bloco]->lines);
#pr($line);
if (isset($line['both'])) {
echo "omog - \n ";
$map->bloco[$bloco]->lines[][$vd->idcurso] = $vd;
unset($discs[$kd]);
continue;
}
#pr($line['both']->idcurso);
foreach ($map->bloco[$bloco]->lines as $k => $v) {
echo $k."-";
#echo $v['3513 ECON']->idcurso;
}
if ($line[$vd->idcurso]) {
echo 'add';
$map->bloco[$bloco]->lines[][$vd->idcurso] = $vd;
} else {
echo 'fill';
$map->bloco[$bloco]->lines[sizeof($map->bloco[$bloco]->lines)-1][$vd->idcurso] = $vd;
}
}
echo sizeof($discs);
return $map;
}
You said "don't ask", but I've got to: why can't you control the order of the rows? Aren't you the one writing the database query?
If you think fixing the order of the rows will help you parse and build a new data structure better, why not make sorting the rows the first step in your process? Or, is the data set too large?
You might find some of PHP's array set manipulations to be of use. i.e. array_diff, array_intersect_key etc.