0

I have an XML which is supplied by a third party and I have no control over its formatting. It looks like this:

<base>  
    <results index="1">  
        <quote vendor_name="Company X">  
            <quote_detail rate="3.375" price="-0.440">  
                <stuff>value</stuff>  
            </quote_detail>  
        </quote>  
    </results>  
    <results index="2">  
        <quote vendor_name="Company y">  
            <quote_detail rate="3.548" price="-0.230">  
                <stuff>value</stuff>  
            </quote_detail>  
        </quote>  
    </results>  
    <results index="3">  
        <quote vendor_name="Company Z">  
            <quote_detail rate="3.799" price="1.120">  
                <stuff>value</stuff>  
            </quote_detail>  
        </quote>  
    </results>  
</base>

What I need to do is return the result (vendor_name, rate and price) that has a price closest to zero without going over as well as the next two above and below. The ideal result would look something like this (where the middle one is closest to zero):

  1. Company Z / 3.875 / -1.375
  2. Company Y / 3.750 / -0.875
  3. Company X / 3.375 / -0.440
  4. Company A / 3.500 / 0.250
  5. Company B / 3.375 / 1.125

I'm not sure about the logic required to do this or how to preserve the XML information while running said logic. Any help?

Adi
  • 5,089
  • 6
  • 33
  • 47
  • 1
    isn't Company A closer to zero than Company X? – Jan Prieser Jul 13 '12 at 14:29
  • Dunno if you can sort XML, but you can put that in an array, `ksort` it and output the first 5 variables. – Peon Jul 13 '12 at 14:30
  • 1
    @DainisAbols suggests a good start, I dont think this question belongs here. You give a start point, a desired end, but there is no effort at a solution in between – allen213 Jul 13 '12 at 14:34
  • You can use [XQuery](http://www.w3.org/TR/xquery/), this question may help you http://stackoverflow.com/q/2211743/1105514 – Adi Jul 13 '12 at 14:50

2 Answers2

0

i'm just throwing some links for you to help you get started.

please look at simpleXML to access the xml data with php objects. the XQuery Hint in your comments points you in this direction, too.

while looping through your results, you could save the absolute values of the prizes in an array and sort them with ksort.

Jan Prieser
  • 1,529
  • 9
  • 15
0

What you have to do is parse the data out of the XML to be able to work with it. Then, once you have the data, you can select the companies that you need.

Here is a mostly working solution using PHP's DOMDocument class. First, this starts off by parsing the companies into an array:

$doc = new DOMDocument;
$doc->loadXML( $xml); // $xml = your string from above

$xpath = new DOMXPath( $doc);

$companies = array();
foreach( $xpath->query('//results') as $result) {
    $quote = $xpath->query( 'quote', $result)->item(0);
    $vendor_name = $quote->attributes->getNamedItem( 'vendor_name')->value;

    $quote_detail = $xpath->query( 'quote_detail', $quote)->item(0);
    $rate = $quote_detail->attributes->getNamedItem( 'rate')->value;
    $price = $quote_detail->attributes->getNamedItem( 'price')->value;

    $companies[] = array( 
        'vendor_name' => $vendor_name,
        'rate' => $rate,
        'price' => $price
    );
}

var_dump( $companies);

Now, you have a companies array which is similar to:

array(3) {
  [0]=>
  array(3) {
    ["vendor_name"]=>
    string(9) "Company X"
    ["rate"]=>
    string(5) "3.375"
    ["price"]=>
    string(6) "-0.440"
  }
  [1]=>
  array(3) {
    ["vendor_name"]=>
    string(9) "Company y"
    ["rate"]=>
    string(5) "3.548"
    ["price"]=>
    string(6) "-0.230"
  }
  [2]=>
  array(3) {
    ["vendor_name"]=>
    string(9) "Company Z"
    ["rate"]=>
    string(5) "3.799"
    ["price"]=>
    string(5) "1.120"
  }
}

Then, this sorts that list of companies on the price field.

usort( $companies, function( $a, $b) { 
    if( $a['price'] == $b['price']) 
        return 0; 
    return $a['price'] < $b['price'] ? -1 : 1;
});

var_dump( $companies);

Your example data is already sorted, so this ends up doing nothing. However, you need a sorted array to be able to determine which ones are closest to zero.

From here, you will have to figure out how to select the 5 elements you need. I think this is more than needed to get started.

nickb
  • 59,313
  • 13
  • 108
  • 143
  • if you need the closest price value to 0 with negative values taken into account, you need to use abs($price) in your comparison function. otherwise you would find the lowest negative values in your sorted array. – Jan Prieser Jul 13 '12 at 15:11
  • That would be the complete working solution, which I didn't say I was producing :) The OP can do *some* of the work. – nickb Jul 13 '12 at 15:22