I have some code that pulls HTML from an external source:
$doc = new DOMDocument();
#$doc->loadHTML($html);
$xml = #simplexml_import_dom($doc); // just to make xpath more simple
$images = $xml->xpath('//img');
$sources = array();
Then, if I add all of the sources with this code:
foreach ($images as $i) {
array_push($sources, $i['src']);
}
echo "<pre>";
print_r($sources);
die();
I get this result:
Array
(
[0] => SimpleXMLElement Object
(
[0] => /images/someimage.gif
)
[1] => SimpleXMLElement Object
(
[0] => /images/en/someother.jpg
)
....
)
But when I use this code:
foreach ($images as $i) {
$sources[] = (string)$i['src'];
}
I get this result (which is what is desired):
Array
(
[0] => /images/someimage.gif
[1] => /images/en/someother.jpg
...
)
What is causing this difference?
What is so different about array_push()?
Thanks,
EDIT: While I realize the answers match what I am asking (I've awarded), I more wanted to know why whether using array_push or other notation adds the SimpleXMLElement Object and not a string when both arent casted. I knew when explicitly casting to a string I'd get a string. See follow up question here:Why aren't these values being added to my array as strings?
The difference is not caused by array_push() -- but by the type-cast you are using in the second case.
In your first loop, you are using :
array_push($sources, $i['src']);
Which means you are adding SimpleXMLElement objects to your array.
While, in the second loop, you are using :
$sources[] = (string)$i['src'];
Which means (thanks to the cast to string), that you are adding strings to your array -- and not SimpleXMLElement objects anymore.
As a reference : relevant section of the manual : Type Casting.
Sorry, just noticed better answers above, but the regex itself is still valid.
Are you trying to get all images in HTML markup?
I know you are using PHP, but you can convert use this C# example of where to go:
List<string> links = new List<string>();
if (!string.IsNullOrEmpty(htmlSource))
{
string regexImgSrc = #"<img[^>]*?src\s*=\s*[""']?([^'"" >]+?)[ '""][^>]*?>";
MatchCollection matchesImgSrc = Regex.Matches(htmlSource, regexImgSrc, RegexOptions.IgnoreCase | RegexOptions.Singleline);
foreach (Match m in matchesImgSrc)
{
string href = m.Groups[1].Value;
links.Add(href);
}
}
In your first example, you should:
array_push($sources, (string) $i['src']);
Your second example gives an array of strings because you are converting the SimpleXMLElements to strings using the (string) cast. In your first example you are not, so you get an array of SimpleXMLElements instead.
Related
I been looking thru the posts here all day but can't figure out what I'm doing wrong. (I'm new to php and json)
Here is my code that work.
$json = '{"id":1234,"img":"1.jpg"}';
$data = json_decode($json, true);
echo $data["img"];
But when the json respond is this
$json = '{"demo1":[{"id":1234,"img":"1.jpg"}],"userId":1}';
it's a big harder for me. then img is a child of demo1? How to get it?
Thx. :)
Figuring out the array indices
As you're new to PHP, I'll explain how to figure out the array indces of the required array value. In PHP, there are many functions for debugging — print_r() and var_dump() are two of them. print_r() gives us a human-readable output of the supplied array, and var_dump() gives us a structured output along with the variable types and values.
In this case, print_r() should suffice:
$json = '{"demo1":[{"id":1234,"img":"1.jpg"}],"userId":1}';
$data = json_decode($json, true);
// wrap the output in <pre> tags to get a prettier output
echo '<pre>';
print_r($data);
echo '</pre>';
This will produce the following output:
Array
(
[demo1] => Array
(
[0] => Array
(
[id] => 1234
[img] => 1.jpg
)
)
[userId] => 1
)
From there, it should be pretty easy for you to figure out how to access the required vaule.
$data['demo1'][0]['img'];
Creating a helper function for ease of use
For ease of use, you can create a helper function to make this process easier. Whenever you want to view the contents of an array, you can simply call dump_array($array); and be done with it. No more messing around with <pre> tags or print_r().
Function code:
function dump_array($array) {
echo '<pre>' . print_r($array, TRUE) . '</pre>';
}
Usage example:
$arr = ['foo' => range('a','i'), 'bar' => range(1,9)];
dump_array($arr);
after decoding :
echo $data->demo[0]->img;
Basically, a { in JSON leads to a -> (it's an object).
And a [ to a [], it's an array.
I am currently attempting to extract values from an array that was generated by an SIMPLEXML/XPATH Query. I have had no success with my attempts if anyone can take look would be greatly appreciated.
I am looking just to extract ReclaimDate. I have tried a few functions and some of the advice on this post with no luck.
Array
(
[0] => Array
(
[0] => SimpleXMLElement Object
(
[#attributes] => Array
(
[ReclaimDate] => 05/15/2008
[ReclaimPrice] => 555555555
[_Owner] => ownername
)
)
)
If I just had to take a stab, I'd agree that what #Frank Farmer said should work:
// if $myVar is what you print_r'ed
echo (string)$myVar[0][0]['ReclaimDate'];
or this
echo (string)$myVar[0][0]->attributes('ReclaimDate');
http://www.php.net/manual/en/simplexml.examples-basic.php#example-4587
This is resolved thanks to Frank Farmer and Dan Beam.
This worked : echo (string)$check_reo[0][0]['ReclaimDate']
For anyone that is looking to use SimpleXML and XPATH to extract and write some basic logic from an XML file this is what worked for me.
$xmlstring = <<<XML <?xml version='1.0' standalone='yes'?> <YOURXMLGOESHERE>TEST</YOURXMLGOESHERE> XML;
$xpathcount = simplexml_load_string($xmlstring); // Load XML for XPATH Node Counts
$doc = new DOMDocument(); // Create new DOM Instance for Parsing
$xpathcountstr = $xpathcount->asXML(); // Xpath Query
$doc->loadXML($xpathcountstr); // Load Query Results
$xpathquery = array($xpathcount->xpath("//XMLNODEA[1]/XMLNODEB/*[name()='KEYWORDTOCHECKIFXMLCEXISTS']"));
print_r ($xpathquery) // CHECK Array that is returned from the XPATH query
`Array
(
[0] => Array
(
[0] => SimpleXMLElement Object
(
[#attributes] => Array
(
[ReclaimDate] => 05/15/2008
[ReclaimPrice] => 555555555
[_Owner] => ownername
)
)
) // Array RETURNED`
echo (string)$xpathquery[0][0]['ReclaimDate'] // EXTRACT THE VALUE FROM THE ARRAY COLUMN;
This site helped me receive a better understanding on how XPATH can search XML very easily with a lot more features than what I had previously known.
http://zvon.org/xxl/XPathTutorial/Output/examples.html
Here is the simple XML Function that worked for me
$xmlread = simplexml_load_string($xmlstring, "simple_xml_extended");
`class simple_xml_extended extends SimpleXMLElement { // Read XML and get attribute
public function Attribute($name){
foreach($this->Attributes() as $key=>$val) {
if($key == $name)
return (string)$val;
}
}
}`
Here is the Function action when extracting Single Values with an attribute based XML results
$GETVAR1 = $xmlread->XMLNODE1->XMLNODE2->XMLNODE3->XMLNODE4->XMLNODE5[0]->Attribute('XMLNODE5ATTRIBUTE');
This might not be the most efficient or best method, but its what ended working our for me. Hope this helps someone out who is still unclear about SIMPLEXML and XPATH.
An additional link for further insight: http://www.phpfreaks.com/tutorial/handling-xml-data
I'm requesting data from an online source which I then decode into json StdClass objects (using php). Once I've done this I have the following (see below). I'm trying to extract the elements in 'otherstuff' by doing echo $response->stuff->WHAT GOES HERE?->otherstuff
However I cant hard code the [2010-12] because its a date, is there any way I can call e.g. $response->stuff->nextsibling->stuff
I hope this makes sense to someone :D Currently i'm bastardising this with a $key => $value for loop and extracting the key value and using it in my $response->stuff->$key->stuff call.
stdClass Object
(
[commentary] =>
[stuff] => stdClass Object
(
**[2010-12]** => stdClass Object
(
[otherstuff] => stdClass Object
(
[otherstuffrate] => 1
[otherstufflevel] => 1
[otherstufftotal] => 1
)
)
)
)
StdClass instances can be used with some Array Functions, among them
current — Return the current element in an array and
key — Fetch a key from an array
So you can do (codepad)
$obj = new StdClass;
$obj->{"2012-10"} = 'foo';
echo current($obj); // foo
echo key($obj); // 2012-10
On a sidenote, object properties should not start with a number and they may not contain dashes, so instead of working with StdClass objects, pass in TRUE as the second argument to json_decode. Returned objects will be converted into associative arrays then.
The date key must be a string, otherwise PHP breaks ;).
echo $response->stuff['2010-12']->otherstuff
Retrieve it using a string.
Edited again: added object code also
json decode it as associative array, and use key fetched through array_keys . See it work here : http://codepad.org/X8HCubIO
<?php
$str = '{
"commentary" : null,
"stuff" : {
"ANYDATE" : {
"otherstuff": {
"otherstuffrate" : 1,
"otherstufflevel" : 1,
"otherstufftotal" : 1
}
}
}
}';
$obj = json_decode($str,true);
$reqKey = array_keys($obj["stuff"]);
$req = $obj["stuff"][$reqKey[0]]["otherstuff"];
print_r($req);
print "====================as object ============\n";
$obj = json_decode($str);
$req = current($obj->stuff)->otherstuff;
print_r($req);
?>
I am trying to convert some xml into a json object using PHP.
This should be working, yet for some bizarre reason it is failing.
Could someone provide some input.
// Loop Through images and return the right one.
$i = 1;
foreach($page->image as $image) {
if ($i == $_GET['id']) {
echo json_encode(array(
'background' => $image['bgColor'],
'image' => $image['source'],
'caption' => $image['caption']
));
}
$i++;
}
This code returns the following.
{"background":{"0":"000033"},
"image":"0":"0210e849f02646e2f5c08738716ce7e8b3c1169112790078351021245495.jpg"},
"caption": {"0":"Frog"}}
print_r($image['bgColor']); shows 'SimpleXMLElement Object ( [0] => 000033 )'
echo $image['bgColor']; shows '000033'
How do I parse values like the echo statement instead of the print_r statement. Why are these different?
Why are these different
Because these variables are not strings internally, but SimpleXMLElement type objects that get converted into strings when output by echo.
To use the values elsewhere,I usually do an explicit cast:
$bg_color = (string) $image['bgColor'];
A canonical question regarding casting a simplexml element into a string is here:
Forcing a SimpleXML Object to a string, regardless of context
I have a multi-dimensional multi-object array from a simplexml_import_dom() function call.
A slice of one section of the array:
[Price] => SimpleXMLElement Object
(
[Prices] => Array
(
[0] => SimpleXMLElement Object
(
[#attributes] => Array
(
[MType] => A
[PType] => R
This is causing me quite a bit of problems when trying to read nested objects. I have tried to loop through the array using multiple get_object_vars() but because the depth and location of the nested objects is continually changing I haven't been able to yield desirable results.
Does PHP contain a function that I haven't been able to find to convert a multi-dimensional multi-object array to a standard multi-dimensional array? Or has anyone solved this problem before?
Thanks for your help!
The question is often asked, but there's a fundamental issue that has to be addressed on a case-by-case basis when converting a XML tree to an array, which makes an one-size-fits-all method impossible: how do you differentiate nodes from attributes?
For instance, how would you convert this XML to an array:
<node val="attr"><val>child</val></node>
Also, a node can have any number of children with the same name, which you can't emulate with an associative array.
Long story short, you'll have to cook up your own solution. Judging from your output, it would look something like this:
$arr = array();
foreach ($Price->Prices as $Prices)
{
$tmp = array();
foreach ($Prices->attributes() as $k => $v)
{
$tmp[$k] = (string) $v;
}
$arr[] = $tmp;
}
If it's not what you're looking for, please edit your question and add an example of the source document (XML) as well as the expected result (the array.)
Are you aware that these objects have functions that you can use? Try the following:
foreach ($simpleXmlObject->children() as $element) {
echo $element->getName();
}