which is better expression to make string into xml object[php]? - php

which is better expression to make string into xml object[php]?
$xml = new SimpleXMLElement($xml_string);
vs
$xml = simplexml_load_string($xml_string);
same?

They're basically identical. SimpleXMLElement::__construct accepts data strings or file paths, if you set the appropriate options. simplexml_load_file and simplexml_load_string are basically convenience function wrappers that amount to the same thing as new SimpleXMLElement() with the correct options set.

They're essentially the same. Which one you use is based on personal taste. I'd go for the first. The simplexml_load_string function will create an object too, which makes it essentially an alias for the constructor.

The simplexml_load_string lets you specify the class of which you want to get the object of. If you call the simplexml_load_string without specifying the class as second parameter, then it automatically gives you the object of SimpleXMLElement.
So, in the way you are running it, they both will give you same results.

Related

Single array element becomes object with Zend_Soap_Client

I'm using Zend_Soap_Client and encountering this issue:
<parent>
<child><name>abc</name></child>
<child><name>def</name></child>
</parent>
If there's more than one child element then Zend return array and I can access like
$result->parent->child[0]->name
but if there's only one child node it returns object like:
$result->parent->child->name
Can you please let me know what's wrong with my approach or how can I overcome it?
My sample code:
$client = new Zend_Soap_Client('url', array('wsdl'=>'url));
$result = $client->getResult();
I'm using zend 1.9. The same issue happens with PHP's native SoapClient
Thanks!
Personally I do not see the need to use Zend_Soap_Client instead of SoapClient because the Zend version does not add anything beneficial, but on the other hand the solution applies to both:
There is an options array parameter in the original SoapClient that accepts plenty of things, and especially this below (ref):
The features option is a bitmask of SOAP_SINGLE_ELEMENT_ARRAYS,...
With this option, all array structures in the soap response are not reduced to one single element if they contain only one, but left as is. You are always accessing an array then, which is easier than switching depending on the content.
Example:
$s = new SoapClient($wsdl, array('features' => SOAP_SINGLE_ELEMENT_ARRAYS));

From SimpleXMLElement to SimpleXMLIterator

I have a nice function that converts a (simple, duh) xml to an array, and to do so it uses the SimpleXmlIterator class.
It works quite well, but I'd like to make it accept not only xml source strings or SimpleXmlIterator objects, but SimpleXmlElements too since I use them way more often that iterators (that I use just in that function, actually).
What I did so far was
$iter = new SimpleXmlIterator($xml->asXML());
but to me it's like passing through Tokyo to get from Paris to London. After all, SimpleXmlIterator extends SimpleXmlElement, so is there a better way to convert a SimpleXmlElement object to a SimpleXmlIterator?
You can use SimpleXMLIterator at the beginning by setting the second parameter in http://php.net/manual/de/function.simplexml-load-file.php
$yourSimpleXMLIteratorObject = simplexml_load_file("your_file.xml","SimpleXMLIterator");
all Objects resulting, are now SimpleXMLIterator-Objects
Why not parse all your XML into SimpleXMLIterator objects to begin with if you plan to use them as such?
As far as I know there is not an easy way to convert/cast from SimpleXMLElement to SimpleXMLIterator. These classes simply wrap a libxml resource so you would think there would be a way to obtain a resource handle and pass it into SimpleXML* constructors, but if there is it's news to me.

ZEND: Appending XML Data to SQLDataBase(XML)

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.

Force SimpleXML node to always be an array, even if just 1 element in it

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();

simplexml get node value without typecasting

Is there any way to get a node value from a simplexml object without casting it?
$amount = (int)$item->amount;
This is not very beautiful in my opinion, I'm searching for a cleaner way but did not find anything so far!
//wouldn't this be nice?
$amount = $item->amount->getValue();
Thanks in advance.
No. SimpleXml only exposes a very limited API to work with nodes. It's implicit API is considered a feature. If you need more control over the nodes, use DOM:
$sxe = simplexml_load_string(
'<root><item><amount>10</amount></item></root>'
);
$node = dom_import_simplexml($sxe->item->amount);
var_dump($node->nodeValue); // string(2) "10"
The dom_import_simplexml function will convert the node from a SimpleXmlElement to a DOMElement, so you are still casting behind the scenes somehow. You no longer need to typecast explicitly though, when fetching the content from the DOMElement.
On a sidenote: personally, I find DOM superior to SimpleXml and I'd suggest not to use SimpleXml but DOM right away. If you want to familiarize yourself with it, have a look at some of my previous answers about using DOM.
Getting the value of a node without having to typecast it? Sure thing! :3
class SimplerXMLElement extends SimpleXMLElement
{
public function getValue()
{
return (string) $this;
}
}
Now you just have to use simplexml_load_string()'s second parameter to get even simpler XML elements!
More seriously though, a node is a node. If you need to use the value of a node as a string, integer and what not, it will involve typecasting at one point or another, whether you do it personally or not.
But it is the safest :). You could create a function to recursively convert the object in an array. Way back when I first starte working with XML in PHP, I remember reaching the conclusion that type casting is just the best method :)
What about xpath way?
$amount = $item->amount->xpath('text()');

Categories