I've got the following problem:
I have a csv file, that I can convert to XML via a php script.
This way, every field goes under the same row in the xml, and I want the product_sku field go under a different row, for example call it SKU_row.
The CSV looks like this:
my CSV file
The XML looks like this:
my XML file
PHP file code that I run to convert the CSV to XML:
error_reporting(E_ALL | E_STRICT);
ini_set('display_errors', true);
ini_set('auto_detect_line_endings', true);
function PrepareXMLName($PrepareString)
{
$PrepareString = str_replace(" ","",$PrepareString);
$PrepareString = preg_replace('#\W#', '', $PrepareString);
$PrepareString = str_replace("ZSPAZESZ","",$PrepareString);
$PrepareString = strtolower($PrepareString);
return $PrepareString;
}
$inputFilename = 'faszom.csv';
$outputFilename = 'faszom.xml';
// Open csv to read
$inputFile = fopen($inputFilename, 'rt');
// Get the headers of the file
$headers = fgetcsv($inputFile);
// Create a new dom document with pretty formatting
$doc = new DomDocument();
$doc->formatOutput = true;
// Add a root node to the document
$root = $doc->createElement('rows');
$root = $doc->appendChild($root);
// Loop through each row creating a <row> node with the correct data
while (($row = fgetcsv($inputFile)) !== FALSE)
{
$container = $doc->createElement('row');
foreach ($headers as $i => $header)
{
$header = str_replace(chr(32),"_",trim($header));
$header = strtolower($header);
if($header==''){ $header = 'empty';}
$header = PrepareXMLName($header);
if(is_numeric($header)) { $header = "number-". $header; }
//echo "HERE: " . $header . "<br />";
$child = $doc->createElement($header);
$child = $container->appendChild($child);
$value = $doc->createTextNode($row[$i]);
$value = $child->appendChild($value);
}
$root->appendChild($container);
}
header("Content-type: text/xml");
$strxml = $doc->saveXML();
$handle = fopen($outputFilename, "w");
fwrite($handle, $strxml);
fclose($handle);
echo $doc->saveXML();
How can I do in this PHP file, to let it put the product_sku fields under a different row, to be it separated from the row in which customer data's are?
XML allows you to group on a further level. So instead of your flat row model:
<rows>
<row>
<product_sku>L162L</product_sku>
<order_entity_id>31</order_entity_id>
<order_customer_firstname>Teszt</order_customer_firstname>
<product_qty_ordered>1.0000</product_qty_ordered>
</row>
You can group further on depending on the context of the data, for example by order, product and customer:
<rows>
<row>
<product>
<sku>L162L</sku>
<qty_ordered>1.0000</qty_ordered>
<product>
<order>
<entity_id>31</entity_id>
<customer>
<firstname>Teszt</firstname>
</customer>
</order>
</row>
But this depends entirely of what you want and from your question I don't see any reason on why to do it this, that or any other way nor what stands in your way to do whatever you want.
Related
I am trying to convert my CSV file to XML. I am using this script below which I got from a post. But it's not working on my side. Any idea why I am getting this error?
error_reporting(E_ALL | E_STRICT);
ini_set('display_errors', true);
ini_set('auto_detect_line_endings', true);
$inputFilename = 'test.csv';
$outputFilename = 'test.xml';
// Open csv to read
$inputFile = fopen($inputFilename, 'rt');
// Get the headers of the file
$headers = fgetcsv($inputFile);
// Create a new dom document with pretty formatting
$doc = new DomDocument();
$doc->formatOutput = true;
// Add a root node to the document
$root = $doc->createElement('rows');
$root = $doc->appendChild($root);
// Loop through each row creating a <row> node with the correct data
while (($row = fgetcsv($inputFile)) !== FALSE)
{
$container = $doc->createElement('row');
foreach($headers as $i => $header)
{
$child = $doc->createElement($header);
$child = $container->appendChild($child);
$value = $doc->createTextNode($row[$i]);
$value = $child->appendChild($value);
}
$root->appendChild($container);
}
$strxml = $doc->saveXML();
The error I am getting is here:
Uncaught exception 'DOMException' with message 'Invalid Character Error'
Here is my csv file:
name, email, test
john,john#foobar.com,blah
mary,mary#blah.com,something
jane,jan#something.com,blarg
bob,bob#test.com,asdfsfd
Your header row has spaces around the field names, spaces don't sit well with the names of XML elements. Simply trim() the field names...
$child = $doc->createElement(trim($header));
Would anyone know how i can "explode" a string back into "normal" xml format?
I found this script (ref:gooseflight,2010) that looks like it can do the job but the output comes out stuck together.
Here's the code:
enter code herefunction combineXML($file)
{
global $xmlstr;
$xml = simplexml_load_file($file);
foreach($xml as $element)
$xmlstr .= $element->asXML();
}
$files[] = "tmp.xml";
$files[] = "traduction.xml";
$xmlstr = '<CAB>';
foreach ($files as $file)
combineXML($file);
$xmlstr .= '</CAB>';
// Convert string to XML for further processing
$xml = simplexml_load_string($xmlstr);
$bytes = file_put_contents("combined.xml", $xml->asXML())
Here is the output:
<?xml version="1.0" encoding="UTF-8"?>
<CAB>
<CABO>XXXXXXXXXX0987650003</CABO><ACTIVITY>NONE</ACTIVITY><BEORI>blablaE</BEORI>BEDEST>blabla</BEDEST><NATRELA>more blabla</NATRELA><ANE>2014</ANE><NODEP>1111</NODEP>
</CAB>
So how could i seperate the nodes to look like this?:
<?xml version="1.0" encoding="UTF-8"?>
<CAB>
<CABO>XXXXXXXXXX0987650003</CABO>
<ACTIVITY>NONE</ACTIVITY>
<BEORI>blablaE</BEORI>
<BEDEST>blabla</BEDEST>
<NATRELA>more blabla</NATRELA>
<ANE>2014</ANE>
<NODEP>1111</NODEP>
.....
</CAB>
Would anyone know how to fix it?
I would suggest to use DomDocument class to save the XML; check this:
$dom_obj = new DOMDocument();
$dom_obj->loadXML($file);
// Do all your changes to the file by using DomDocument command (e.g. CreateElement, CreateAttribute, etc)
$dom_obj->formatOutput = true;
$dom_obj->save($file);
hey there i have an xml file that has what i need to do is to add an event with same location name A
<timetable>
<location name="A" >
<event >
<title>EVENT TITLE </title>
<subtitle>Amman -text </subtitle>
<description>Amman -text </description>
</event>
</location>
</timetable>
so it can be like this
<timetable>
<location name="A" >
<event >
<title>EVENT TITLE </title>
<subtitle>Amman -text </subtitle>
<description>Amman -text </description>
</event>
<event >
<title>EVENT TITLE </title>
<subtitle>Amman -text </subtitle>
<description>Amman -text </description>
</event>
</location>
</timetable>
i got stuck in my php code where i want to cheack if the event is created or not if its created modify my xml with name of the event and add the new one
this is my full php inserting code `
if(isset($_GET['coname'])){
$coid = $_GET['id'];
$cname=$_GET['coname'];
$title = $_POST ['title'];
$sub = $_POST ['sub'];
$description = $_POST ['description'];
$location = $_POST ['location'];
$event = $_POST ['event'] ;
$str =$_POST ['str'] ;
$end =$_POST ['end'] ;
$topic = $_POST ['topic'] ;
$sql="INSERT INTO timeline (title,sub,description,location,event,str,end,topic,coid)
VALUES
('$title','$sub','$location','$location','$event','$str','$end','$topic','$coid')";
if (!mysqli_query($con,$sql))
{
die('Error: ' . mysqli_error($con));
}
echo "1 record added";
$q = mysqli_query($con,"SELECT * FROM timeline where coid = $coid") or die(mysqli_error());
$xml = '<timetable start="'.$st.'" end="'.$en.'" interval="'.$in.'" title="'.$da.'">';
while($r = mysqli_fetch_array($q)){
$loc=$r['topic'];
$evns=$r['str'];
$evne= $r['end'];
$xml .= '<location name="'.$loc.'" subtext=" ">';
$xml .= '<event start="'.$evns.'" end="'.$evne.'">';
$xml .= "<title>".$r['title']."</title>";
$xml .= "<subtitle>".$r['location']."</subtitle>";
$xml .= "<description>".$r['description']."</description>";
$xml .= "</event>";
$xml .= "</location>";
}
$xml .= "</timetable>";
$sxe = new SimpleXMLElement($xml);
$sxe->asXML('xml/'.$cname.'.xml'); `
Amer, rather than creating the XML from strings, I'd use the simplexml methods:
Inserting a new <event> in existing XML:
$xml = simplexml_load_string($x); // assume XML in $x
$loc = $xml->xpath("location[#name = 'A']")[0]; // select <location> with name = A
$event = $loc->addChild("event");
$event->addAttribute("start", "2013-05-20 10:00:00");
$event->addAttribute("end", "2013-05-20 14:30:00");
$event->addChild("title", "some title");
$event->addChild("subtitle", "some subtitle");
$event->addChild("description", "some description");
see it working: http://codepad.viper-7.com/12xtVD
From what I understand, you want to create a child element. This is how I would go about doing this:
PHP:
$eleone=$_POST['elementone'];
$eletwo=$_POST['elementtwo'];
$file = "verbs.xml";
$openf = fopen($file, "c+") or die ("Cannot open file");
$str = fread ($openf, filesize($file));
$xml = new DOMDocument('1.0', 'iso-8859-1');
$xml->formatOutput=TRUE;
$xml->preserveWhiteSpace = FALSE;
$xml ->loadXML($openf) or die ("There has been an error with opening the XML file. Our team has been notified and will start working to fix this problem.");
//this is the original document
echo "<xmp>OLD:\n". $xml->saveXML(). "<xmp>";
//this is how you get the document element
$root= $xml ->documentElement;
$firstnode= $root->firstChild;
//good stuff right here; how to make a node
$ori= $firstnode->childNodes->item(2);
$eleadd= $xml->createElement($elementone);
$eleaddt= $xml->createTextNode($//what gets shown in $eleadd );
$eleadd->appendChild("$idt");
If you don't want all of this, you may be able to delete some non-crucial things like the parent elements. If you need more information, http://www.phpeveryday.com/articles/PHP-XML-Adding-XML-Nodes-P414.html is the place to go, or where I found my information.
I'm now using the function fwrite(); in PHP. But i want to locate my new things after a specific rule.
This wil be the output.
<?xml version="1.0" encoding="utf-8" ?>
<logs>
<log type="text">the new log</log>
<log type="text>the old log</log>
<log type="login">some other log.</log>
</logs>
How can i get the new log in the new log and not on the end. I only can find something like file_get_contents and then str_replace. But that seems really not efficient.
My php Code:
$file = $this->path.'logs.xml';
// Open our file. And Create file if it doesn't exsist
$fopen = fopen($file, "w+");
// Looks if file is empty.
if(filesize($file) == 0) {
/*
* Put your data in XML data.
*/
$xmlData = "<?xml version=\"1.0\" encoding=\"utf-8\" ?> \r\n";
$xmlData .= "<logs> \r\n";
$xmlData .= "\t<log type=\"".$data[0]."\">\r\n";
$xmlData .= "\t\t<author>".$data[1]."</author>\r\n";
$xmlData .= "\t\t<action>".$data[2]."</action>\r\n";
$xmlData .= "\t\t<result>".$data[3]."</result>\r\n";
$xmlData .= "\t\t<note>".$data[4]."</note>\r\n";
$xmlData .- "\t</log>\r\n";
$xmlData .= "</logs>";
} else {
}
if(is_writeable($file)) {
fwrite($fopen, $xmlData);
return true;
}
return false;
fclose($fopen);
Sincerely thank you.
Well, you're lucky your data is in XML. PHP has got a bunch of easy to use libraries (extensions) that deal with XML data. For example SimpleXML or the more capable DOM (both extension are enabled by default).
<?php
$filename = $this->path.'logs.xml';
if (!file_exists($filename)) {
// Here's your code from above, although it would be easier to use
// the libraries here, as well
} else {
$logs = simplexml_load_file($filename);
// See if there's a "text" log element
$txtlog = $logs->xpath('./log[#type = "text"]');
...
}
You could use the array_splice method. This way you can insert a new element in an array at any position.
$file = $this->path.'logs.xml';
$content = file($file); //is array with all lines as elements.
/*
0: <?xml version="1.0" encoding="utf-8" ?>
1: <logs>
2: <log type="text>the old log</log>
3: <log type="login">some other log.</log>
4: </logs>
*/
//insert the new line at position 2
array_splice( $content, 2, 0, ' <log type="text">the new log</log>' );
/*
0: <?xml version="1.0" encoding="utf-8" ?>
1: <logs>
2: <log type="text">the new log</log>
3: <log type="text>the old log</log>
4: <log type="login">some other log.</log>
5: </logs>
*/
$fopen = fopen($file, "w+");
fwrite($fopen, implode("\n", $content);
fclose($fopen);
I would like to create a new simplified xml based on an existing one:
(using "simpleXml")
<?xml version="1.0" encoding="UTF-8"?>
<xls:XLS>
<xls:RouteInstructionsList>
<xls:RouteInstruction>
<xls:Instruction>Start</xls:Instruction>
</xls:RouteInstruction>
</xls:RouteInstructionsList>
<xls:RouteInstructionsList>
<xls:RouteInstruction>
<xls:Instruction>End</xls:Instruction>
</xls:RouteInstruction>
</xls:RouteInstructionsList>
</xls:XLS>
Because there are always colons in the element-tags, it will mess with "simpleXml", I tried to use the following solution->link.
How can I create a new xml with this structure:
<main>
<instruction>Start</instruction>
<instruction>End</instruction>
</main>
the "instruction-element" gets its content from the former "xls:Instruction-element".
Here is the updated code:
But unfortunately it never loops through:
$source = "route.xml";
$xmlstr = file_get_contents($source);
$xml = #simplexml_load_string($xmlstr);
$new_xml = simplexml_load_string('<main/>');
foreach($xml->children() as $child){
print_r("xml_has_childs");
$new_xml->addChild('instruction', $child->RouteInstruction->Instruction);
}
echo $new_xml->asXML();
there is no error-message, if I leave the "#"…
/* the use of # is to suppress warning */
$xml = #simplexml_load_string($YOUR_RSS_XML);
$new_xml = simplexml_load_string('<main/>');
foreach ($xml->children() as $child)
{
$new_xml->addChild('instruction', $child->RouteInstruction->Instruction);
}
/* to print */
echo $new_xml->asXML();
You could use xpath to simplify things. Without knowing the full details, I don't know if it will work in all cases:
$source = "route.xml";
$xmlstr = file_get_contents($source);
$xml = #simplexml_load_string($xmlstr);
$new_xml = simplexml_load_string('<main/>');
foreach ($xml->xpath('//Instruction') as $instr) {
$new_xml->addChild('instruction', (string) $instr);
}
echo $new_xml->asXML();
Output:
<?xml version="1.0"?>
<main><instruction>Start</instruction><instruction>End</instruction></main>
Edit: The file at http://www.gps.alaingroeneweg.com/route.xml is not the same as the XML you have in your question. You need to use a namespace like:
$xml = #simplexml_load_string(file_get_contents('http://www.gps.alaingroeneweg.com/route.xml'));
$xml->registerXPathNamespace('xls', 'http://www.opengis.net/xls'); // probably not needed
$new_xml = simplexml_load_string('<main/>');
foreach ($xml->xpath('//xls:Instruction') as $instr) {
$new_xml->addChild('instruction', (string) $instr);
}
echo $new_xml->asXML();
Output:
<?xml version="1.0"?>
<main><instruction>Start (Southeast) auf Sihlquai</instruction><instruction>Fahre rechts</instruction><instruction>Fahre halb links - Ziel erreicht!</instruction></main>