How do I parse "id" from the following event
<event id="100990">
<title>myTitle</title>
</event>
I parse the title like this:
$xml->event[0]->title
Use the attributes method of SimpleXML
$id_attribute = (string)$xml->event[0]->attributes()->id;
You access attributes just like you would access elements of an associative array:
$xml_node['id'] // The value of the attribute `id` of the node `$xml_node`
The returned value is an object (with a __toString method), so you may want to typecast the returned value.
This is exactly what you need: http://www.php.net/manual/en/simplexmlelement.attributes.php
Related
I have an xpath query on a simplexml element like so:
$theSimpleXmlObject->xpath('//path/to/*/node');
it returns an array of results which is great but it is an array of simplexml objects and i just want a flat array.
Is this possible?
Ideally i would have a simple array returned with the matching node values instead of having to iterate over the results to prepare the array.
Try in this way to get Array
$xml = json_decode(json_encode((array) simplexml_load_string($string)), 1);
When you cast xml to array it will cast only "first level", so we can made it by convert it in JavaScript Object Notation and decode it again to array. Serialization will not help, becouse it keep data-structure.
I've seen this problem a few times, and would like a definitive answer.
Given this structure in xml:
<ByteListSet>
<Byte Order="0">14</Byte>
</ByteListSet>
I am not able to access the attribute 'order'. var_dump (unsurprisingly) does not show any attributes for ByteListSet. Indeed, foreach iteration does not produce a #attributes item.
However, the following structure:
<ByteListSet>
<Byte Order="0"><Value>3729</Value></Byte>
</ByteListSet>
Results properly in ByteListSet having a child Byte that is a SimpleXmlObject which has #attributes.
I would assume that SimpleXML is indeed picking up the #attributes from the first case, but where is it keeping them? The trouble is that in the former structure, ByteListSet produces this on var_dump of ->children():
object(SimpleXMLElement)[25]
public 'Byte' => string '14' (length=2)
if I get_object_vars() on it and var_dump each, I simply get:
string '14' (length=2)
Indicating that Byte is not being returned to me as an xml object, but just as a string; as a property of the ByteList object above it.
Order="0" is there somewhere, but I don't have access to it. How do I get to it? NOTE: ->attributes() returns, as you would expect, a blank array.
(We do not control this schema, so it can't be restructured.)
You wrote:
Given this structure in xml:
<ByteListSet>
<Byte Order="0">14</Byte>
</ByteListSet>
I am not able to access the attribute 'order'.
Sure, because the attribute order does not exist. XML is case-sensitive, the attribute is named Order with uppercase O at the beginning.
Using the right attribute name allows you to access the value as outline in Example #5 in the basic examples of the SimpleXML extension you can find in the manual:
$ByteListSet = simplexml_load_string(<<<XML
<ByteListSet>
<Byte Order="0">14</Byte>
</ByteListSet>
XML
);
echo $ByteListSet->Byte['Order']; # 0
Please keep in mind that what you see in var_dump or print_r is not always what you get. This is espeically true for Simplexml (compare: How to get values of xml elements?; SimpleXML and print_r() - why is this empty?), however, also for other objects in PHP that make use of ArrayAccess, __toString() or IteratorIterator / IteratorAggregate.
Please let me know if that answers your question. You were not very specific which existing solutions you have not understood so far, so I answered your question, but I'm not 100% if I hit the nail.
My Issue: Unable to append XML data to prexisting XML data in a MYSQL database.
I have an array - $buyer. Inside this array is a $key and $value similar to (shippingTotal => 55). What I want to do is use something similar to
$param = array(
'shippingTotal' => $shippingTotal
);
$where['quote_data = ?'] = $quoteNumber
$n = $db->update('quote_xml', simplexml_load_string($param), $where);
My hiccup is that the current data inside quote_data is an XML element containing LOTS of information. Is there any way to just "stick" shippingTotal into said existing XML? When I use the above code I just end up with quote_data becoming empty.
I also created a variable called $shippingTotal so that I wouldn't have to use $buyer['shippingTotal']. Still not functional.
Thank you for your time and assistance with this issue.
Aaron
I see a few issues with this:
First, simplexml_load_string doesn't accept array parameters, only XML strings. Since the $params is not a valid argument, it is returning boolean false. Even when successful, it returns a SimpleXMLElement. To convert that to an XML string, you would have to call the asXML() method on the returned object before passing it to Zend_Db_Table::update().
Second, most likely XML cannot just be "appended" to other XML. I don't know exactly what your table holds, but the XML needs to be programmatically added to the existing XML. You can't append XML because the data you want to add needs to be added to the proper nodes.
What you will have to do is first read the value of that column, parse it using SimpleXML, add your new data to the appropriate node in the document using one of the SimpleXML functions and then perform the update.
Hope that helps.
Is it possible to sort a simplexml object but keep the object as a simplexml object instead of casting to an array.
There doesnt appear to be a way to do this - and if casted to an array it seems very messy to transform the array(s) back to a simplexml object.
So -
Is it possible to sort a simplexml object by an attribute etc.
For example (sort by the position attribute node):
<test_nodes>
<node position="1"></node>
<node position="2"></node>
<node position="3"></node>
</test_nodes>
If not then what is the most painless and efficient way to cast an array to a simple xml object
Let's say I want a Place to have a list of phone numbers.
Some places will have 1 phone number, and some will have more than one. Others won't have one at all.
The problem is that this:
$xml->addChild('phone_number','555.555.5555');
creates a non-iterable phone_number text node:
$response->xml->phone_number;
But this:
$xml->addChild('phone_number','555.555.5555');
$xml->addChild('phone_number','555.555.5556');
creates an iterable array of phone_number:
$response->xml->phone_number[0];
$response->xml->phone_number[1];
This puts an unnecessary burden on the client. They have to detect if the result is iterable or not, and modify their code accordingly.
It would be MUCH better if I could always send back an interable array, even if it had 0 or 1 items in it... but I haven't been able to find any documentation on how to do this. In Perl I believe it's called "forcearray", but I haven't found an equivalent for PHP, which is waht i need.
Just don't use this fancy, magic interface ($obj->xml->phone_number[x]) and use SimpleXMLElement::children() method which always returns iterable object.
you should consider this
<phone_numbers>
<phone_number>555.555.5555</phone_number>
</phone_numbers>
this is more flexible
beside the children() method, you can also consider xpath
which always will yields an array to be return
example
$xml = <<<XML
<person>
<phone_numbers>
<phone_number>555.555.5555</phone_number>
</phone_numbers>
</person>
XML;
$obj = simplexml_load_string($xml);
$tels = $obj->xpath("//phone_numbers/*");
/* even more simple */
$tels = $obj->phone_numbers->children();