Reputation: 4613
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?
Upvotes: 7
Views: 3436
Reputation: 486
It's an old question, but I found something that works neat - parse it into a DOMNode object.
// $customer contains the SimpleXMLElement
$customerDom = dom_import_simplexml($customer);
var_dump($customerDom->getAttribute('numeric'));
Will show:
string 'numeric'
Upvotes: 0
Reputation: 443
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.
Upvotes: 6
Reputation: 152
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.
Upvotes: 7
Reputation: 2923
Here's some code to iterate through attributes, and construct JSON. If supports, one or many customers.
If you're XML looks like this (or just one customer)
<xml>
<customer editable="true" maxChars="9" valueType="numeric">69236</customer>
<customer editable="true" maxChars="9" valueType="numeric">12345</customer>
<customer editable="true" maxChars="9" valueType="numeric">67890</customer>
</xml>
Iterate through it like this.
try {
$xml = simplexml_load_file( "customer.xml" );
// Find the customer
$result = $xml->xpath('/xml/customer');
$bFirstElement = true;
echo "var customers = {\r\n";
while(list( , $node) = each($result)) {
if( $bFirstElement ) {
echo "'". $node."':{\r\n";
$bFirstElement = false;
} else {
echo ",\r\n'". $node."':{\r\n";
}
$bFirstAtt = true;
foreach($node->attributes() as $a => $b) {
if( $bFirstAtt ) {
echo "\t".$a.":'".$b."'";
$bFirstAtt = false;
} else {
echo ",\r\n\t".$a.":'".$b."'";
}
}
echo "}";
}
echo "\r\n};\r\n";
} catch( Exception $e ) {
echo "Exception on line ".$e->getLine()." of file ".$e->getFile()." : ".$e->getMessage()."<br/>";
}
To produce a JSON structure like this
var customers = {
'69236':{
editable:'true',
maxChars:'9',
valueType:'numeric'},
'12345':{
editable:'true',
maxChars:'9',
valueType:'numeric'},
'67890':{
editable:'true',
maxChars:'9',
valueType:'numeric'}
};
Finally, in your script, access the attribute like this
WScript.Echo( customers["12345"].editable );
Good luck
Upvotes: -1