1

I have this lovely chunk of text found inside an XML element and want to convert it into a simple array, the XML is from wikia.com.

The array would be something like this:

card name => [Martial] Ares, character name => Ares, release_date => May 1 2013 and so on..

I've tried all sorts of imploding and exploding variations but no luck.. This one has got me stumped..

|card name=[Martial] Ares
|character name=Ares
|release_date=May 1 2013
|image 1=MartialAres5.jpg
|rarity 1=Super Special Rare
|pwr req 1=28
|sale price 1=94200
|max card lv 1=60
|max mastery lv 1=40
|quote 1=Ares prefers weapons that were used during the age of Greek myth: sword, axe, and spear.  But he can use any weapon expertly, and turn most ordinary objects into lethal weapons.
|base atk 1=2440
|base def 1=2650
|max atk 1=7015
|max def 1=7613
|mastery bonus atk 1=915
|mastery bonus def 1=993
|image 2=MartialAres6.jpg
|rarity 2=Ultimate Rare
|sale price 2=188400
|max mastery lv 2=200
|quote 2=Next time I see Hercules, We're going to have a steel conversation. It's about time for him to answer for massacring my Stymphalian Birds.
|max atk 2=9822
|max def 2=10660
|mastery bonus atk 2=1098
|mastery bonus def 2=1192
|alignment=Bruiser
|ability=Warhawk
|gender=Male
|usage=Average
|faction=Super Hero
|effect=Significantly harden DEF of your Bruisers.
|centretrait=None

Code I've tried:

if (file_exists('card.xml')) {
    $xml = simplexml_load_file('card.xml');


    $text = $xml->page->revision->text;
    $newtext = explode('|', $text);
    foreach($newtext as $newnewtext) {
        $newtext2 = explode('=', $newnewtext);
        print_r($newtext2);

    }


} else {
    exit('Failed to open card.xml.');
}
4
  • explode on pipe\line break, loop, explode on equals Commented Aug 2, 2015 at 22:33
  • This is a snippet of what that gives me Array ( [0] => {{Infobox card (2) ) Array ( [0] => card name [1] => [Martial] Ares ) Array ( [0] => character name [1] => Ares ) Commented Aug 2, 2015 at 22:35
  • 1
    edit the question with the code tried Commented Aug 2, 2015 at 22:37
  • 2
    how about: codepad.viper-7.com/3BkXD6 Commented Aug 2, 2015 at 22:42

6 Answers 6

5

as requested:

<?php
$file="|card name=[Martial] Ares
|character name=Ares
|release_date=May 1 2013
|image 1=MartialAres5.jpg
|rarity 1=Super Special Rare
|pwr req 1=28
|sale price 1=94200
|max card lv 1=60
|max mastery lv 1=40
|quote 1=Ares prefers weapons that were used during the age of Greek myth: sword, axe, and spear.  But he can use any weapon expertly, and turn most ordinary objects into lethal weapons.
|base atk 1=2440
|base def 1=2650
|max atk 1=7015
|max def 1=7613
|mastery bonus atk 1=915
|mastery bonus def 1=993
|image 2=MartialAres6.jpg
|rarity 2=Ultimate Rare
|sale price 2=188400
|max mastery lv 2=200
|quote 2=Next time I see Hercules, We're going to have a steel conversation. It's about time for him to answer for massacring my Stymphalian Birds.
|max atk 2=9822
|max def 2=10660
|mastery bonus atk 2=1098
|mastery bonus def 2=1192
|alignment=Bruiser
|ability=Warhawk
|gender=Male
|usage=Average
|faction=Super Hero
|effect=Significantly harden DEF of your Bruisers.
|centretrait=None";


$x=explode("\n",$file);
$out=array();
foreach($x as $each){
  $xx=explode('=',$each);
 $out[ltrim($xx[0],'|')]=$xx[1]; 
}
echo '<pre>';
print_r($out);

working demo: http://codepad.viper-7.com/3BkXD6

Sign up to request clarification or add additional context in comments.

Comments

1

The simplest and most efficient way to achieve that is using regular expressions. Given that $string holds the data, do the following:

preg_match_all('/^\|(?<key>[^=]+)=(?<value>.*)$/m', $string, $matches);
print_r(array_combine($matches['key'], $matches['value']));

For the data you provided as an example you'll get:

Array
(
  [card name] => [Martial] Ares
  [character name] => Ares
  [release_date] => May 1 2013
  [image 1] => MartialAres5.jpg
  [rarity 1] => Super Special Rare
  [pwr req 1] => 28
  [sale price 1] => 94200
  [max card lv 1] => 60
  [max mastery lv 1] => 40
  ...and so on
)

Comments

0

This should work for you:

First explode() your string by a new line. Then go through each element with array_map() and explode the substr() with an offset of 1 by an equal sign.

At the end just use array_column() to use the first column as value and the 0 column as key.

$arr = array_column(array_map(function($v){
    return explode("=", substr($v, 1));
}, explode(PHP_EOL, $str)), 1, 0);

print_r($arr);

Comments

0

First, I would split the string on the '|' charater.

$parts = explode("|", $str);

This will result in an array like the following:

    Array
    (
        [0] => 
        [1] => card name=[Martial] Ares

        [2] => character name=Ares

        [3] => release_date=May 1 2013

        [4] => image 1=MartialAres5.jpg

        [5] => rarity 1=Super Special Rare

        [6] => pwr req 1=28

        [7] => sale price 1=94200

        [8] => max card lv 1=60

        [9] => max mastery lv 1=40

        [10] => quote 1=Ares prefers weapons that were used during the age of Greek myth: sword, axe, and spear.  But he can use any weapon expertly, and turn most ordinary objects into lethal weapons.

        [11] => base atk 1=2440

        [12] => base def 1=2650

        [13] => max atk 1=7015

        [14] => max def 1=7613

        [15] => mastery bonus atk 1=915

        [16] => mastery bonus def 1=993

        [17] => image 2=MartialAres6.jpg

        [18] => rarity 2=Ultimate Rare

        [19] => sale price 2=188400

        [20] => max mastery lv 2=200

        [21] => quote 2=Next time I see Hercules, We're going to have a steel conversation. It's about time for him to answer for massacring my Stymphalian Birds.

        [22] => max atk 2=9822

        [23] => max def 2=10660

        [24] => mastery bonus atk 2=1098

        [25] => mastery bonus def 2=1192

        [26] => alignment=Bruiser

        [27] => ability=Warhawk

        [28] => gender=Male

        [29] => usage=Average

        [30] => faction=Super Hero

        [31] => effect=Significantly harden DEF of your Bruisers.

        [32] => centretrait=None
    )

Next, I would loop over the array and split each string on the "=" character and build an associative array from the pieces.

    //First remove the first empty element from the array.
    array_shift($parts);

    $finalArray = array();
    foreach($parts as $part)
    {
        $b = explode("=", $part);
        $finalArray[$b[0]] = $b[1];
    }

This should result in the structure you are seeking.

Array
(
    [card name] => [Martial] Ares

    [character name] => Ares

    [release_date] => May 1 2013

    [image 1] => MartialAres5.jpg

    [rarity 1] => Super Special Rare

    [pwr req 1] => 28

    [sale price 1] => 94200

    [max card lv 1] => 60

    [max mastery lv 1] => 40

    [quote 1] => Ares prefers weapons that were used during the age of Greek myth: sword, axe, and spear.  But he can use any weapon expertly, and turn most ordinary objects into lethal weapons.

    [base atk 1] => 2440

    [base def 1] => 2650

    [max atk 1] => 7015

    [max def 1] => 7613

    [mastery bonus atk 1] => 915

    [mastery bonus def 1] => 993

    [image 2] => MartialAres6.jpg

    [rarity 2] => Ultimate Rare

    [sale price 2] => 188400

    [max mastery lv 2] => 200

    [quote 2] => Next time I see Hercules, We're going to have a steel conversation. It's about time for him to answer for massacring my Stymphalian Birds.

    [max atk 2] => 9822

    [max def 2] => 10660

    [mastery bonus atk 2] => 1098

    [mastery bonus def 2] => 1192

    [alignment] => Bruiser

    [ability] => Warhawk

    [gender] => Male

    [usage] => Average

    [faction] => Super Hero

    [effect] => Significantly harden DEF of your Bruisers.

    [centretrait] => None
)

5 Comments

This actually resulted in plain text, which is kind of cool but not what I need
@CodeX -It results in a php array. I just ran print_r on it so that you'd see that it created the correct structure. If you run the code you'll find that the $finalArray variable IS AN ARRAY with the structure you asked for.
When I do it, it comes out as a list of values, im print_r($finalArray[$b[0]] = $b[1]);
@CodeX - the line containing '$finalArray[$b[0]] = $b[1];' is building the final array. To print the final array do: 'print_r($finalArray);' To access individual array items do: '$finalArray['alignment']' (for instance) which will output: 'Bruiser'.
I apologise for my stupidity, this works perfect also! Thanks
0

With the minimal error checking:

$text = explode('|', $text);
$result = array();
foreach ($text as $entry) {
    if ($entry) {
        $entry = explode('=', $entry);
        $result[$entry[0]] = $entry[1];
    }
}

Comments

0

@Dagon is correct. This is how an implementation might look:

<?php
$keyvalues = array();
$text = file_get_contents('path/to/your/file');
$rows = explode('|',$text);
foereach($rows as $row) {
    if (strpos($row,'=')) {
        $kv = array_map('trim',explode('=',$row));
        $keyvalues[ $kv[0] ] = $kv[1];
    }
}
?>

2 Comments

try array_filter( $rows = explode('|',$text) );
it's probably throwing up on blank lines. I've updated the code to not try to parse blank lines, by using if (strpos($row,'=')) { ... }

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.