Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 10 of 10
  1. #1
    Regular Coder
    Join Date
    May 2009
    Posts
    165
    Thanks
    77
    Thanked 1 Time in 1 Post

    Parsing XML from SOAP response

    Hi guys,

    Feel free to move if this would be better performed in another language. Basically, I do a SOAP request. I then receive a response and store it into a variable. The response is like

    Code:
    <SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/">
       <SOAP:Body>
          <air:AvailabilitySearchRsp TraceId="test" xmlns:air="http://www.test.com/schema/test_v24_0">
             <air:FlightDetailsList>
                <air:FlightDetails Key="+v5Pvz6ATRekIe8GOUrE4A==" Origin="SYD" Destination="MEL" DepartureTime="2013-12-30T06:00:00.000+11:00" FlightTime="95" TravelTime="95" Equipment="320" OriginTerminal="2" DestinationTerminal="1"/>
                <air:FlightDetails Key="PbqZMSakSOKZ8Bu73xphng==" Origin="SYD" Destination="MEL" DepartureTime="2013-12-30T06:00:00.000+11:00" FlightTime="95" TravelTime="95" Equipment="737" OriginTerminal="3" DestinationTerminal="1"/>
                <air:FlightDetails Key="h9QCS823SBevVdB4VRVi+w==" Origin="SYD" Destination="MEL" DepartureTime="2013-12-30T06:00:00.000+11:00" FlightTime="95" TravelTime="95" Equipment="737" OriginTerminal="3" DestinationTerminal="1"/> 
            </air:FlightDetailsList>
         </air:AvailabilitySearchRsp>
        </SOAP:Body>
    </SOAP:Envelope>
    Now I am trying to output this in a html file. My variable $serverResponse holds the above. For now I am trying
    Code:
    $xml = simplexml_load_string($serverResponse,NULL,NULL,"http://schemas.xmlsoap.org/soap/envelope/");
        $xml->registerXPathNamespace('soap', 'http://schemas.xmlsoap.org/soap/envelope/');
        $xml->registerXPathNamespace('air', 'http://www.test.com/schema/test_v24_0');
        $xml_resp = $xml->xpath('//air:AvailabilitySearchRsp/air:FlightDetailsList');
        echo $xml_resp[0]->AvailabilitySearchRsp;
    Nothing is being echoed so I presume I am doing something wrong. My aim is to display the xml data neatly into a table. What would be the best way of achieving this?

    Thanks

  • #2
    God Emperor Fou-Lu's Avatar
    Join Date
    Sep 2002
    Location
    Saskatoon, Saskatchewan
    Posts
    16,994
    Thanks
    4
    Thanked 2,662 Times in 2,631 Posts
    I'm not sure how you do this with simple_xml. It looks like you'd probably have to fetch the children() off of the list, and give them the namespace. I personally think that's ridiculous since you've already registered against the xpath.
    It's simple in the dom, I modified the xpath slightly so I could collect a node list with each of the flights, instead of the parent of each of the flights (I don't like fetching children if I don't have to, and with XPath there's no reason to really do so):
    PHP Code:
    $dom = new DOMDocument('1.0''UTF-8');
    $dom->loadXML($serverResponse);
    $xpath = new DOMXPath($dom);
    $xpath->registerNamespace('soap''http://schemas.xmlsoap.org/soap/envelope/');
    $xpath->registerNamespace('air''http://www.test.com/schema/test_v24_0');
    $xml_resp $xpath->evaluate('//air:AvailabilitySearchRsp/air:FlightDetailsList/air:FlightDetails');

    foreach (
    $xml_resp AS $available)
    {
        
    // I don't know what makes these any different, but the Key changes, so I'll use that:
        
    printf("Key %s is available" PHP_EOL$available->getAttribute('Key'));

    I assumed $available, that may or may not accurately describe the data.
    PHP Code:
    header('HTTP/1.1 420 Enhance Your Calm'); 
    Been gone for a few months, and haven't programmed in that long of a time. Meh, I'll wing it ;)

  • Users who have thanked Fou-Lu for this post:

    nick2price (10-12-2013)

  • #3
    Regular Coder
    Join Date
    May 2009
    Posts
    165
    Thanks
    77
    Thanked 1 Time in 1 Post
    Fantastic, that works perfectly and a lot better than SimpleXML. I have to ask, what is %s?

    No worries, worked it out. I have now made it print out everything I need
    Code:
    foreach ($xml_resp AS $available)
        {
            printf("Key %s is available <br>\r\n" . PHP_EOL, $available->getAttribute('Key'));
            printf("Departing from %s <br>\r\n" . PHP_EOL, $available->getAttribute('Origin'));
            printf("Arriving at %s <br>\r\n" . PHP_EOL, $available->getAttribute('Destination'));
            printf("Depart time %s <br>\r\n" . PHP_EOL, $available->getAttribute('DepartureTime'));
            printf("Airline type %s <br>\r\n" . PHP_EOL, $available->getAttribute('Equipment'));
            printf("Depart terminal %s <br>\r\n" . PHP_EOL, $available->getAttribute('OriginTerminal'));
            printf("Arrival terminal %s <br>\r\n<br>\r\n" . PHP_EOL, $available->getAttribute('DestinationTerminal'));
        }
    Now the problem is the output contains some more information related to each key above. So for instance, the first key printed is COErbwUVRXCsb7ii0+A1qg==

    That key also relates to the following bit of data (FlightDetailsRef Key)

    Code:
    <air:AirSegmentList>
          <air:AirSegment Key="S6cxmUo5TBa1m91sYSrglQ==" Group="0" Carrier="JQ" FlightNumber="571" Origin="SYD" Destination="MEL" DepartureTime="2013-12-30T06:00:00.000+11:00" ArrivalTime="2013-12-30T07:35:00.000+11:00" ETicketability="Yes" Equipment="320" ChangeOfPlane="false" ParticipantLevel="No Special Participant" OptionalServicesIndicator="false" AvailabilitySource="AvailStatusTTY">
               <air:AirAvailInfo ProviderCode="1P">
                   <air:BookingCodeInfo CabinClass="Economy" BookingCounts="RC|PC|AC|IC|SC|Y4|B4|HC|QC|MC|NC|KC|LC|TC|VC|EC"/>
               </air:AirAvailInfo>
           <air:FlightDetailsRef Key="COErbwUVRXCsb7ii0+A1qg=="/>
    </air:AirSegment>
    How can I also link this in with the data for each key in the previous bit of code?

    Thanks
    Last edited by nick2price; 10-12-2013 at 05:02 PM.

  • #4
    God Emperor Fou-Lu's Avatar
    Join Date
    Sep 2002
    Location
    Saskatoon, Saskatchewan
    Posts
    16,994
    Thanks
    4
    Thanked 2,662 Times in 2,631 Posts
    You should be able to evaluate another xpath expression inside of the loop, and give it the Key you need (fetched from the attribute for the key). I'm sure there's a way in pure xpath to get them together, but I'm not sure how you would do it (xpath is a lot more powerful than people give it credit for). The plus side is, it shouldn't be that resource intensive; the DOM itself is the biggest part since its entirely within memory, but iterating it shouldn't consume much more with a specialized xpath versus a nested lookup approach.
    PHP Code:
    header('HTTP/1.1 420 Enhance Your Calm'); 
    Been gone for a few months, and haven't programmed in that long of a time. Meh, I'll wing it ;)

  • Users who have thanked Fou-Lu for this post:

    nick2price (10-12-2013)

  • #5
    Regular Coder
    Join Date
    May 2009
    Posts
    165
    Thanks
    77
    Thanked 1 Time in 1 Post
    Thanks for the reply. I think I get what you are talking about, and I have got it working partially, but not 100% on the logic here. So inside the foreach loop I have added

    Code:
    $xml_inner = $xpath->evaluate('//air:AvailabilitySearchRsp/air:AirSegmentList/air:AirSegment/air:AirAvailInfo/air:BookingCodeInfo');
    foreach($xml_inner AS $inner_request){
          printf("Cabin class is %s <br>\r\n" . PHP_EOL, $inner_request->getAttribute('CabinClass'));
    }
    Now for each one in the first lot of outputs, thie above will print out every CabinClass for every result returned. So I need to make it only print it out for the one with the same key. I am trying something which doesnt work now, but I think I am on the right lines. Just need a little advice to push me in the right direction. I came up with
    Code:
    foreach ($xml_resp AS $available)
        {
            printf("Key %s is available <br>\r\n" . PHP_EOL, $available->getAttribute('Key'));
            printf("Departing from %s <br>\r\n" . PHP_EOL, $available->getAttribute('Origin'));
            printf("Arriving at %s <br>\r\n" . PHP_EOL, $available->getAttribute('Destination'));
            printf("Depart time %s <br>\r\n" . PHP_EOL, $available->getAttribute('DepartureTime'));
            printf("Airline type %s <br>\r\n" . PHP_EOL, $available->getAttribute('Equipment'));
            printf("Depart terminal %s <br>\r\n" . PHP_EOL, $available->getAttribute('OriginTerminal'));
            printf("Arrival terminal %s <br>\r\n" . PHP_EOL, $available->getAttribute('DestinationTerminal'));
    
            $xml_inner_key = $xpath->evaluate('//air:AvailabilitySearchRsp/air:AirSegmentList/air:AirSegment/air:FlightDetailsRef');
            foreach($xml_inner_key AS $inner_request){
                if($inner_request->getAttribute('Key')===$available->getAttribute('Key')){
                    $xml_inner_data = $xpath->evaluate('//air:AvailabilitySearchRsp/air:AirSegmentList/air:AirSegment/air:FlightDetailsRef');
                    printf("Cabin class is %s <br>\r\n" . PHP_EOL, $inner_request->getAttribute('CabinClass'));
                }
            }
        }
    Thanks

  • #6
    God Emperor Fou-Lu's Avatar
    Join Date
    Sep 2002
    Location
    Saskatoon, Saskatchewan
    Posts
    16,994
    Thanks
    4
    Thanked 2,662 Times in 2,631 Posts
    That's just a matter of the search criteria.
    If I understand what you want, you just need the cabin class, and I think I have your structure correct:
    PHP Code:
        $key $available->getAttribute('Key');
        
    $sXpath "//air:AvailabilitySearchRsp/air:AirSegmentList/air:AirSegment[air:FlightDetailsRef/@Key='$key']/air:AirAvailInfo/air:BookingCodeInfo/attribute::CabinClass";
        
    $cabinclasslist $xpath->evaluate($sXpath);
        
    $sCabinClass 'Unknown';
        if (
    $cabinclasslist->length 0)
        {
            
    $sCabinClass $cabinclasslist->item(0)->value;
        }
        
    printf("Cabin class: %s" PHP_EOL$sCabinClass); 
    PHP Code:
    header('HTTP/1.1 420 Enhance Your Calm'); 
    Been gone for a few months, and haven't programmed in that long of a time. Meh, I'll wing it ;)

  • Users who have thanked Fou-Lu for this post:

    nick2price (10-13-2013)

  • #7
    Regular Coder
    Join Date
    May 2009
    Posts
    165
    Thanks
    77
    Thanked 1 Time in 1 Post
    Thank you, thats fantastic. One last quick question. You done that last xpath using an attribute attribute::CabinClass
    Say I also wanted to search for the attribute BookingCounts. Would I somehow add another attribute to the xpath, or is there a more effecient way to do this?

    Thanks

  • #8
    God Emperor Fou-Lu's Avatar
    Join Date
    Sep 2002
    Location
    Saskatoon, Saskatchewan
    Posts
    16,994
    Thanks
    4
    Thanked 2,662 Times in 2,631 Posts
    I can't see that working. You can just fetch the domelement out of it, and then use the getAttribute like in the outer loop. I just added CabinClass since that's all you appeared to have used. The dereference in the if block would change though; the DOMNodeList is a list of DOMAttr objects for which I can pull the value off of. If you instead grab the parent, you'd need to use the getAttribute instead.

    Edit:
    But do try it out; it does actually return a list, so maybe you can pull multiple. Just add |attribute::whatyouwant to see. Methinks it'll really complain if its syntactically incorrect for xpath.
    PHP Code:
    header('HTTP/1.1 420 Enhance Your Calm'); 
    Been gone for a few months, and haven't programmed in that long of a time. Meh, I'll wing it ;)

  • Users who have thanked Fou-Lu for this post:

    nick2price (10-13-2013)

  • #9
    Regular Coder
    Join Date
    May 2009
    Posts
    165
    Thanks
    77
    Thanked 1 Time in 1 Post
    I am trying to do it using getAttribute because this makes more sense to me. I think I have got myself into a pickle though. I changed it to
    Code:
    $key = $available->getAttribute('Key');
    $sXpath = "//air:AvailabilitySearchRsp/air:AirSegmentList/air:AirSegment[air:FlightDetailsRef/@Key='$key']/air:AirAvailInfo/air:BookingCodeInfo";
    $cabinclasslist = $xpath->evaluate($sXpath);
    
    printf("Cabin class: %s <br>\r\n<br>\r\n" . PHP_EOL, $cabinclasslist->getAttribute('CabinClass'));
    printf("Booking counts: %s <br>\r\n<br>\r\n" . PHP_EOL, $cabinclasslist->getAttribute('BookingCounts'));
    So that should grab the data from BookingCodeInfo. I then evaluate this into cabinclasslist. I then use this to getAttribute which I know now is not allowed. I have tried using $available aswell but that returns nothing.

    I am trying to look at the docs but its confusing me slightly. What am I doing wrong here?

    Thanks

  • #10
    Regular Coder
    Join Date
    May 2009
    Posts
    165
    Thanks
    77
    Thanked 1 Time in 1 Post
    Putting it in its own foreach seemed to solve the problem. Thanks for the help.


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •