I use this below to save me the contents of the XML addresses I have in array. However only one XML is saved, specifically the last one. What am I missing here?
$filenames = array('xml url','xml url','xml url');
foreach( $filenames as $filename) {
$xml = simplexml_load_file( $filename );
$xml->asXML("test.xml");
}
You appear to be opening each XML file, then saving them in the same location. File 1 is written, then File 2 overwrites it, then File 3... In short, the last file will overwrite the previous ones, and therefore "only the last one is saved".
What exactly are you trying to do here?
You save them all as the same name, so of course the earlier ones will be lost.
Try this:
$filenames = array('xml url','xml url','xml url');
foreach( $filenames as $key => $filename) {
$xml = simplexml_load_file( $filename );
$xml->asXML('test' . $key. '.xml');
}
That should save the files sequentially as test0.xml, test1.xml, test2.xml and so on.
If you want all your loaded XML URL's to be appended to a single file, you can do something like this:
$filenames = array('xml url','xml url','xml url');
$fullXml = array();
foreach( $filenames as $key => $filename) {
$xml = simplexml_load_file( $filename );
// Convert the simplexml object into a string, and add it to an array
$fullXml[] = $xml->asXML();
}
// Implode the array of all our xml into one big xml string
$fullXml = implode("\n", $fullXml);
// Load the new big xml string into a simplexml object
$xml = simplexml_load_string($fullXml);
// Now we can save the entire xml as your file
$xml->asXml('test.xml');
Related
I have multiple CSV files in a folder with different data. I want to read in 1 CSV file at a time, convert the data to XML and then output the file as .xml before reading in the next CSV file.
Currently, the CSV files that I have all have a header row in it. The code I ave right now runs fine for all the CSV files that have a header row in it.
However, when it reads in a file that does not have a header row in it, it throws an error. I want it to be able to detect if there is no headings in the header row and then make it input strings which have been preset in variables in the code. Is this possible?
Current Code
function converttoxml( $input_filename ) {
echo $input_filename;
//set the delimiter
$delimiter = "," ;
//set count to 0
$row_count++ ;
//strip the input filename of the extension
$stripped = pathinfo($input_filename, PATHINFO_FILENAME);
//set output filename
$outputFilename = UPLOAD_DIR."/".$stripped.".xml";
//open inputfilename
$inputFile = fopen( $input_filename, 'rt' );
//get input file pointers for csv parsing
$headers = fgetcsv( $inputFile );
//create new DOM document
$doc = new DomDocument();
//set the output to clean
$doc->formatOutput = true;
//create element
$root = $doc->createElement( 'Shipping_Details' );
$root = $doc->appendChild( $root );
//while there are rows in the csv file
while ( ( $row = fgetcsv( $inputFile ) ) !== FALSE ) {
//create container row
$container = $doc->createElement('Job_Header_Details');
//for loop
foreach ( $headers as $i => $header ) {
//explode with the delimiter the header
$arr = explode( $delimiter, $header );
//print_r($arr);
//for loop
foreach ( $arr as $key => $ar ) {
//only accept regualar expressions matching this
$child = $doc->createElement(preg_replace( "/[^A-Za-z0-9]/","",$ar ) );
//add the previous child to $child
$child = $container->appendChild( $child );
//explode row with delimiter
$whole = explode( $delimiter, $row[$i] );
//left and right trim anything with speechmarks
$value = $doc->createTextNode( ltrim( rtrim( $whole[$key], '"') ,'"') );
//append previous value to $value
$value = $child->appendChild( $value );
}//for
}//for
//append to root - container
$root->appendChild($container);
}//while
echo "Saving the XML file\n" ;
$result = $doc->saveXML();
echo "Writing to the XML file\n" ;
$handle = fopen( $outputFilename, "w" );
fwrite( $handle, $result );
fclose( $handle );
return $outputFilename;
Examples of CSV files that will/willnot process
CSV File example that will work with above code
CSV File example that will NOT work with the above code
With the example that will not work, I believe it is because the header row is missing. In this case, I want to somehow define what each column heading should be and input it in.
for example
$column_1 = "<heading1>";
$column_2 = "<heading2>";
$column_3 = "<heading3>";
$column_4 = "<heading4>";
$column_5 = "<heading5>";
$column_6 = "<heading6>";
etc..
So when the script runs and it detects headings in the CSV file, it will use them. But when it detects that they are not there, the it will use the above $column examples to input the in.
The error I get when a CSV file does not have a header description
Any ideas?
Just to try this out, added ...
//get input file pointers for csv parsing
$headers = fgetcsv( $inputFile );
$row = 1;
foreach ( $headers as &$header ) {
if (preg_match('/\A(?!XML)[a-z][\w0-9-]*/i', $header) === 0 ) {
$header = 'heading'.$row;
}
$row++;
}
unset($header);
Which when passed in a header of a,1223 produces headers of a,heading2. Whereas a,b gives a,b.
Update: Although if any element fails, you'll want to process this row as data by the look of it.
I have the following code to read an XML file which works well when the URL is available:
$url = 'http://www1.blahblah.com'."param1"."param2";
$xml = file_get_contents($url);
$obj = SimpleXML_Load_String($xml);
How can I change the above code to cycle through a number of different URL's if the first one is unavailable for any reason? I have a list of 4 URL's all containing the same file but I'm unsure how to go about it.
Replace your code with for example this
//instead of simple variable use an array with links
$urls = [ 'http://www1.blahblah.com'."param1"."param2",
'http://www1.anotherblahblah.com'."param1"."param2",
'http://www1.andanotherblahblah.com'."param1"."param2",
'http://www1.andthelastblahblah.com'."param1"."param2"];
//for all your links try to get a content
foreach ($urls as $url) {
$xml = file_get_contents($url);
//do your things if content was read without failure and break the loop
if ($xml !== false) {
$obj = SimpleXML_Load_String($xml);
break;
}
}
I would like to be able to edit a config file for a server application using php. The config file is as follows:
include=sc_serv_public.conf
streamid_2=2
streampath_2=/relay
streamrelayurl_2=http://<full_url_of_relay_including_port>
;allowrelay=0
;allowpublicrelay=0
I would like to edit the line:
streamrelayurl_2=http://<full_url_of_relay_including_port>
and then save the file.
I am currently using:
$data = file_get_contents("sc_serv.conf"); //read the file
$convert = explode("\n", $data); //create array separate by new line
to open the file, but now I dont know how to edit it.
As an alternative, you could just use file() instead. This just loads it up into array form, no need to explode. Then after that, you just loop the elements, if the desired needle is found, overwrite it, the write the file again:
$data = file('sc_serv.conf', FILE_IGNORE_NEW_LINES); // load file into an array
$find = 'streamrelayurl_2='; // needle
$new_value = 'http://www.whateverurl.com'; // new value
foreach($data as &$line) {
if(strpos($line, 'streamrelayurl_2=') !== false) { // if found
$line = $find . $new_value; // overwrite
break; // stop, no need to go further
}
}
file_put_contents('sc_serv.conf', implode("\n", $data)); // compound into string again and write
You can use file() to read the file content to an array, then you can iterate trough the array with foreach() searching with the strstr() function the line that have your URL (in this case is in the var $id_change) and change the value. Then as you found what you needed, you end the foreach() with break. And make your string to save in the file with implode() and save the string to the config file with file_put_content().
See the code:
<?php
$new_url = 'http://www.google.com';
$id_change = 'streamrelayurl_2';
$file = "sc_serv.conf";
$data = file($file); //read the file
foreach($data as $key => $value) {
if(strstr($value, $id_change)) {
$info = $id_change . '=' . $new_url . "\n";
$data[$key] = $info;
break;
}
}
$data = implode("", $data);
file_put_contents($file, $data);
?>
Output:
include=sc_serv_public.conf
streamid_2=2
streampath_2=/relay
streamrelayurl_2=http://www.google.com
;allowrelay=0
;allowpublicrelay=0
So I have an XML file that looks similar to this:
<container>
<example1>some text</example1>
<example2>some text</example2>
<example3>some text</example3>
<example4>some text</example4>
</container>
<container>
<example1>some text</example1>
<example2>some text</example2>
<example4>some text</example4>
</container>
Basically, if example3 doesn't contain any information, the XML author decided to leave it out completely. The trouble is, when I am using my script to convert to CSV, this particular XML file doesn't convert to CSV properly due to the text in the second example4 being displayed under the header of example3 in the CSV file.
This is the PHP script I have to normally works with other XML files.
$file='input.xml';
if (file_exists($file)) {
$xml = simplexml_load_file($file);
$f = fopen('output.csv', 'w');
// array to hold the field names
$headers = array();
// loop through the first set of fields to get names
foreach ($xml->container->children() as $field) {
// put the field name into array
$headers[] = $field->getName();
}
// print headers to CSV
fputcsv($f, $headers, ',', '"');
foreach ($xml->container as $information) {
fputcsv($f, get_object_vars($information), ',', '"');
}
fclose($f);
}
I can't figure out how to predefine the headers that I need and insert the correct information in the correct columns in the CSV.
Any pointers much appreciated.
thanks
mike
If your first entry always present all fields, then its enougth to iterate over the header fields for each line and look if the current line has all entrys.
foreach ($xml->container as $information) {
$vars = get_object_vars($information);
$line = array();
foreach($headers as $field) {
$line[] = isset($vars[$field]) ? $vars[$field] : '';
}
fputcsv($f, $line, ',', '"');
}
I want to add/display data from querying from the database and add it into an XML file.
Example, I have a table_persons which has a name and age. I create a mysql query to get its name and age. Then simply put the data(name and age of persons) into an XML file.
How would you do that? Or is it possible?
I suggest you use DomDocument and file_put_contents to create your XML file.
Something like this:
// Create XML document
$doc = new DomDocument('1.0', 'UTF-8');
// Create root node
$root = $doc->createElement('persons');
$root = $doc->appendChild($root);
while ($row = mysql_fetch_assoc($result)) {
// add node for each row
$node = $doc->createElement('person');
$node = $root->appendChild($node);
foreach ($row as $column => $value) {
$columnElement = $doc->createElement($column);
$columnElement = $node->appendChild($columnElement);
$columnValue = $doc->createTextNode($value);
$columnValue = $columnElement->appendChild($columnValue);
}
}
// Complete XML document
$doc->formatOutput = true;
$xmlContent = $doc->saveXML();
// Save to file
file_put_contents('persons.xml', $xmlContent);
<?php
[snip] //database code here
$f = fopen('myxml.xml', 'a+');
foreach($row = mysqli_fetch_assoc($resultFromQuery))
{
$str = "<person>
<name>{$row['name']}</name>
<age>{$row['age']}</age>
</person>\n";
fwrite($f, $str);
}
fclose($f);
?>
Assuming you use mysqli, this code works. If not, suit to fit. In the fopen function call, the a+ tells it to open it for reading at writing, placing the pointer at the end of the file.
Best of luck.