Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Disappearing attributes in PHP SimpleXML Object?

I need to return a SimpleXML object converted as a JSON object to work with it in JavaScript. The problem is that there are no attributes on any object with a value.

As an example:

<customer editable="true" maxChars="9" valueType="numeric">69236</customer>

becomes in the SimpleXML object:

"customer":"69236"

Where is the @attributes object?

like image 246
headacheCoder Avatar asked Dec 19 '11 14:12

headacheCoder


People also ask

What is the use of the simplexmlelement attribute in PHP?

The SimpleXMLElement::attributes() function is an inbuilt function in PHP which is used to retrieve the attributes and its value from an XML tag in a SimpleXML object.

How to retrieve the value of an XML tag in SimpleXML?

The SimpleXMLElement::attributes () function is an inbuilt function in PHP which is used to retrieve the attributes and its value from an XML tag in a SimpleXML object. SimpleXMLElement SimpleXMLElement::attributes ( $namespace, $is_prefix ) Parameter: This function accepts two parameters as mentioned above and described below:

Can SimpleXML handle database type data?

So lets say you have database type data in an XML string called $xmlstring with the key or item ID as an XML Attribute and all content data as regular XML Elements, as above. SimpleXML processes the Attributes as an array, so we can play along and push the Attributes into an array.

What is return in simplexmlelement?

Returns a SimpleXMLElement object that can be iterated over to loop through the attributes on the tag. Returns null if called on a SimpleXMLElement object that already represents an attribute and not a tag.


2 Answers

This has driven me crazy on several occasions. When SimpleXML encounters a node that only has a text value, it drops all the attributes. My workaround has been to modify the XML prior to parsing with SimpleXML. With a bit of regular expressions, you can create a child node that contains the actual text value. For example, in your situation you can change the XML to:

<customer editable="true" maxChars="9" valueType="numeric"><value>69236<value></customer>

Some example code assuming that your XML string was in $str:

$str = preg_replace('/<customer ([^>]*)>([^<>]*)<\/customer>/i', '<customer $1><value>$2</value></customer>', $str);
$xml = @simplexml_load_string($str);

That would preserve the attributes and nest the text value in a child node.

like image 161
ryanmcdonnell Avatar answered Sep 20 '22 02:09

ryanmcdonnell


I realize this is an old post, but in case it proves useful. The below extends @ryanmcdonnell's solution to work on any tags instead of a hard-coded tag. Hopefully it helps someone.

$str = preg_replace('/<([^ ]+) ([^>]*)>([^<>]*)<\/\\1>/i', '<$1 $2><value>$3</value></$1>', $result);

The main different is that it replaces /<customer with /<([^ ]+), and then </customer> with </\\1>

which tells it to match that part of the search against the first element in the pattern.

Then it just adjusts the placeholders ($1,$2,$3) to account for the fact that there are three sub-matches now instead of two.

like image 29
Lindsay Ryan Avatar answered Sep 19 '22 02:09

Lindsay Ryan