I've been trying unsuccessfully with PHP to loop through two XML files and print the result to the screen. The aim is to take a country's name and output its regions/states/provinces as the case may be.
The first block of code successfully prints all the countries but the loop through both files gives me a blank screen.
The countries file is in the format:
<row>
<id>6</id>
<name>Andorra</name>
<iso2>AD</iso2>
<phone_code>376</phone_code>
</row>
And the states.xml:
<row>
<id>488</id>
<name>Andorra la Vella</name>
<country_id>6</country_id>
<country_code>AD</country_code>
<state_code>07</state_code>
</row>
so that country_id = id.
This gives a perfect list of countries:
$xml = simplexml_load_file("countries.xml");
$xml1 = simplexml_load_file("states.xml");
foreach($xml->children() as $key => $children) {
print((string)$children->name); echo "<br>";
}
This gives me a blank screen except for the HTML stuff on the page:
$xml = simplexml_load_file("countries.xml");
$xml1 = simplexml_load_file("states.xml");
$s = "Jamaica";
foreach($xml->children() as $child) {
foreach($xml1->children() as $child2){
if ($child->id == $child2->country_id && $child->name == $s) {
print((string)$child2->name);
echo "<br>";
}
}
}
Where have I gone wrong?
Thanks.
I suspect your problem is not casting the name to a string before doing your comparison. But why are you starting the second loop before checking if it's needed? You're looping through every single item in states.xml needlessly.
$countries = simplexml_load_file("countries.xml");
$states = simplexml_load_file("states.xml");
$search = "Jamaica";
foreach($countries->children() as $country) {
if ((string)$country->name !== $search) {
continue;
}
foreach($states->children() as $state) {
if ((string)$country->id === (string)$state->country_id) {
echo (string)$state->name . "<br/>";
}
}
}
Also, note that naming your variables in a descriptive manner makes it much easier to figure out what's going on with code.
You could probably get rid of the loops altogether using an XPath query to match the sibling value. I don't use SimpleXML, but here's what it would look like with DomDocument:
$search = "Jamaica";
$countries = new DomDocument();
$countries->load("countries.xml");
$xpath = new DomXPath($countries);
$country = $xpath->query("//row[name/text() = '$search']/id/text()");
$country_id = $country[0]->nodeValue;
$states = new DomDocument();
$states->load("states.xml");
$xpath = new DomXPath($states);
$states = $xpath->query("//row[country_id/text() = '$country_id']/name/text()");
foreach ($states as $state) {
echo $state->nodeValue . "<br/>";
}
Hi i want to create a php code which generates xml of specific format given below. Kindly help me through this
<?xml version="1.0" encoding="utf-8"?>
<order>
<requisition>
<dateofservice>2012-12-13</dateofservice>
<labid>str1234</labid>
<reqnotes_c>str1234</reqnotes_c>
<rptemail_c>str1234</rptemail_c>
<rptmethod_c>str1234</rptmethod_c>
<specimen_type_c>str1234</specimen_type_c>
<collectiontype_c>str1234</collectiontype_c>
</requisition>
<patient>
<firstname>str1234</firstname>
<lastname>str1234</lastname>
<dob>2012-12-13</dob>
<breed_c>str1234</breed_c>
<species>str1234</species>
<sex>s</sex>
<sterilization_c>str1234</sterilization_c>
</patient>
</order>
My code is this Now correct me please. My code gives only one parent and i want to generate the output as given above
while (($row = fgetcsv($inputFile)) !== FALSE){
$container = $doc->createElement('row');
foreach($headers as $i => $header) {
if(!empty($row[$i])) {
$child = $doc->createElement($header);
$child = $container->appendChild($child);
$value = $doc->createTextNode($row[$i]);
$value = $child->appendChild($value);
}
}
$root->appendChild($container);
}
$strxml = $doc->saveXML();
I have an ecommerce website in which regularly transactions keeps happening. Now we are developing an android app for the same. So I was asked to build an API using PHP. The API that i made was in xml format. But now since i will be sending he login credentials through it I am scared that someone would hack it. So can someone help me with it.
here is the way i had created the xml API using php..
<?php
include 'config.php';
include 'database.php';
$sqlCat = "select category_id,image,name from table" ;
$categories = DatabaseHandler::GetAll($sqlCat);
$xml = new DomDocument("1.0","UTF-8");
$content = $xml->createElement("content");
$content = $xml->appendChild($content);
foreach($categories as $category) {
$item = $xml->createElement("item");
$catName = $xml->createElement("catName",htmlspecialchars($category['name']));
$catName = $item->appendChild($catName);
$catImage = $xml->createElement("catImage",htmlspecialchars($category['image']));
$catImage = $item->appendChild($catImage);
$sql = "select image,name,model,price,quantity from table;
$results = DatabaseHandler::GetAll($sql);
foreach($results as $key=>$result) {
$product = $xml->createElement("product");
$product->setattribute('id',$key);
$model = $xml->createElement("model",$result['model']);
$model = $product->appendChild($model);
$name = $xml->createElement("name",htmlspecialchars($result['name']));
$name = $product->appendChild($name);
$image = $xml->createElement("image",htmlspecialchars($result['image']));
$image = $product->appendChild($image);
$price = $xml->createElement("price",$result['price']);
$price = $product->appendChild($price);
$product = $item->appendChild($product);
}
$item = $content->appendChild($item);
}
$xml->FormatOutput = true;
$output = $xml->saveXML();
$xml->save("categories.xml");
?>
and I get the xml in this form..
<content>
<item>
<catName>Comp</catName>
<catImage/>
<product id="0">
<model>156443</model>
<name>CD</name>
<image>109.jpg</image>
<price>48</price>
</product>
<product id="1">
<model>46876</model>
<name>memory card</name>
<image>81.jpg</image>
<price>12</price>
</product>
<product id="2">
<model>865793</model>
<name>drive</name>
<image>51.png</image>
<price>2</price>
</product>
</item>
</content>
Can someone tell whether the way i have generated API in XML format correct.
Dont make think too complex make it simple like following code
$con = mysql_connect("localhost","root","root") or die("could not connect".mysql_error());
//select your database table
mysql_select_db("android_maps", $con) or die("Could not select database".mysql_error());
//get your results with a mysql query
$result = mysql_query("SELECT gmaps.*, urls.* FROM gmaps, urls WHERE urls.idgmaps = gmaps.idgmaps") or die(mysql_error());
//run a while loop get your data.
while($location = mysql_fetch_array($result)) {
$output = '<?xml version="1.0" encoding="utf-8"?>';
$output .= '<data>';
$output .= "<lat>".$location['lat']."</lat>";
$output .= "<long>.".$location['lon']."</long>";
$output .= "<description>.".$location['description']."</description>";
$output .= '</data>';
print $output;
}
mysql_close($con);
}else{
echo "<h1>No results to show for you query</h1>";
}
for more info
http://teachingyou.net/php/php-api-development-dreaming-of-your-own-api-make-it-possible-today/
I have this XML feed below I am trying to import into MySQL for all the products.
For example, inside the table XML_FEED I want something like
shop - product_id - product_name - product_link - .......
mywebstore - 322233 - MadBiker 600 - .........
mywebstore - 324633 - Samsung S4 - .........
The code until now it works only if the XML begins from <products> and not from <mywebstore>
How to change my code to do this ?
$xml = simplexml_load_file("test.xml");
foreach($xml->product as $product)
{
$columns = array();
$data = array();
foreach($product->children() as $child)
{
echo $child->getName() . ": " . $child . "<br />";
$columns[] = $child->getName();
$data[] = mysql_real_escape_string((string)$child);
}
$col = '`'. implode('`,`',$columns) .'`';
$val = "'". implode("','",$data)."'";
$query = "INSERT INTO XML_FEED ($col) VALUES ($val)";
echo $query;
mysql_query($query);
}
Here is the XML:
<?xml version="1.0" encoding="UTF-8"?>
<mywebstore>
<created_at>2010-04-08 12:32</created_at>
<products>
<product>
<id>322233</id>
<name><![CDATA[MadBiker 600]]></name>
<link><![CDATA[http://www.mywebstore.co.uk/product/322233]]></link>
<image><![CDATA[http://www.mywebstore.co.uk/product/322233.jpg]]></image>
<category><![CDATA[Outdor > Extreme Sports]]></category>
<price_with_vat>322.33</price_with_vat>
</product>
...
...
...
</products>
</mywebstore>
Use This code:
<?php
$xml = simplexml_load_file('test.xml');
foreach($xml->products->product as $product)
{
$columns = array();
$data = array();
foreach($product->children() as $child)
{
echo $child->getName() . ": " . $child . "<br />";
$columns[] = $child->getName();
$data[] = mysql_real_escape_string((string)$child);
}
$col = '`'. implode('`,`',$columns) .'`';
$val = "'". implode("','",$data)."'";
$query = "INSERT INTO XML_FEED ($col) VALUES ($val)";
echo $query;
mysql_query($query);
}
?>
This should work for you:
<?php
//Xml stuff
$xml = simplexml_load_file("file.xml");
//Database stuff
$hostname = "localhost";
$username = "root";
$password = "";
try {
//DB Connection
$dbh = new PDO("mysql:host=$hostname;dbname=dbname", $username, $password);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
echo "Connected to Database<br/>";
foreach($xml->products->product as $data) {
$sql = "INSERT INTO XML_FEED (shop, product_id, product_name, product_link, product_image, product_category, product_price_with_vat)
VALUES (:SHOP, :ID, :NAME, :LINK, :IMAGE, :CATEGORY, :PRICE)";
$stmt = $dbh->prepare($sql);
$params = array(
"SHOP" => $xml->getName(),
"ID" => $data->id ,
"NAME" => $data->name,
"LINK" => $data->link,
"IMAGE" => $data->image,
"CATEGORY" => $data->category,
"PRICE" => $data->price_with_vat
);
$stmt->execute($params);
}
//Close Connection
$dbh = null;
} catch(PDOException $e) {
echo $e->getMessage();
}
?>
Site Note:
Add error reporting to the top of your file(s) which will help during production testing.
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
?>
Also if you want to show/see the data in html you can use this:
<?php
//Xml stuff
$xml = simplexml_load_file("file.xml");
echo "<table border='1'>";
echo "<tr>
<td>Shop</td>
<td>Product ID</td>
<td>Product Name</td>
<td>Product Link</td>
<td>Product Image</td>
<td>Product Category</td>
<td>Product Price with vat</td>
</tr>";
foreach($xml->products->product as $data) {
echo "<tr>
<td>" . $xml->getName() . "</td>
<td>" . $data->id . "</td>
<td>" . $data->name . "</td>
<td>" . $data->link . "</td>
<td>" . $data->image . "</td>
<td>" . $data->category . "</td>
<td>" . $data->price_with_vat. "</td>
</tr>";
}
echo "</table>";
?>
You are not able to get data because of missing or invalid parent node.
While working with XML needs to handle parent and child(children) node
relationship carefully. Unfortunately you have missed the exact same
thing.
When you use mywebstore node as a parent then its intermediate child node is products and products child node is product.
But when you use products node as a parent then its child node is product.
In your code you have handled the second condition. You have to handle the both conditions or you can use the first condition in your code.
Example:
<?php
$file = 'test.xml';
$xml = simplexml_load_file($file, null, LIBXML_NOCDATA);
if($xml === false){
echo "Failed to load '$file'.\n";
}else{
$productsArr = Array();
if(isset($xml->products)){
$productsArr = $xml->products;
}else if(isset($xml->product)){
$productsArr = $xml;
}
if(sizeof($productsArr) > 0){
foreach($productsArr->product as $productArr){
$productArr = (array) $productArr;
$id = null;
if(isset($productArr['#attributes'])){
$id = $productArr['#attributes']['id'];
unset($productArr['#attributes']);
}
if(!isset($productArr['id']) && !empty($id)){
$productArr['id'] = $id;
}
array_walk_recursive($productArr, function (&$value) {
$value = htmlentities($value,ENT_QUOTES,'UTF-8');
$value = mysql_real_escape_string($value);
});
$col = '`'. implode('`,`',array_keys($productArr)) .'`';
$val = "'". implode("','",array_values($productArr))."'";
$query = "INSERT INTO projectx ($col) VALUES ($val)";
echo "$query \n";
mysql_query($query);
}
}else{
echo "Invalid XML Format.Missing parent node '<mywebstore> or <products>'. \n";
}
}
XML:
Format with <mywebstore> as parent node XML with attribute ID:
`
<?xml version="1.0" encoding="UTF-8"?>
<mywebstore>
<created_at>2010-04-08 12:32</created_at>
<products>
<product id="322233">
<name><![CDATA[MadBiker' 600]]></name>
<link><![CDATA[http://www.mywebstore.co.uk/product/322233]]></link>
<image><![CDATA[http://www.mywebstore.co.uk/product/322233.jpg]]></image>
<category><![CDATA[Outdor > Extreme Sports]]></category>
<price_with_vat>322.33</price_with_vat>
</product>
<product>
<id>322234</id>
<name><![CDATA[MadBiker 700]]></name>
<link><![CDATA[http://www.mywebstore.co.uk/product/322233]]></link>
<image><![CDATA[http://www.mywebstore.co.uk/product/322233.jpg]]></image>
<category><![CDATA[Outdor > Extreme Sports]]></category>
<price_with_vat>344.00</price_with_vat>
</product>
</products>
</mywebstore>
Format with <mywebstore> as parent node XML without attribute ID (Same as Question XML):
`
<?xml version="1.0" encoding="UTF-8"?>
<mywebstore>
<created_at>2010-04-08 12:32</created_at>
<products>
<product>
<id>322233</id>
<name><![CDATA[MadBiker 600]]></name>
<link><![CDATA[http://www.mywebstore.co.uk/product/322233]]></link>
<image><![CDATA[http://www.mywebstore.co.uk/product/322233.jpg]]></image>
<category><![CDATA[Outdor > Extreme Sports]]></category>
<price_with_vat>322.33</price_with_vat>
</product>
</products>
</mywebstore>
`
Format with <products> as parent node XML with attribute ID:
`
<?xml version="1.0" encoding="UTF-8"?>
<products>
<product id="322233">
<name><![CDATA[MadBiker' 600]]></name>
<link><![CDATA[http://www.mywebstore.co.uk/product/322233]]></link>
<image><![CDATA[http://www.mywebstore.co.uk/product/322233.jpg]]></image>
<category><![CDATA[Outdor > Extreme Sports]]></category>
<price_with_vat>322.33</price_with_vat>
</product>
<product>
<id>322234</id>
<name><![CDATA[MadBiker 700]]></name>
<link><![CDATA[http://www.mywebstore.co.uk/product/322233]]></link>
<image><![CDATA[http://www.mywebstore.co.uk/product/322233.jpg]]></image>
<category><![CDATA[Outdor > Extreme Sports]]></category>
<price_with_vat>344.00</price_with_vat>
</product>
</products>
`
Format with <products> as parent node XML without attribute(ID):
`
<?xml version="1.0" encoding="UTF-8"?>
<products>
<product>
<id>322233</id>
<name><![CDATA[MadBiker 600]]></name>
<link><![CDATA[http://www.mywebstore.co.uk/product/322233]]></link>
<image><![CDATA[http://www.mywebstore.co.uk/product/322233.jpg]]></image>
<category><![CDATA[Outdor > Extreme Sports]]></category>
<price_with_vat>322.33</price_with_vat>
</product>
</products>
Conclusion: In valid handling of parents & child node relationship.
Simply change this:
foreach($xml->product as $product)
{
with this:
foreach($xml->products[0] as $product)
{
In order to get the different products you should use xpath
Code:
$xml = simplexml_load_file("xml.xml");
// will search for array of products no matter what it is nested inside of
$products = $xml->xpath('//product');
foreach($products as $product)
{
$columns = array();
$data = array();
foreach($product->children() as $child)
{
echo $child->getName() . ": " . $child . "<br />";
$columns[] = $child->getName();
$data[] = mysql_real_escape_string((string)$child);
}
$col = '`'. implode('`,`',$columns) .'`';
$val = "'". implode("','",$data)."'";
$query = "INSERT INTO XML_FEED ($col) VALUES ($val)";
echo $query;
mysql_query($query);
}
Explanation:
Xpath for simplexml simply returns an array of the simple xml objects or here the product xml elements.
Since we want to return an array of all the products, we search "foreach" occurrence of the product using xpath.
Inside of the xpath string, A double slash (//) signals that all elements in the XML document that match the search criteria are returned, regardless of location/level within the document.
Firstly, simplexml_load_file() returns a pointer to the root element of the XML feed, i.e. the very first XML tag in the input file. In other words, when you write:
$xml = simplexml_load_file("test.xml");
if test.xml contains "<mywebstore> <products> <product> (...)" then $xml points at <mywebstore>
if test.xml contains "<products> <product> (...)" then $xml points at <products>
Secondly, $xml->[tagName] looks for direct children only, not recursively. Therefore $xml->product finds something only if a <product> tag exists as a child of the root element.
In general, it is better for the code to match the input structure exactly. Adapt your outer loop to the expected input:
foreach($xml->product as $product) {
...
}
or
foreach($xml->products->product as $product) {
...
}
If for some reason the <products> tag can be at various locations in the input XML feed, perhaps proceed in two steps:
// try to locate the <product> nodes
if (count($xml->product) !== 0) {
$productNodes = $xml->product;
} else if (count($xml->products->product) !== 0) {
$productNodes = $xml->products->product;
} else {
throw new Exception('No <product> node found');
}
// do the job
foreach($productNodes as $product){
...
}
Or for extreme flexibility, use an xpath. The below will return a list of all <product> nodes anywhere in the XML feed.
$productNodes = $xml->xpath('//product');
foreach($productNodes as $product){
...
}
I trust the MySQL part is not an issue, so I will just stick to the usual incantation:
Please, don't use mysql_* functions in new code. They are no longer maintained and are officially deprecated. See the red box? Learn about prepared statements instead, and use PDO or MySQLi - this article will help you decide which. If you choose PDO, here is a good tutorial.
I get response from SOAP server which has zero or more transactions of different types in each response.
Each transaction type is extension of base transaction type.
Different transaction types are processed differently.
Is there a way in PHP to get transaction type for each of transactions in response
(other then trying to figure difference in elements within each complex type)?
There is lot of types and lot of elements in each type....
Is there any class which could get this?
Following is just illustration...
<transactions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns2:type1">
<id>24111</id><something>00000000</something><name>Blah</name>
</transactions>
<transactions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns2:type8">
<id>24111</id><somethingelse>011</somethingelse>
</transactions>
I 'm not quite sure if this answer fits your question exactly. The following code snippet gets the type attribute value by their given namespaces and not the type of the namespaced value itself.
Done with PHP 's own Document Object Model.
<?php
$str = <<<XML
<content>
<transactions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns2:type1">
<id>24111</id>
<something>00000000</something>
<name>Blah</name>
</transactions>
<transactions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns2:type8">
<id>24111</id>
<somethingelse>011</somethingelse>
</transactions>
</content>
XML;
$doc = new DomDocument();
$doc->loadXML($str);
$nodeList = $doc->getElementsByTagName('transactions');
foreach ($nodeList as $element) {
$value = $element->getAttributeNS('http://www.w3.org/2001/XMLSchema-instance', 'type');
echo $value . "\n";
}
This will output the two given types "ns2:type1" and "ns2:type8".
I can parse your elements with simple_html_dom.
Here is the link for it.
An example is here :
<?php
include "simple_html_dom.php";
$html_nb = '
<transactions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns2:type1"><id>24111</id><something>00000000</something><name>Blah</name>
</transactions>
<transactions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns2:type8"><id>24111</id><somethingelse>011</somethingelse>
</transactions>';
function chtml($str){
if(strpos("<html>", $str) !== false)
return '<html><whole_code>'.$str.'</whole_code></html>';
else
return "<whole_code>".$str."</whole_code>";
}
function find_element_type($str){
if(preg_match_all("/\<(.*?)\>/i", $str, $matches))
return $matches[1][0];
else
return false;
}
function get_xsi_type($str){
if(preg_match_all("/xsi\:type\=\"(.*?)\"/i", $str, $matches))
return $matches[1][0];
else
return false;
}
$html = new simple_html_dom();
$html_2 = new simple_html_dom();
$html->load(chtml($html_nb));
$max_type = 10;
$element = $html->find('whole_code');
$e = $element[0]->innertext;
$html_2->load(chtml($e));
$k = 0;
while($html_2->find("whole_code",false)->children($k) != "")
{
$all = $html_2->find("whole_code",false)->children($k);
echo get_xsi_type($all) . "<br>";
echo find_element_type($all) . " : " .$all."<br>";
$k++;
}
echo "<hr>";
The result :
ns2:type1
transactions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns2:type1" : 2411100000000Blah
ns2:type8
transactions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns2:type8" : 24111011