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.
Related
I have to filter portions of a JSON, there are different nodes/sub-nodes and I really need only a portion, for example this is what it may look like:
"node1":{
"686":{
"value1":"686",
"value2":"M",
"value3":0
}
"687":{
"value1":"687",
"value2":"L",
"value3":1
}
"688":{
"value1":"688",
"value2":"M",
"value3":0
}
For example I need to extract the node1 nodes, specifically ["686","687","688"] what I have tried so far:
$node1values = array_keys((array)$myjson->node1)
The response is weird: * items consider that I never use PHP regularly, no idea how to get this sorted without having to write a procedure to iterate every possible node.
Use array_column() to get a particular property from each array element.
$node1values = array_column((array)$myjson->node1, 'value1');
DEMO
I have an application where the user writes XPath queries to use as source data from a given document. Sometimes they need just the contents of an element, sometimes they need the whole element itself. To my understanding they should be able to specify either text() or node() at the end of their query to choose which behavior.
But it seems like the way I get a string out of the SimpleXMLElement determines the behavior, regardless of the query.
When I cast the query to (string), it ALWAYS only returns inner XML.
(string) $xml->xpath('//document/head/Keywords')[0] ===
(string) $xml->xpath('//document/head/Keywords/node()')[0] ===
(string) $xml->xpath('//document/head/Keywords/text()')[0] ===
'17';
If I use ->saveXML(), it ALWAYS returns the entire tag.
$xml->xpath('//document/head/Keywords')[0]->asXML() ===
$xml->xpath('//document/head/Keywords/node()')[0]->asXML() ===
$xml->xpath('//document/head/Keywords/text()')[0]->asXML() ===
'<Keywords topic="611x27keqj">17</Keywords>';
Is there a single way that I can get a string, which allows my users to specify inner vs outer XML as a part of their XPath query?
The SimpleXML xpath() method always returns SimpleXMLElement objects representing either an element or an attribute, never text. The methods you show in the question are the correct way to use that object to get text content or full XML.
If you want richer (but less simple) XPath functionality, you will have to use the DOM, and specifically the DOMXPath class. Note that you can freely mix SimpleXML and DOM using simplexml_import_dom and dom_import_simplexml; the internal representation is the same, so you can switch between the two "wrappers" with minimal cost.
I am a bit of a newbie to PHP and I'm not sure what I'm missing here. I have an multidimensional array that I've created from an XML file using XPath. I'm able to move through the array and retrieve most all values but I am getting stuck on one section.
Example of XML structure:
MasterNode
SubNodeItem1
SubNodeItem2
SubNodeItem3
SubNodeItemList
SubListItem
SubItemProperty1
SubItemProperty2
SubItemProperty3
SubItemList
SubItemProperty1
SubItemProperty2
SubItemProperty3
SubNodeItem4
SubNodeItem5
I am able to retrieve the value of any of the SubNode values by using the following syntax:
$val=$XML[$i]->SubNodeItem1;
however, I can not for the life of me figure out how to retrieve the values of SubListItemProperty.
I figured this would be the logical syntax:
$SubItemPropVal=$XML[$i]->SubNodeItemList->SubListItem[$i]->SubItemProperty1;
I have searched other forums and topics related to PHP multi arrays and have not been able to find the proper way to do this.
I am getting a "Trying to get property of non-object" error when I run the code. I'm pretty sure that's the indication that I'm not pointing the node correctly.
My recommendation would be to keep the XML file, which apparently works fine already, and use it.
Transferring its elements into an array does not make much sense to me.
EDIT: The OP does not actually use an array, but a SimpleXML object.
XPath is extremely flexible and powerful in selecting the needed bits from an XML document:
$doc = new DOMDocument();
$doc->loadXML($your_xml);
$xp = new DOMXPath($doc);
// for example
$result = $xp->query("//SubListItem[2]/SubItemProperty1");
if ($result->length)
{
echo $result->item(0)->textContent;
}
SimpleXML would also work:
$xml = simplexml_load_string($result);
// either this ($node will be an array of matches, or FALSE)
$node = $xml->xpath("//SubNodeItemList/SubListItem[1]/SubItemProperty1");
// or this (unless you add a number, [0] will be assumed)
$node = $xml->SubNodeItemList->SubListItem->SubItemProperty1;
Important: Array notation counts from 0, while XPath always counts from 1.
Note that the second option (array notation) will throw run-time errors when the structure of the document is not what your code expects.
With XPath there would simply be no return value, which is easier to handle (no try/catch block necessary, an if ($node) { ... } suffices).
Also note that with SimpleXML, the document element (<MasterNode>) becomes the document. So you would not use $xml->MasterNode->SubNodeItemList, but $xml->SubNodeItemList.
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.
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.