SimpleXMLElement get non-attribute values - php

I have the following SimpleXMLElement:
object(SimpleXMLElement)#10 (3) {
["#attributes"]=> array(3) {
["id"]=> string(8) "18022352"
["name"]=> string(14) "The Salmon Man"
["slug"]=> string(14) "the-salmon-man"
}
["bids"]=> object(SimpleXMLElement)#11 (1) {
["price"]=> array(1) {
[0]=> object(SimpleXMLElement)#13 (1) {
["#attributes"]=> array(4) {
["decimal"]=> string(4) "9.60"
["percent"]=> string(5) "10.42"
["backers_stake"]=> string(5) "40.36"
["liability"]=> string(6) "347.00"
}
}
}
}
["offers"]=> object(SimpleXMLElement)#12 (1) {
["price"]=> array(1) {
[0]=> object(SimpleXMLElement)#15 (1) {
["#attributes"]=> array(4) {
["decimal"]=> string(4) "9.20"
["percent"]=> string(5) "10.87"
["backers_stake"]=> string(5) "85.35"
["liability"]=> string(5) "10.41"
}
}
}
}
}
Why does this work:
$horse[0]['name']
but this doesn't:
$horse[0]['bids'] // also tried $horse['bids'] and other ways
I can get the values like below but I was hoping to search the smaller object:
$xml->xpath("//odds/event[#id='$matchid']/market[#slug='to-win']/contract[#name='$pony']/bids"); // $pony == $horse[0]['name']

It's often easier to look at the XML itself, rather than a print_r of the SimpleXML object. In this case, you have something like this:
<horse id="18022352" name="The Salmon Man" slug="the-salmon-man">
<bids>
<price decimal="9.60" percent="10.42" backers_stake="40.36" liability="347.00" />
</bids>
<offers>
<price decimal="9.60" percent="10.42" backers_stake="40.36" liability="347.00" />
</offers>
</horse>
The bids item is an element, and as discussed in the SimpleXML Basic Usage guide, you access child elements with ->foo notation, whereas attributes use ['foo'] notation.
So if $horse is that <horse> element, you need:
$name = $horse['name'];
$bids = $horse->bids;
Note that this is equivalent to explicitly asking for the first child called bids; both forms will work regardless of whether there is actually more than one identically name element:
$bids = $horse->bids[0];
Now there are presumably one or more <price> elements in practice, so you might want to loop over, and then echo each decimal attribute. That would look like this:
foreach ( $horse->bids->price as $price ) {
echo $price['decimal'];
}
Again, this loop will work fine with only one <price>, it will just just loop once. If there is only ever one price, or you only care about the first one, you could just write:
echo $horse->bids->price['decimal'];
Which is equivalent to:
echo $horse->bids[0]->price[0]['decimal'];
Or of course either of these:
echo $horse->bids[0]->price['decimal'];
echo $horse->bids->price[0]['decimal'];
The number of different ways of getting to the same place is one reason I don't recommend relying too much on print_r output. Another is that it sometimes can't display everything that's in the XML, which doesn't mean that data isn't available if you ask for it.

Related

(PHP) var_dumping an object in structured format.

I need to analyze an object in my code, but when I do a var_dump (or print_r) it just prints the object out with no structure, for example:
[0]=> object(simple_html_dom_node)#2185 (9) { ["nodetype"]=> int(1) ["tag"]=> string(3) "div" ["attr"]=> array(1) { ["class"]=> string(36) "element element--collection internal" } ["children"]=> array(2) { [0]=> object(simple_html_dom_node)#2187 (
I need to see it in a more structured format so I can see what is going on, i.e.:
object(simple_html_dom_node)#2185 (9) {
["nodetype"]=> int(1)
["tag"]=> string(3) "div"
["attr"]=> array(1)
{
["class"]=> string(36) "element element--collection internal"
}
["children"]=> array(2) {
[0]=> object(simple_html_dom_node)#2187 (9)
Does anyone know how to do this?
The format you want is actually how var_dump() prints the object. The problem is that you're doing it in an HTML document, and the browser reformats it.
If you put it inside a <pre> tag, the browser will leave the formatting alone. So:
echo "<pre>"; var_dump($object); echo "</pre>";
Try using var_export(), this function will give you a more readable structure of the object or data.

How do I get the values out of the #attribute section?

I cannot figure out to get these values from this array. I need to know the code and name so my application knows which one to go for but I can't get the values out of there. Can someone please help me out? It's the values in the #attributes.
I'm using PHP by the way.
Thanks
array(2) {
[0]=>
object(SimpleXMLElement)#22 (2) {
["#attributes"]=>
array(2) {
["code"]=>
string(3) "HCD"
["name"]=>
string(31) "HIGH COST DELIVERY REGION SRCHG"
}
[0]=>
string(5) "71.25"
}
[1]=>
object(SimpleXMLElement)#24 (2) {
["#attributes"]=>
array(2) {
["code"]=>
string(3) "HCD"
["name"]=>
string(31) "HIGH COST DELIVERY REGION SRCHG"
}
[0]=>
string(5) "71.25"
}
}
Using SimpleXML, you're able to access the attributes on an XML by using the elements as if it was an array ($xml->elementName['attributeName'], or using the ->attributes() method as previously given).
For example, given the following code:
$xml = new SimpleXMLElement('<root><item foo="bar"></item></root>');
If I wanted to access the foo attribute on the item element, I would access it like this:
echo $xml->item['foo'];
However, there's a catch: the value that is returned is actually an instance of SimpleXMLElement. To be able to store or use it, you will need to convert it to a primitive type:
echo (string)$xml->item['foo']; // now a string
echo (int)$xml->item['foo']; // now an integer
echo (bool)$xml->item['foo']; // now a boolean
I figured it out on my own.
$xmlResponse->AccessorialCharges->OtherAccessorialCharges[$i]['code'];

How can I preserve the "tag order" when converting an XML fragment to an array in PHP?

I've read a large number of articles and Stack Overflow questions about converting an XML document or fragment into an array in PHP, but none that I've read so far have addressed my specific problem. Here's my dilemma, preceded by an example XML fragment:
<category>
<template>
<random>
<li>And a good</li>
<li>Pleasant</li>
<li>Good</li>
<li>Fantabulous</li>
</random>
<set name="TOD"><srai>time of day</srai></set> to you, <get name="name" />.
<random>
<li>How are you?</li>
<li>To what do I owe the pleasure of this visit?</li>
<li>May your Athlete's Foot be under control, and may the flying monkeys never come to take your dog!</li>
<li>I trust your <get name="TOD" /> is going well?</li>
<li>May your <get name="TOD" /> be as pleasant as possible.</li>
</random>
</template>
</category>
This is a REAL WORLD example of some of the XML my script will be dealing with. The sequence order of the XML tags needs to be preserved, as the parsed results need to be concatenated correctly in order to provide the proper result. So far, all of the methods for converting XML fragments into arrays have created arrays that no longer contain the correct order. As an example, here's a var dump of the above XML, once it's been converted into an array:
Template array Var Dump:
array(4) {
["random"]=>
array(2) {
[0]=>
array(1) {
["li"]=>
array(4) {
[0]=>
array(1) {
["text"]=>
string(10) "And a good"
}
[1]=>
array(1) {
["text"]=>
string(8) "Pleasant"
}
[2]=>
array(1) {
["text"]=>
string(4) "Good"
}
[3]=>
array(1) {
["text"]=>
string(11) "Fantabulous"
}
}
}
[1]=>
array(1) {
["li"]=>
array(5) {
[0]=>
array(1) {
["text"]=>
string(12) "How are you?"
}
[1]=>
array(1) {
["text"]=>
string(44) "To what do I owe the pleasure of this visit?"
}
[2]=>
array(1) {
["text"]=>
string(97) "May your Athlete's Foot be under control, and may the flying monkeys never come to take your dog!"
}
[3]=>
array(2) {
["text"]=>
array(2) {
[0]=>
string(12) "I trust your"
[1]=>
string(14) "is going well?"
}
["get"]=>
array(1) {
["#attributes"]=>
array(1) {
["name"]=>
string(3) "TOD"
}
}
}
[4]=>
array(2) {
["text"]=>
array(2) {
[0]=>
string(8) "May your"
[1]=>
string(27) "be as pleasant as possible."
}
["get"]=>
array(1) {
["#attributes"]=>
array(1) {
["name"]=>
string(3) "TOD"
}
}
}
}
}
}
["set"]=>
array(2) {
["#attributes"]=>
array(1) {
["name"]=>
string(3) "TOD"
}
["srai"]=>
array(1) {
["text"]=>
string(11) "time of day"
}
}
["text"]=>
array(2) {
[0]=>
string(7) "to you,"
[1]=>
string(1) "."
}
["get"]=>
array(1) {
["#attributes"]=>
array(1) {
["name"]=>
string(4) "name"
}
}
}
As can be seen, the array, when created, "lost" the sequence order of the XML fragment, and you can't iterate through the array in a linear manner to arrive at the proper response. This is the crux of my problem, and what I'm looking to "fix".
The method I used in this example was json_decode(json_encode($xml), true), but I've used other, more complex script functions, with pretty much the same results. So, just as I asked in the title of this post, how can I preserve the "tag order" when converting an XML fragment to an array in PHP?
Pretty sure there are no flags available with say simpleXML or json_decode. I don't think XML is intended to preserve that. The structure is not intended to convey that, can see how it leads to bad design. Specific to XML, you can get around this by use of sequence in an XSD. But your data looks more like a DOM.
As a work around have you looked at parsing it with as a DOM Document and stepping through it? Not too much code to parse it yourself leveraging that.

A list of arrays contained in a master array PHP

I hope I can make this question clear enough.
I'm looking to put a list of arrays inside one master array, dynamically, so that it looks like this:
masterarray {
array1
{ [0]=>VAL1 [1]=>VAL2 }
array2
{ [0]=>VAL1 [1]=>VAL2 }
array3
{ [0]=>VAL1 [1]=>VAL2 }
}
I've tried, but I could only get it to look like this:
array(1) { [0]=> array(2) { [0]=> string(1) "1" [1]=> string(13) "CODE" } }
array(2) { [0]=> array(2) { [0]=> string(1) "1" [1]=> string(13) "CODE" } [1]=> array(2) { [0]=> string(1) "1" [1]=> string(13) "CODE" } }
array(3) { [0]=> array(2) { [0]=> string(1) "1" [1]=> string(13) "CODE" } [1]=> array(2) { [0]=> string(1) "1" [1]=> string(13) "CODE" } [2]=> array(2) { [0]=> string(1) "1" [1]=> string(13) "CODE" } }
And that's definitely not what I'm aiming for. Nothing seems contained. I need the format specified above.
I'm using the explode function on a string pulled from a file to make this table of arrays (I think you call it that)
Here is the code I'm using that's not working.
$variabledebugging = file("FILE.TXT");//LOOK IN THIS FILE FOR THE NUMBER AND SET IT TO A VAR.
$i=0;
foreach($variabledebugging as $placeholder){
$variabledebuggingtbl[] = explode("\t",$variabledebugging[$i]);
var_dump($variabledebuggingtbl);
$i++;
}
I've tried a couple of different variations, but that's the one I'm using now.
To be clear, that file being pulled (each line as a value in an array) has 2 things written to each line, separated by a tab character, so that's the system I'm going on.
Thank you! I'm sure this is a simple task, I just can't think it through.
Oh and while I'm at is there a way to make debugging more readable?
You ARE getting the right result. The reason it seems wrong is that you are running var_dump inside the loop. And why don't you use the $placeholder variable?
$variabledebugging = file("FILE.TXT");
foreach($variabledebugging as $placeholder){
$variabledebuggingtbl[] = explode("\t", $placeholder);
}
var_dump($variabledebuggingtbl);
I'm not sure what you mean by "making debugging more readable", but if you want some linebreaks and indentation you should just look in the generated HTML code. var_dump do add spacing to make it readable but it is ignored by the web browser. If you don't want to read the HTML source, just add your var_dump to a <pre> element.

PHP - Simple XML attributes problem

I use PHP and Simple XML.
I use a loop that does not work like expected:
foreach($item->Image->attributes()->source as $key => $value)
{
echo $value;
}
In the foreach I try to tell that I want to get the "source" of the image which is listed in the attributes.
$item above is created with a loop around my code above foreach($xml_content->Section->Item as $item {}, (if you need to know where it came from)
My object looks like this:
object(SimpleXMLElement)#36 (4) {
["Text"]=>
string(15) "Vinbergs socken"
["Description"]=>
string(73) "Vinbergs socken ingick i Faurås härad och ligger i Falkenbergs kommun.
"
["Url"]=>
string(44) "http://sv.wikipedia.org/wiki/Vinbergs_socken"
["Image"]=>
object(SimpleXMLElement)#38 (1) {
["#attributes"]=>
array(3) {
["source"]=>
string(113) "http://upload.wikimedia.org/wikipedia/commons/thumb/2/25/Faur%C3%A5s_Vinberg.svg/50px-Faur%C3%A5s_Vinberg.svg.png"
["width"]=>
string(2) "50"
["height"]=>
string(2) "41"
}
}
}
What is wrong with my loop in the beginning of my post?
Your are trying to iterate a string, not an array
$item->Image->attributes()->source
To iterate all the attributes of the Image element, use
foreach ($item->Image->attributes() as $attributeName => $attributeValue) {
If you just want to output the value of the source attribute, do not iterate but use the shorthand
echo $item->Image['source']
See this demo and the SimpleXml Basic Usage Examples in the PHP Manual

Categories