0

I'm in the need of writing a function to get data from an XML file.

It's the first time I'm trying to do something like this. I thought to treat it like I would treat a mysql database (Yeah, I'm a newbie).

The XML is structured like the following:

$xmlstr = <<<XML
<?xml version='1.0' standalone='yes'?>
<PlayerCount value="2">
    <Position value="Left">
        <Action value="Hit">
            <Range BBIdx="2" model="Math">0.653</Range>
            <Range BBIdx="3" model="Math">0.341</Range>
            <Range BBIdx="4" model="Math">0.216</Range>
        </Action>
        <Action value="Punch">
            <Range BBIdx="0" model="Math">1.000</Range>
            <Range BBIdx="1" model="Math">1.000</Range>
            <Range BBIdx="2" model="Math">0.498</Range>
            <Range BBIdx="3" model="Math">0.256</Range>
            <Range BBIdx="4" model="Math">0.168</Range>
        </Action>
        <Action value="Defend">
            <Range BBIdx="1" model="Math">1.000</Range>
            <Range BBIdx="2" model="Math">1.000</Range>
            <Range BBIdx="3" model="Math">0.503</Range>
            <Range BBIdx="4" model="Math">0.341</Range>
        </Action>
    </Position>
    <Position value="Right">
        <Action value="Hit">
            <Range BBIdx="2" model="Math">0.828</Range>
            <Range BBIdx="3" model="Math">0.416</Range>
            <Range BBIdx="4" model="Math">0.278</Range>
        </Action>
        <Action value="Punch">
            <Range BBIdx="1" model="Math">1.000</Range>
            <Range BBIdx="2" model="Math">0.623</Range>
            <Range BBIdx="3" model="Math">0.309</Range>
            <Range BBIdx="4" model="Math">0.217</Range>
        </Action>
        <Action value="HitDefend">
            <Range BBIdx="2" model="Math">0.628</Range>
            <Range BBIdx="3" model="Math">0.313</Range>
            <Range BBIdx="4" model="Math">0.204</Range>
        </Action>
        <Action value="PunchDefend">
            <Range BBIdx="1" model="Math">0.755</Range>
            <Range BBIdx="2" model="Math">0.380</Range>
            <Range BBIdx="3" model="Math">0.192</Range>
            <Range BBIdx="4" model="Math">0.127</Range>
        </Action>
    </Position>
</PlayerCount>
<PlayerCount value="3">
    <Position value="Up">
        <Action value="Hit">
            <Range BBIdx="2" model="Math">0.455</Range>
            <Range BBIdx="3" model="Math">0.237</Range>
            <Range BBIdx="4" model="Math">0.158</Range>
        </Action>
        <Action value="Punch">
            <Range BBIdx="0" model="Math">0.931</Range>
            <Range BBIdx="1" model="Math">0.702</Range>
            <Range BBIdx="2" model="Math">0.372</Range>
            <Range BBIdx="3" model="Math">0.178</Range>
            <Range BBIdx="4" model="Math">0.117</Range>
        </Action>
        <Action value="Defend">
            <Range BBIdx="1" model="Math">1.000</Range>
            <Range BBIdx="2" model="Math">0.725</Range>
            <Range BBIdx="3" model="Math">0.352</Range>
            <Range BBIdx="4" model="Math">0.235</Range>
        </Action>
    </Position>
    <Position value="Left">
        <Action value="Hit">
            <Range BBIdx="2" model="Math">0.576</Range>
            <Range BBIdx="3" model="Math">0.273</Range>
            <Range BBIdx="4" model="Math">0.189</Range>
        </Action>
        <Action value="Punch">
            <Range BBIdx="0" model="Math">1.000</Range>
            <Range BBIdx="1" model="Math">0.862</Range>
            <Range BBIdx="2" model="Math">0.434</Range>
            <Range BBIdx="3" model="Math">0.209</Range>
            <Range BBIdx="4" model="Math">0.150</Range>
        </Action>
        <Action value="Defend">
            <Range BBIdx="1" model="Math">1.000</Range>
            <Range BBIdx="2" model="Math">0.844</Range>
            <Range BBIdx="3" model="Math">0.439</Range>
            <Range BBIdx="4" model="Math">0.291</Range>
        </Action>
        <Action value="HitDefend">
            <Range BBIdx="2" model="Math">0.429</Range>
            <Range BBIdx="3" model="Math">0.212</Range>
            <Range BBIdx="4" model="Math">0.142</Range>
        </Action>
        <Action value="PunchDefend">
            <Range BBIdx="0" model="Math">0.693</Range>
            <Range BBIdx="1" model="Math">0.530</Range>
            <Range BBIdx="2" model="Math">0.269</Range>
            <Range BBIdx="3" model="Math">0.133</Range>
...
<PlayerCount value="3">
...

I would like to be able to access easily the numbers between the <Range> tag.

Something like get the number where

<PlayerCount value="2">
<Position value="Left">
<Action value="Hit">
<Range BBIdx="2" model="Math">

If it would be mysql I would do something like:

$query = "SELECT range FROM modeling WHERE BB='' AND POS='' AND OPP='";

Any help is really appreciate. I've wasted 2 days looking at the SimpleXML PHP class but I don't know how to search in the attribute like in this case. I'm sure it will take no more than 2 minutes for you to solve this.

It would be perfect if I have a function like getnumber('file-xml','playercount','position','action','bbidx');

Thanks in advance.

This is the code I wrote, but I don't know how to make it work with attributes:

$xml = new SimpleXMLElement($input);

$res = $xml->xpath('/Playercount[.=2]/Position[.=Left]/Action[.=Hit]/Range[.=2]');

while(list( , $node) = each($result)) {
    echo 'result: ',$node,"\n";
}

Unfortunately this doesn't work as expected.

This is the code I'm trying to use now:

 <?php


$x = <<<XML
<?xml version='1.0' standalone='yes'?>
<document>
<PlayerCount value="2">
    <Position value="Left">
        <Action value="Hit">
            <Range BBIdx="2" model="Math">0.653</Range>
            <Range BBIdx="3" model="Math">0.341</Range>
            <Range BBIdx="4" model="Math">0.216</Range>
        </Action>
        <Action value="Punch">
            <Range BBIdx="0" model="Math">1.000</Range>
            <Range BBIdx="1" model="Math">1.000</Range>
            <Range BBIdx="2" model="Math">0.498</Range>
            <Range BBIdx="3" model="Math">0.256</Range>
            <Range BBIdx="4" model="Math">0.168</Range>
        </Action>
        <Action value="Defend">
            <Range BBIdx="1" model="Math">1.000</Range>
            <Range BBIdx="2" model="Math">1.000</Range>
            <Range BBIdx="3" model="Math">0.503</Range>
            <Range BBIdx="4" model="Math">0.341</Range>
        </Action>
    </Position>
    <Position value="Right">
        <Action value="Hit">
            <Range BBIdx="2" model="Math">0.828</Range>
            <Range BBIdx="3" model="Math">0.416</Range>
            <Range BBIdx="4" model="Math">0.278</Range>
        </Action>
        <Action value="Punch">
            <Range BBIdx="1" model="Math">1.000</Range>
            <Range BBIdx="2" model="Math">0.623</Range>
            <Range BBIdx="3" model="Math">0.309</Range>
            <Range BBIdx="4" model="Math">0.217</Range>
        </Action>
        <Action value="HitDefend">
            <Range BBIdx="2" model="Math">0.628</Range>
            <Range BBIdx="3" model="Math">0.313</Range>
            <Range BBIdx="4" model="Math">0.204</Range>
        </Action>
        <Action value="PunchDefend">
            <Range BBIdx="1" model="Math">0.755</Range>
            <Range BBIdx="2" model="Math">0.380</Range>
            <Range BBIdx="3" model="Math">0.192</Range>
            <Range BBIdx="4" model="Math">0.127</Range>
        </Action>
    </Position>
</PlayerCount>
</document>
XML;

$xml = simplexml_load_string($x);

//$result = (string)$xml->xpath("//PlayerCount[@value='2']/Position[@value='Left']/Action[@value='Hit']/Range[@BBIdx='2' and @model='Math']")[0];

list($result) = (string)$xml->xpath("//document/PlayerCount[@value='2']/Position[@value='Left']/Action[@value='Hit']/Range[@BBIdx='2' and @model='Math']");
var_dump($result);

?>

Var_dump returns NULL. How come?

Giorgio
  • 1,603
  • 5
  • 29
  • 52

1 Answers1

1

Your xpath is almost there, use @for attributes though:

$result = (string)$xml->xpath("//PlayerCount[@value='2']/Position[@value='Left']/Action[@value='Hit']/Range[@BBIdx='2' and @model='Math']")[0];

This will work with PHP >= 5.4 and return the first selected value.
see it working: http://codepad.viper-7.com/fI1Dh6

With PHP < 5.4:

list($result) = $xml->xpath(...);
$result = (string)$result;  

or do...

$result = $xml->xpath("//PlayerCount[@value='2']/Position[@value='Left']/Action[@value='Hit']/Range[@BBIdx='2' and @model='Math']");
$result = (string)$result[0];

see it working: http://codepad.viper-7.com/2DhUiN

michi
  • 6,565
  • 4
  • 33
  • 56