I'm trying to write a parser for a xml postback listener, but can't seem to get it to dump the xml for a sample. The API support guy told me to use 'DOMDocument', maybe 'SimpleXML'? Anyways here's the code: (thanks!)
<?php
$xml_document = file_get_contents('php://input');
$doc = new DOMDocument();
$doc->loadXML($xml_document);
$doc->save("test2/".time().".sample.xml").".xml");
?>
How about use this to create an XML file?
/**
* Will output in a similar form to print_r, but the nodes are xml so can be collapsed in browsers
*
* #param mixed $mixed
*/
function print_r_xml($mixed)
{
// capture the output of print_r
$out = print_r($mixed, true);
// Replace the root item with a struct
// MATCH : '<start>element<newline> ('
$root_pattern = '/[ \t]*([a-z0-9 \t_]+)\n[ \t]*\(/i';
$root_replace_pattern = '<struct name="root" type="\\1">';
$out = preg_replace($root_pattern, $root_replace_pattern, $out, 1);
// Replace array and object items structs
// MATCH : '[element] => <newline> ('
$struct_pattern = '/[ \t]*\[([^\]]+)\][ \t]*\=\>[ \t]*([a-z0-9 \t_]+)\n[ \t]*\(/miU';
$struct_replace_pattern = '<struct name="\\1" type="\\2">';
$out = preg_replace($struct_pattern, $struct_replace_pattern, $out);
// replace ')' on its own on a new line (surrounded by whitespace is ok) with '</var>
$out = preg_replace('/^\s*\)\s*$/m', '</struct>', $out);
// Replace simple key=>values with vars
// MATCH : '[element] => value<newline>'
$var_pattern = '/[ \t]*\[([^\]]+)\][ \t]*\=\>[ \t]*([a-z0-9 \t_\S]+)/i';
$var_replace_pattern = '<var name="\\1">\\2</var>';
$out = preg_replace($var_pattern, $var_replace_pattern, $out);
$out = trim($out);
$out='<?xml version="1.0"?><data>'.$out.'</data>';
return $out;
}
Im my application I posted all of the $_POST variables to it:
$handle = fopen("data.xml", "w+");
$content = print_r_xml($_POST);
fwrite($handle,$content);
fclose();
Related
Good evening,
I am retrieving a JSON file and trying to read a variable at the very end of the file.
$eedomus_api_user = 'xyz';
$eedomus_api_secret = 'zzz';
$periph_id = 'yyy';
$url = "http://19X.XXX.0.XX/api/get?";
$url .= "api_user=$eedomus_api_user";
$url .= "&api_secret=$eedomus_api_secret";
$url .= "&action=periph.value";
$url .= "&periph_id=$periph_id";
$result = file_get_contents($url);
$phpObj = json_decode($result, true);
The file I'm getting is the following :
{ "success": 1, "body":{"last_value": 100} }
I'm interested in getting the '100' corresponding to the last_value field.
Using the function strpos, I'm intending to look for the position of the first '}' and retrieve the characters until the previous space. Is there an easier way to achieve this ?
Thanks for your help.
OK... I am using PHP 5 (be gentle, still learning PHP). CURL is enabled. Attempting to load XML or JSON output from an API to an object and nothing happens. When I manually execute the URL in question, I get what I am expecting.
Here is my code:
class XmlToJson {
public function Parse ($url) {
$fileContents = file_get_contents($url);
$fileContents = str_replace(array("\n", "\r", "\t"), '', $fileContents);
$fileContents = trim(str_replace('"', "'", $fileContents));
$simpleXml = simplexml_load_string($fileContents);
$json = json_encode($simpleXml);
return $json;
}
}
$_MySQLServer = "localhost";
$_MySQLServerUserName = "";
$_MySQLServerPassword = "";
$_MySQLDatabaseName = "";
$_SSActiveWear_UserID = "*****";
$_SSActiveWear_APIKey = "*****";
$_SSActiveWear_APIBaseURL = "https://*****/v2";
$_CategoryURL = "/categories/";
$_StylesURL = "/styles/";
$_ProductsURL = "/products/";
$_SpecsURL = "/specs/";
$_SSActiveWear_MediaType = "xml";
//$_conn = mysqli_connect($_MySQLServer, $_MySQLServerUserName, $_MySQLServerPassword, $_MySQLDatabaseName);
//Insert or Update Categories
$_URL = $_SSActiveWear_APIBaseURL . $_CategoryURL;
$_URL = $_URL . "?mediatype=$_SSActiveWear_MediaType&UserName=$_SSActiveWear_UserID&Password=$_SSActiveWear_APIKey";
$OBJ = simplexml_load_string($_URL);
print_r($OBJ);
What am I doing wrong?
Edit 1
Added the following code:
$xml = simplexml_load_file($_URL) or die("Error: Cannot create object");
print_r($xml);
and it dies. Does that mean that there is something wrong with the code?
Try this :
$OBJ = simplexml_load_string(file_get_contents($_URL));
If you want to know why your code is not working, you are trying to load XML from URL but "simplexml_load_string" loads XML from string.
I FINALLY figured it out... More to the point I finally found a site on Google that helped. It is the first answer in fsockopen with http authentication problem.
So here is the code that works:
file_get_contents("https://$_SSActiveWear_UserID:$_SSActiveWear_APIKey#$_SSActiveWear_APIBaseURL$_CategoryURL/?mediatype=$_SSActiveWear_MediaType");
mediatype can be either json or xml
As the code i tried and by trial removal to get json content out of the return is below
method i used.
$date= YYYYMMDD;
//example '20140113'
$handle = fopen('http://finance.yahoo.com/connection/currency-converter-cache?date='.$date.'', 'r');
//sample code is http://finance.yahoo.com/connection/currency-converter-cache?date=20140208 paste the url in browser;
// use loop to get all until end of content
while (!feof($handle)) {
$contents .= fread($handle, 8192);
}
fclose($handle);
the code return a given bulk in yahoo and json format
so remove the unknown format which is
"/**/YAHOO.Finance.CurrencyConverter.addConversionRates (" and ends with ");"
by
$contents = str_replace('/**/YAHOO.Finance.CurrencyConverter.addConversionRates(','',$contents);
$contents = str_replace(');','',$contents);
$obj = json_decode($contents,true);
then loop the content by
foreach($obj['list']['resources'] as $key0 => $value0){
}
I prefer to use file_get_contents to get the html and preg_match_all to cleanup the json, i.e.:
<?php
$json = file_get_contents("http://finance.yahoo.com/connection/currency-converter-cache?date=20140113");
preg_match_all('/\((.*)\);/si', $json, $json, PREG_PATTERN_ORDER);
$json = $json[1][0];
$json = json_decode($json,true);
foreach ($json["list"]["resources"] as $resource){
echo $resource["resource"]["fields"]["date"];
echo $resource["resource"]["fields"]["price"];
echo $resource["resource"]["fields"]["symbol"];
echo $resource["resource"]["fields"]["price"];
}
NOTE:
I've tested the code and it works as intended.
I have a script that appends XML data to the end of an XML file via PHP. The only problem is that after each new line of XML I add via the PHP script, an extra line (whitespace) is created. Is there a way to remove the whitespace from the XML file with PHP without loosing the neatly formated XML file? Here is my PHP code that writes to the XML file:
<?php
function formatXmlString($xml) {
// add marker linefeeds to aid the pretty-tokeniser (adds a linefeed between all tag-end boundaries)
$xml = preg_replace('/(>)(<)(\/*)/', "$1\n$2$3", $xml);
// now indent the tags
$token = strtok($xml, "\n");
$result = ''; // holds formatted version as it is built
$pad = 0; // initial indent
$matches = array(); // returns from preg_matches()
// scan each line and adjust indent based on opening/closing tags
while ($token !== false) :
// test for the various tag states
// 1. open and closing tags on same line - no change
if (preg_match('/.+<\/\w[^>]*>$/', $token, $matches)) :
$indent=0;
// 2. closing tag - outdent now
elseif (preg_match('/^<\/\w/', $token, $matches)) :
$pad=0;
// 3. opening tag - don't pad this one, only subsequent tags
elseif (preg_match('/^<\w[^>]*[^\/]>.*$/', $token, $matches)) :
$indent=4;
// 4. no indentation needed
else :
$indent = 0;
endif;
// pad the line with the required number of leading spaces
$line = str_pad($token, strlen($token)+$pad, ' ', STR_PAD_LEFT);
$result .= $line . "\n"; // add to the cumulative result, with linefeed
$token = strtok("\n"); // get the next token
$pad += $indent; // update the pad size for subsequent lines
endwhile;
return $result;
}
function append_xml($file, $content, $sibling, $single = false) {
$doc = file_get_contents($file);
if ($single) {
$pos = strrpos($doc, "<$sibling");
$pos = strpos($doc, ">", $pos) + 1;
}
else {
$pos = strrpos($doc, "</$sibling>") + strlen("</$sibling>");
}
return file_put_contents($file, substr($doc, 0, $pos) . "\n$content" . substr($doc, $pos));
}
$content = "<product><id>3</id><name>Product 3</name><price>63.00</price></product>";
append_xml('prudcts.xml', formatXmlString($content), 'url');
?>
Do not just put all in one line and you're more flexible:
return file_put_contents($file, substr($doc, 0, $pos) . "\n$content" . substr($doc, $pos));
Instead (suggestion):
$buffer = substr($doc, 0, $pos) . "\n$content" . substr($doc, $pos);
$buffer = rtrim($buffer);
return file_put_contents($file, $buffer);
P.S: Using DomDocument might be more straight forward and save for XML processing then the string functions.
Instead of appending new data to $result and then a newline, do the reverse.
Use something like if( !empty($result) ) { result .= "\n" } to avoid beginning the XML data with a newline.
I tried this to format the XML output in a PHP function with the formatoutput = true and that didn't do it. So I want to do this with a function. I found two different scripts for that but they all have the same issue: they do the indentation but the newline "\n" doesn't print in the file. Is there a different way to get the newline?
PHP script
<?php
ini_set('display_errors', 1);
error_reporting(E_ALL);
function make_update( $nodeid, $name, $top, $left, $width, $height ) {
$nodes = new SimpleXMLElement('linkcards.xml', null, true);
$returnArray = $nodes->xpath("//LINKCARD[#ID='$nodeid']");
$node = $returnArray[0];
$node->NAME = $name;
$node->TOP = $top;
$node->LEFT = $left;
$node->WIDTH = $width;
$node->HEIGHT = $height;
$nodes->asXML('linkcards.xml');
$formatted = formatXmlString($nodes->asXML());
$file = fopen ('linkcards.xml', "w");
fwrite($file, $formatted);
fclose ($file);
}
echo make_update(trim($_REQUEST['nodeid']),trim($_REQUEST['name']),trim($_REQUEST['top']),trim($_REQUEST['left']),trim($_REQUEST['width']),trim($_REQUEST['height']));
function formatXmlString($xml) {
// add marker linefeeds to aid the pretty-tokeniser (adds a linefeed between all tag-end boundaries)
$xml = preg_replace('/(>)(<)(\/*)/', "$1\n$2$3", $xml);
// now indent the tags
$token = strtok($xml, "\n");
$result = ''; // holds formatted version as it is built
$pad = 0; // initial indent
$matches = array(); // returns from preg_matches()
// scan each line and adjust indent based on opening/closing tags
while ($token !== false) :
// test for the various tag states
// 1. open and closing tags on same line - no change
if (preg_match('/.+<\/\w[^>]*>$/', $token, $matches)) :
$indent=0;
// 2. closing tag - outdent now
elseif (preg_match('/^<\/\w/', $token, $matches)) :
$pad--;
// 3. opening tag - don't pad this one, only subsequent tags
elseif (preg_match('/^<\w[^>]*[^\/]>.*$/', $token, $matches)) :
$indent=1;
// 4. no indentation needed
else :
$indent = 0;
endif;
// pad the line with the required number of leading spaces
$line = str_pad($token, strlen($token)+$pad, ' ', STR_PAD_LEFT);
$result .= $line . "\n"; // add to the cumulative result, with linefeed
$token = strtok("\n"); // get the next token
$pad += $indent; // update the pad size for subsequent lines
endwhile;
return $result;
}
?>
Found the answer. If I write "\r\n" for the newline, it works!!!!!!
$result .= $line . "\r\n";
Using that function instead of formatoutput = true might be a useful workaround for anyone else who had trouble formatting the XML output.