I am trying to parse an XML file. I want to create a project object that has instances such as title,date,version and an array of files that hold all the files within the project. Everything seems to work such as the title,date,and version.
I checked by printing them out to see the results. However, when I try printing out the array to see if the contents are correct, nothing happens. I'm not sure where I'm going wrong.
<?php
require_once('project.php');
require_once('files.php');
function parse()
{
$svn_list = simplexml_load_file("svn_list.xml");
$dir = $svn_list->xpath("//entry[#kind = 'dir']");
foreach ($dir as $node) {
if (strpos($node->name, '/') == false) {
$endProject = initProject($node);
}
}
for ($x = 0; $x <= 7; $x++) {
echo $endProject->fileListArray[$x]->name . "<br />\r\n";
}
}
function initProject($node){
$project = new project();
$project->title = $node->name;
$project->date = $node->commit->date;
$project->version = $node->commit['revision'];
initFiles($node,$project);
return $project;
}
function initFiles($project){
$svn_list = simplexml_load_file("svn_list.xml");
$file = $svn_list->xpath("//entry[#kind ='file']/name[contains(., '$project->title')]/ancestor::node()[1]");
//$file = $svn_list->xpath("//entry[#kind='file']/name[starts-with(., '$project->title')]/..");
foreach($file as $fileObject){
$files = new files();
$files->size = $fileObject->size;
$files->name = $fileObject->name;
array_push($project->fileListArray, $files);
}
}
echo $endProject->fileListArray prints out "Array" 7 times. However echo $endProject->fileListArray[$x]->name does not print anything out.
I'm not sure if the array is just not being initialized or if I'm parsing the XML file incorrectly.
<?xml version="1.0" encoding="UTF-8"?>
<lists>
<list
path="https://subversion....">
<entry
kind="file">
<name>.project</name>
<size>373</size>
<commit
revision="7052">
<author></author>
<date>2016-02-25T20:56:16.138801Z</date>
</commit>
</entry>
<entry
kind="file">
<name>.pydevproject</name>
<size>302</size>
<commit
revision="7052">
<author></author>
<date>2016-02-25T20:56:16.138801Z</date>
</commit>
</entry>
<entry
kind="dir">
<name>Assignment2.0</name>
<commit
revision="7054">
<author></author>
<date>2016-02-25T20:59:11.144094Z</date>
</commit>
</entry>
Your function definition:
function initFiles( $project )
Your function call:
initFiles( $node, $project );
So, the function use $node as $project, but $node doesn't have ->fileListArray property array, so your array_push() fails.
And, in the future, don't forget to activate error checking in our php code:
error_reporting( E_ALL );
ini_set( 'display_errors', 1 );
With error checking, your original code output this error:
PHP Warning: array_push() expects parameter 1 to be array, object given in ...
By default, function arguments are passed by value which means the value of the argument doesn't get changed outside of the function, unless you pass by reference. The PHP docs have more details but I think if you simply change:
function initFiles($project){... to function initFiles(&$project){... (note the &), it will work as you expect.
Related
I'm trying to compare and check the differences between two xml strings but my code is not detecting any changes in xml strings!
for ex my first string contains :
<Result>
<pid>10</pid>
<DocID>29</DocID>
<Response>True</Response>
<DocID>60<DocID>
<Blvd_Name>dfdfdfdfd</Blvd_Name>
<Alley_Name>dfd</Alley_Name>
<Plate_Number>654654</Plate_Number>
<Post_Code>654654654</Post_Code>
<Phone_1>654654</Phone_1>
<Phone_2>654654564</Phone_2>
<Fax>2323232</Fax>
<Website>ewewew</Website>
<Mobile_No>23232323232</Mobile_No>
<Information>
<Info>
<National_Code>106397854</National_Code>
<Start_Activity_Date>2015-12-22 00:00:00</Start_Activity_Date>
<End_Activity_Date>2016-01-03 00:00:00</End_Activity_Date>
</Info>
</Information>
<Service_Times>
<Service_Time>15:30 - 17:45</Service_Time>
</Service_Times>
</Result>
the second string is :
<Result>
<pid>10</pid>
<DocID>29</DocID>
<Response>True</Response>
<DocID>60<DocID>
<Blvd_Name>dfdfdfdfd</Blvd_Name>
<Alley_Name>dfd</Alley_Name>
<Plate_Number>654654</Plate_Number>
<Post_Code>654654654</Post_Code>
<Phone_1>11111</Phone_1>
<Phone_2>6546111154564</Phone_2>
<Fax>11111</Fax>
<Website>11111</Website>
<Mobile_No>11111</Mobile_No>
<Information>
<Info>
<National_Code>106397854</National_Code>
<Start_Activity_Date>2015-12-22 8:01:50</Start_Activity_Date>
<End_Activity_Date>2016-01-03 11:20:10</End_Activity_Date>
</Info>
</Information>
<Service_Times>
<Service_Time>15:30 - 17:45</Service_Time>
</Service_Times>
</Result>
as you can see there are some differences in the values of the objects!
I've tried simplexmlload and then array_diff and jason encode and decode and comparing the jason but there was not chance to detect the differences.
any suggestion how to accomplish that ?
my array diff code :
$result = array_diff($Data1, $Data2);
if(empty($result)){
// the XML documents are the same
$res = "No changes";
} else {
// they are different
$res = "There are Some changes";
}
You can leave the data as raw text ane see the difference by using the following
<?php
$difference = xdiff_string_diff($Data1, $Data2);
Ok I solved the problem using simple if comparison method and it worked.
I first opened two xml files and then i copared them using method below, if i change a value/structure in second xml file it gives me "there are some changes".
$file = './Result.xml';
if (file_exists($file)) {
$Data = file_get_contents($file);
} else {
exit('Failed to open ' . $file);
}
$file2 = './Result2.xml';
if (file_exists($file2)) {
$Data2 = file_get_contents($file2);
} else {
exit('Failed to open ' . $file2);
}
if ($Data === $Data2) {
// the XML documents are the same
$res = "No changes";
} else {
// they are different: print the reason why
$res = "There are Some changes";
}
hello i have tried and nothing will happen...
i will count the childs from an xml file via php
everthing is ok but i dont get, - load correctly this stupid xml file into my page =
here's the script simply --
$url123 = 'http://steamcommunity.com/id/ProJaCore/stats/GarrysMod/?xml=1';
$data123 = file_get_contents($url123);
$xml = simplexml_load_string($data123);
$elem = new SimpleXMLElement($xml);
foreach ($elem as $achievements) {
print $achievements->count().'<br>';
}
Do this:
$url123 = 'http://steamcommunity.com/id/ProJaCore/stats/GarrysMod/?xml=1';
$data123 = file_get_contents($url123);
$elem = new SimpleXMLElement($data123);
foreach ($elem as $achievements) {
print $achievements->count().'<br>';
}
In your code you're creating a SimpleXMLElement object in $xml, then trying to create another one in $elem using the $xml object.
See the complete reference: http://www.php.net/manual/en/book.simplexml.php
I am having some trouble mixing PHP with XML.
I currently have a PHP file that takes variables from the URL string and I need to calculate something based on these variables, and then return the output in an XTML format.
I currently have my main config file that links to my xml generating file:
include('Xml.php');
$x = new xml();
$x->generate();
And my XML generating file is as follows:
<?php
Class XML {
public function generate() {
$doc = new DOMDocument('1.0');
$doc->formatOutput = true;
$root = $doc->createElement('conv');
$root = $doc->appendChild($root);
$at = $doc->createElement('at');
$at = $root->appendChild($at);
$text = $doc->createTextNode("hi");
$text = $at->appendChild($text);
echo $doc->saveXML();
}
}
?>
But this doesn't work - what am I doing wrong here - I know it's probaby obvious but I am new to XML and can't seem to get it working!
Should I be doing it differently? If so ... how?
I've just tested your class with following code:
$xml = new XML();
$xml->generate();
And I've got this result:
[vyktor#grepfruit tmp]$ php test.php
<?xml version="1.0"?>
<conv>
<at>hi</at>
</conv>
So your class works just fine and your error is somewhere else, eg. including wrong file.
Turn on error_reporting and paste errors in comment.
foreach ($filePaths as $filePath) {
/*Open a file, run a function to write a new file
that rewrites the information to meet design specifications */
$fileHandle = fopen($filePath, "r+");
$newHandle = new DOMDocument();
$newHandle->loadHTMLFile( $filePath );
$metaTitle = trim(retrieveTitleText($newHandle));
$pageMeta = array('metaTitle' => $metaTitle, 'pageTitle' => 'Principles of Biology' );
$attributes = retrieveBodyAttributes($filePath);
cleanfile($fileHandle, $filePath);
fclose($fileHandle);
}
function retrieveBodyAttributes($filePath) {
$dom = new DOMDocument;
$dom->loadHTMLFile($filePath);
$p = $dom->getElementsByTagName('body')->item(0);
/*if (!$p->hasAttribute('body')) {
$bodyAttr[] = array('attr'=>" ", 'value'=>" ");
return $bodyAttr;
}*/
if ($p->hasAttributes()) {
foreach ($p->attributes as $attr) {
$name = $attr->nodeName;
$value = $attr->nodeValue;
$bodyAttr[] = array('attr'=>$name, 'value'=>$value);
}
return $bodyAttr;
}
}
$filePaths is an array of strings. When I run the code, it give me a "Call to member function hasAttributes() on non-object" error for the line that calls hasAttributes. When it's not commented out, I get the same error on the line that calls hasAttribute('body'). I tried a var_dump on $p, on the line just after the call to getElementsByTagName, and I got "object (DOMElement) [5]". Well, the number changed because I was running the code on multiple files at once, but I didn't know what the number meant. I can't find what I'm doing wrong.
with:
$p = $dom->getElementsByTagName('body')->item(0);
You are executing: DOMNodelist::item (See: http://www.php.net/manual/en/domnodelist.item.php) which returns NULL if, at the given index, no element is found.
But you're not checking for that possibility, you're just expecting $p to be not null.
Try adding something like:
if ($p instanceof DOMNode) {
// the hasAttributes code
}
Although, if you're sure that there should be a body element, you'll probably have to check your file paths.
It should be because there is no <body> tag in your DOM Document.
hi
i am working with a xml file and structure of the file is like
<ListRecords>
<record>
</record>
<totalupnow> </totalupnow>
<record>
</record>
<record>
</record>
<record>
</record>
<record>
</record>
<totalupnow> </totalupnow>
</listrecord>
now i need a php program tht just removes the <totalupnow> </totalupnow> from this file.. the file is very big in size almost 4 gbs.
please help me out...
or if there is anyway i can only read the <record> </record> from this leaving the <totalupnow> </totalupnow> as it is.
You can use the event-based streaming XML parser (SAX) to parse such a file. It works a little differently than a DOM parser, but in exchange it can work with files of any size.
[...] or if there is anyway i can only read the <record> </record>
To keep things simple, I assume your <record> elements contain nothing but text and that "read" means "write their contents to the screen".
<?php
$file = "your_big_file.xml";
$xml_parser = xml_parser_create();
// set up some basic parser properties
xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, 0);
xml_parser_set_option($xml_parser, XML_OPTION_SKIP_WHITE, 1);
// set up your event handlers
xml_set_element_handler($xml_parser, "startElement", "endElement");
xml_set_character_data_handler($xml_parser, "contents");
// read the file in 4kb chunks and parse these as they are read
while ($data = fread($fp, 4096)) {
if (!xml_parse($xml_parser, $data, feof($fp))) {
die( sprintf("XML error: %s at line %d",
xml_error_string(xml_get_error_code($xml_parser)),
xml_get_current_line_number($xml_parser)));
}
}
// clean up
xml_parser_free($xml_parser);
// EVENT HANDLERS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$in_record = false;
$counter = 0;
$depth = 0;
// this function is called whenever a start element (<foo>) is encountered
function startElement($parser, $name, $attrs) {
global $in_record;
global $depth;
global $counter;
$depth++;
$in_record = ($name == "record");
if ($in_record) {
$counter++;
echo "Record #$counter:\n";
}
}
// this function is called whenever a start element (</foo>) is encountered
function endElement($parser, $name) {
global $in_record;
global $depth;
$depth--;
$in_record = ($name != "record");
}
// this function is called whenever text data is encountered
function contents($parser, $data) {
global $in_record;
if ($in_record) {
echo "\t".$data."\n";
}
}
?>