1

I want to convert this string:

<5> 20825.24 </ 5> <7> 0.0 </ 7> <8> 0.0 </ 8>

to an array with key value

I would really appreciate the help

I tried different xmlParse strategies but it is not exactly an xml.

$xml = new \SimpleXMLElement("<5>20825.24</5><7>0.0</ 7><8>0.0</8>");

Response: String could not be parsed as XML

I expect an array like this:

[5=>20825.24,7=>0.0,8=>0.0]
1
  • 3
    XML tag names cannot start with a number, so this means unless you process the data - it isn't valid XML (also doesn't have a root node - but that's easily fixed) Commented May 26, 2019 at 16:30

4 Answers 4

3

As long as your output has numbers at the start of the XML tag name, it won't be valid XML. You may have to resort to using a regex to do the job.

This uses <(\d*)>(.*?)</~ which looks for a < followed by digits, then the > and captures everything up till the next </. It then combines the values from capture group 1 (the tag name) and 2 (the value)...

$data = "<5>20825.24</5><7>0.0</ 7><8>0.0</8>";

preg_match_all("~<(\d*)>(.*?)</~", $data, $matches);
$output = array_combine($matches[1], $matches[2]);
print_r($output);

gives...

Array
(
    [5] => 20825.24
    [7] => 0.0
    [8] => 0.0
)
Sign up to request clarification or add additional context in comments.

1 Comment

That's concise, and much cleaner than my ans.
2
<?php

$subject = '<5> 20825.24 <7> 0.0 <8> 0.0';
$pattern = '/\<(\d)\>\s+(\d+\.\d+)/u';
$result = preg_match_all($pattern,$subject,$output);

$numbers = $output[1];
$output = $output[2];
$outTotal = [];

foreach ($numbers as $key => $number) {
    $outTotal[$number] = $output[$key];
}
var_dump($outTotal);

gives:

array(3) {
  [5]=>
  string(8) "20825.24"
  [7]=>
  string(3) "0.0"
  [8]=>
  string(3) "0.0"
}

Comments

1

Here, we can also use a regular expression and collect our desired numbers, then push it to a new array:

(?:<)(\d?)(?:>)(?:.+?)([0-9.]+)?

This expression might also work with nested elements.

Test

$re = '/(?:<)(\d?)(?:>)(?:.+?)([0-9.]+)?/m';
$str = '<5> 20825.24 </ 5> <7> 0.0 </ 7> <8> 0.0 </ 8>';
preg_match_all($re, $str, $matches, PREG_SET_ORDER, 0);

$arr = array();
foreach ($matches as $key => $value) {
    $arr[$value[1]] = $value[2];
}

var_dump($arr);

Output

array(3) {
  [5]=>
  string(8) "20825.24"
  [7]=>
  string(3) "0.0"
  [8]=>
  string(3) "0.0"
}

DEMO

RegEx Circuit

jex.im visualizes regular expressions:

enter image description here

Comments

0

If you want to match the digits in the opening tag with the digits in the closing tag, you could use a regex make use of a backreference to the first capturing group:

<(\d+)>\h*\d+(?:\.\d+)?\h*</\h*\1>

Explanation

  • < Match > char
  • (\d+)> Capture in group 1 matching 1+ digits and match >
  • \h* Match 0+ horizontal whitespace chars
  • \d+(?:\.\d+)? Match 1+ digits followed by an optional part to match a dot and 1+ digits
  • \h* Match 0+ horizontal whitespace chars
  • < Match <
  • /\h* Match \ followed by 0+ horizontal whitespace chars
  • \1> Match backreference to group 1 using \1 and match >

Regex demo | Php demo

For example:

$re = '~<(\d+)>\h*(\d+(?:\.\d+)?)\h*</\h*\1>~m';
$str = '<5> 20825.24 </ 5> <7> 0.0 </ 7> <8> 0.0 </ 8>';
preg_match_all($re, $str, $matches);
print_r(array_combine($matches[1], $matches[2]));

Result

Array
(
    [5] => 20825.24
    [7] => 0.0
    [8] => 0.0
)

Note that now the array keys are 5, 7 and 8. Keep in mind that if you might use different data, that arrays can not have duplicate keys.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.