loops with fwrite for XML - php

function xmlParse() {
$fh = fopen('schools/' . $this->id . '/books/school_books.xml', 'a');
$xmlstr = "<?xml version='1.0' ?>\n" .
"<rows></rows>";
// create the SimpleXMLElement object with an empty <book> element
$xml = new SimpleXMLElement($xmlstr);
$x = 0;
// add some more child nodes
for ($i = 0; $i < sizeof($this->students); $i++) {
$this->students[$i]->getmyBooks();
for ($j = 0; $j < sizeof($this->students[$i]->myBooks); $j++) {
$row = $xml->addChild("row");
$row->addAttribute("id", $x);
$row->addChild("cell", $this->students[$i]->myBooks[$j]->owner);
$row->addChild("cell", $this->students[$i]->myBooks[$j]->title);
$row->addChild("cell", $this->students[$i]->myBooks[$j]->category);
$row->addChild("cell", $this->students[$i]->myBooks[$j]->price);
$row->addChild("cell", $this->students[$i]->myBooks[$j]->description);
$row->addChild("cell", "Test");
$x++;
fwrite($fh, $xml->asXML());
}
}
}
I know what the problem is: its fwrite($fh, $xml->asXML());
if I keep calling that within the loop it doesn't append it keeps starting the xml document from scratch and posting the tags again.
My Problem is that it keeps writing from all over again the xml tags... instead of just continuing with the xml. If i do it for just 1 student it works perfect, but instead when I try to loop through all my students it keeps printing the xml tags instead of continuing on to the next student.
<?xml version="1.0"?>
<rows>
<row id="0">
<cell>Owner</cell>
<cell>test</cell>
<cell>Math</cell>
<cell>11</cell>
<cell>test</cell>
<cell>Test</cell>
</row>
</rows>
<?xml version="1.0"?>
continues with the next one then it does xml tags again and again.
This is how its to look like for one student:
<rows>
<row id="0">
<cell>Owner</cell>
<cell>Calculus III</cell>
<cell>Math</cell>
<cell>82</cell>
<cell>This book is in great condition! Available asap.</cell>
<cell>Test</cell>
</row>
<row id="1">
<cell>Owner</cell>
<cell>Discrete Mathematics</cell>
<cell>Math</cell>
<cell>62</cell>
<cell>This book is in poor condition.</cell>
<cell>Test</cell>
</row>
<row id="2">
<cell>Owner</cell>
<cell>Calculus I</cell>
<cell>Math</cell>
<cell>12</cell>
<cell>Really good book.</cell>
<cell>Test</cell>
</row>
</rows>

You're really looking for file_put_contents($name, $contents). That function adds all of the content en masse, so you would call it once at the end of the loop.
The code might look like:
// after i >= sizeof($this->students)
file_put_contents('schools/' . $this->id . '/books/school_books.xml',
$xml->asXML());
fwrite on the other hand, appends a file every single time it is called. This means that it will add the contents of the XML to the file sizeof($this->students) times, which is what you're seeing right now.
By the way, depending on the size of sizeof($this->students), you may want to declare a local variable to cache that before you look, sizeof it will be called every time.
$studentSize = sizeof($this->students);
for ($i = 0; $i < $studentSize; $i++) {
On the other hand, you might want to change that to a foreach loop (can't describe how at the moment but I'll add that in later if I remember).

Related

How to turn PHP variables into XML

I'm trying to do some feed submission for MWS.
I have a db that I need to make a call from.
dbCall functiion and $sql is the sql that calls the variable from customer database.
$var = dbCall($sql);
for ($x = 0; $x < 1; $x++ )
{
feed[] = "<Message>
<MessageID>".$messageID."</MessageID>
<OperationType>Update</OperationType>
<Product>
<SKU>book_".$var[$x]."</SKU>
<StandardProductID>
<Type>ASIN</Type>
<Value>".$var[$x]."</Value>
</StandardProductID>
<Condition>
<ConditionType>New</ConditionType>
<ConditionNote>Brand New! Never used!</ConditionNote>
</Condition>
</Product>
</Message>";
$messageID = $messageID + 1;
}
$total_feed = implode(" ", $feed);
$final_feed = '<?xml version="1.0" encoding="utf-8"?>
<AmazonEnvelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="amznenvelope.xsd">
<Header>
<DocumentVersion>1.01</DocumentVersion>
<MerchantIdentifier>'.$merch_id.'</MerchantIdentifier>
</Header>
<MessageType>Product</MessageType>
<PurgeAndReplace>false</PurgeAndReplace>' .$total_feed.'</AmazonEnvelope>');
`
When I run this; I get the string back but some of the tags don't align properly (see SKU and value).
How do I get an XML output from database variables?
Edit:
When I print the output for implode(" ",$feed) - all my tags seem lower case, but if I use htmlspecialchars or htmlentities, I get them in correct format.
<message> instead of <Message>
using trim adjusted the xml correctly.

Count how many children are in XML with PHP

i know a few about php, so sorry for the question:
i have this file xml:
<?xml version="1.0" encoding="ISO-8859-1"?>
<alert>
<status> </status>
<nothing> </nothing>
<info>
<area>
</area>
</info>
<info>
<area>
</area>
</info>
<info>
<area>
</area>
</info>
</alert>
i must do a for loop and inside a "foreach" for each
The problem is that i'm not sure what is a way to know how many times i had to repeat a for loop. Because in this file xml (that is an example) i don't know how many are
Is good if:
$url = "pathfile";
$xml = simplexml_load_file($url);
$numvulcani = count($xml->alert->info); // is good ?
for ($i = 0; $i <= $numvulcani; $i++) {
foreach ($xml->alert->info[$i] as $entry) {
$area = $entry->area;
}
}
is true ?
sorry for bad english
You need to use SimpleXMLElement::count function for this — It counts the children of an element.
<?php
$xml = <<<EOF
<people>
<person name="Person 1">
<child/>
<child/>
<child/>
</person>
<person name="Person 2">
<child/>
<child/>
<child/>
<child/>
<child/>
</person>
</people>
EOF;
$elem = new SimpleXMLElement($xml);
foreach ($elem as $person) {
printf("%s has got %d children.\n", $person['name'], $person->count());
}
?>
The output will be as follows :
Person 1 has got 3 children.
Person 2 has got 5 children.
Also take a look at this link : xml count using php
Try replacing foreach ($xml->alert->info[$i] as $entry) with:
foreach ($xml->alert->info[$i] as $j => $entry)
The current item index will be $j
You're perhaps overcomplicating this a bit as it's new to you.
First of all, you don't need to reference the alert root element like $xml->alert because the SimpleXMLElement named by the variable $xml represents that document element already.
And second, you don't need to count here, you can just foreach directly:
foreach ($xml->info as $info) {
echo ' * ', $info->asXML(), "\n";
}
This iterates over those three info elements that are children of the alert element.
I recommend the Basic SimpleXML usage guide in the PHP manual for a good start with SimpleXML.

Get the attributes and values from xml file

I have following xml file:
<ROW>
<rating>10</rating>
<answers>Very Satisfied</answers>
<transaction_date>01/21/2015</transaction_date>
<date>05/30/2015</date>
<username>got2bsunny4me</username>
<link>http://widget.resellerratings.com/store/Amberen/review/#comment8877470</link>
<comment><![CDATA[my extreme hot flashes became less frequent within a couple weeks, and not as severe. after 2 months of taking Amberen, I didn't need to take as often. I've used Amberen before and my hot flashes...]]></comment>
</ROW>
<ROW>
<rating>10</rating>
<answers>Very Satisfied</answers>
<transaction_date>03/23/2015</transaction_date>
<date>05/18/2015</date>
<username>musiclvr24</username>
<link>http://widget.resellerratings.com/store/Amberen/review/#comment8785090</link>
<comment><![CDATA[Ordering was very easy! The whole website was very informative and very useful as a health resource. Thank you very much!]]></comment>
</ROW>
Here is my php file to parse xml file.
<pre>
<?php
$seller_id = 113;
$xml = simplexml_load_string(file_get_contents("http://widget.atings.com/widget/snippet/?seller_id=$seller_id"));
foreach($xml->ROW as $row){
//echo $row,'="',$s,"\"\n"; // to get all rows
var_dump($row);
echo '<div class="spans"></div>';
}
//var_dump($xml->ROW) // to get single row
?>
</pre>
I need to get each row's attributes and values displayed on newly created divs for each row. How can I achieve this?
If possible add some main tags at start and end of your XML and rest of your code will work fine...
<document>
<ROW>
<rating>10</rating>
<answers>Very Satisfied</answers>
<transaction_date>01/21/2015</transaction_date>
<date>05/30/2015</date>
<username>got2bsunny4me</username>
<link>http://widget.resellerratings.com/store/Amberen/review/#comment8877470</link>
<comment><![CDATA[my extreme hot flashes became less frequent within a couple weeks, and not as severe. after 2 months of taking Amberen, I didn't need to take as often. I've used Amberen before and my hot flashes...]]></comment>
</ROW>
<ROW>
<rating>10</rating>
<answers>Very Satisfied</answers>
<transaction_date>03/23/2015</transaction_date>
<date>05/18/2015</date>
<username>musiclvr24</username>
<link>http://widget.resellerratings.com/store/Amberen/review/#comment8785090</link>
<comment><![CDATA[Ordering was very easy! The whole website was very informative and very useful as a health resource. Thank you very much!]]></comment>
</ROW>
</document>
You need to enclosed some main tags like "ROWS" which enclosed other tags. please check below XML and code to access element value.
$xml = <<<XML
<ROWS>
<ROW>
<rating>10</rating>
<answers>Very Satisfied</answers>
<transaction_date>01/21/2015</transaction_date>
<date>05/30/2015</date>
<username>got2bsunny4me</username>
<link>http://widget.resellerratings.com/store/Amberen/review/#comment8877470</link>
<comment><![CDATA[my extreme hot flashes became less frequent within a couple weeks, and not as severe. after 2 months of taking Amberen, I didn't need to take as often. I've used Amberen before and my hot flashes...]]></comment>
</ROW>
<ROW>
<rating>10</rating>
<answers>Very Satisfied</answers>
<transaction_date>01/21/2015</transaction_date>
<date>05/30/2015</date>
<username>got2bsunny4me</username>
<link>http://widget.resellerratings.com/store/Amberen/review/#comment8877470</link>
<comment><![CDATA[my extreme hot flashes became less frequent within a couple weeks, and not as severe. after 2 months of taking Amberen, I didn't need to take as often. I've used Amberen before and my hot flashes...]]></comment>
</ROW>
</ROWS>
XML;
$xml = simplexml_load_string($xml);
foreach($xml as $row){
echo $row->rating;
echo $row->answers;
}
$xml=simplexml_load_file("http://widget.atings.com/widget/snippet/?seller_id=$seller_id") or die("Error: Cannot create object");
foreach($xml->children() as $child) :
endforeach;
// Load xml file content
$xml=simplexml_load_file("http://example.com/xml.xml") or die("Error: Cannot create object");
//Get children with foreach.
foreach($xml->children() as $child)
{ $inc = 1;
foreach($child->children() as $childs){
foreach($childs->children() as $childss){
if($inc == 7) :
if($childss->getName() === 'description') :
echo '<div class="descriptionOfNisab">'. $childss . '</div>';
endif;
endif;
}
$inc ++;
}
}

Restructure XML in PHP

I'm provided a XML file with this structure:
<items>
<item>
<images>
<image>A</image>
<image>B</image>
<image>C</image>
</images>
.
.
.
</item>
</items>
However the import function of my Shop requires the following format:
<items>
<item>
<images>
<image>A</image>
<image1>B</image>
<image2>C</image>
</images>
.
.
.
</item>
</items>
At first I was thinking I would do this simply in Java since it would be pretty easy to read line by line and restructure the document but I would love to have it so I can just visit a url and this is done for me.
Here is the approach I took:
<?php
$xml = simplexml_load_file('data.xml');
// Loop over items in original xml
for($i = 0; $i < count($xml->item); $i++)
{
$images;
if( ($c = count($xml->item[$i]->images->image)) > 1)
{
$images = $xml->item[$i]->images;
// Remove entry
unset($xml->item[$i]->images);
$xml->item[$i]->addChild('images');
for($y = 0; $y < count($images->image); $y++)
{
if($y == 0)
{
$xx = $xml->item[$i]->images->addChild('image', $images->image[$y]);
}else {
$xml->item[$i]->images->addChild('image' . $y, $images->image[$y]);
}
}
var_dump($images);
}
}
$xml->asXML('POTO.xml');
The dilemma I have tho is that none of the childs get added to images. I have been told I need to restructure the whole document but this is kind of silly if I var_dump just after removing the images node the node and it's children are all removed however when I go to add images node back to item node it and var_dump the node it shows the node was added to item node as a child however when I try to add image to images nothing gets added.
Do I really need to restructure the whole document because it seems simpler to do it in Java then. Or did I miss something.
Okay, I think the key problem here is that assigning the images to $images doesn't work like you'd expect. While such an assignment of a primitive makes a copy, assigning an object makes a reference to the same object (similar to a pointer you've worked with lower level languages). They do this because an object can be larger than a primitive, and unnecessary duplication of that is just wasteful.
However, in this case, the result is that when you unset the images from the main SimpleXML object, you're also destroying the instance in $images. Fortunately, there is a solution. You can clone the object, rather than assigning it. See http://www.php.net/manual/en/language.oop5.cloning.php
I modified your sample code here and it seems to work: http://3v4l.org/ZmRZV
Edit: cleaned up my code a little and included it:
<?php
//$xml = simplexml_load_file('data.xml');
$xml = simplexml_load_string('<items>
<item>
<images>
<image>A</image>
<image>B</image>
<image>C</image>
</images>
</item>
</items>');
// Loop over items in original xml
foreach ($xml->item as $item) {
if (count($item->images->image) > 1) {
// Clone entry
$images = clone $item->images;
// Remove entry and replace with empty
unset($item->images);
$item->addChild('images');
for ($i = 0; $i < count($images->image); $i++) {
$num = ($i > 0) ? $i : '';
$item->images->addChild('image'.$num, $images->image[$i]);
}
}
}
//$xml->asXML('POTO.xml');
echo $xml->asXML();
Looks like this doesn't work prior to version 5.2.1 (http://3v4l.org/m0VoD), but that's going back pretty far, really. Rasmus doesn't want anyone running less than 5.4 (http://www.youtube.com/watch?v=anr7DQnMMs0&t=10m27s), and I'm inclined to agree.
For the record, this behavior, of copying only the reference is not a quirk of PHP. It's a common practice. Further reading: http://en.wikipedia.org/wiki/Cloning_(programming)

Get Child Data from large XML file

I have an large XML file (26,434 lines) that I'm working with.
Excerpt XML:
<row name="Scorned Syndicate" shortName="-SS-" allianceID="1778325832" executorCorpID="98020631" memberCount="29" startDate="2010-08-14 00:29:00">
<rowset name="memberCorporations" key="corporationID" columns="corporationID,startDate">
<row corporationID="98020119" startDate="2011-02-09 04:52:00" />
<row corporationID="98020631" startDate="2011-02-23 23:55:00" />
</rowset>
</row>
By searching here I've found how I can get the alliance name and short name but now I want the corporationID
$xml = new XMLReader();
$xml->XML( $xmlString );
while( $xml->read() ) {
if( 'row' === $xml->name ) {
echo $xml->getAttribute('name') . ' '. $xml->getAttribute('shortName').'<br>';
$xml->next();
}
}
I researched enough to know I need to utilize a streaming reader for efficiency but not sure how to get the last part of my data.
When you use the next() function in the XMLReader the subtrees are skipped. Your while statement should advance it through automatically. If you need to see output before the entire file is parsed you might consider ob_flush, otherwise it would be better to create an array so that the format is more customizable.

Categories