MDS
MDS

Reputation: 507

Parsing XML with REGEX

I'm trying to integrate UPS shipping label printing functionality into a custom crm/shopping cart app. I'm forming the xml document using a php stdClass object. I pass the method an array containing the package(s) variables ex.

    $pkgs = Array ( [1] => Array ( [length] => 6 [width] => 8 [height] => 11 [weight] => 5 ) [2] => Array ( [length] => 5 [width] => 14 [height] => 10 [weight] => 9 ) )

My xml building method looks like this

public function assemble_xml($pkgs){
    $xmlRequest = new stdClass();
    $xmlRequest->header="<?xml version='1.0'?>
<AccessRequest xml:lang='en-US'>
<AccessLicenseNumber>HIDDEN</AccessLicenseNumber>
<UserId>HIDDEN</UserId>
<Password>HIDDEN</Password>
</AccessRequest>
<?xml version='1.0'?>
<ShipmentConfirmRequest xml:lang='en-US'>
<Request>
    <TransactionReference>
        <CustomerContext>Customer Comment</CustomerContext>
        <XpciVersion/>
    </TransactionReference>
    <RequestAction>ShipConfirm</RequestAction>
    <RequestOption>validate</RequestOption>
</Request>
<LabelSpecification>
    <LabelPrintMethod>
        <Code>GIF</Code>
        <Description>gif file</Description>
    </LabelPrintMethod>
    <HTTPUserAgent>Mozilla/4.5</HTTPUserAgent>
    <LabelImageFormat>
        <Code>GIF</Code>
        <Description>gif</Description>
    </LabelImageFormat>
</LabelSpecification>
<Shipment>
    <RateInformation>
        <NegotiatedRatesIndicator/>
    </RateInformation>
    <Description/>
    <Shipper>
        <Name>HIDDEN</Name>
        <PhoneNumber>HIDDEN</PhoneNumber>
        <ShipperNumber>HIDDEN</ShipperNumber>
        <TaxIdentificationNumber>HIDDEN</TaxIdentificationNumber>
        <Address>
            <AddressLine1>HIDDEN</AddressLine1>
            <City>HIDDEN</City>
            <StateProvinceCode>HIDDEN</StateProvinceCode>
            <PostalCode>HIDDEN</PostalCode>
            <PostcodeExtendedLow></PostcodeExtendedLow>
            <CountryCode>HIDDEN</CountryCode>
        </Address>
    </Shipper>";
    $xmlRequest->shipto="<ShipTo>
        <CompanyName>HIDDEN</CompanyName>
        <AttentionName>HIDDEN</AttentionName>
        <PhoneNumber></PhoneNumber>
        <Address>
            <AddressLine1>HIDDEN</AddressLine1>
            <City>HIDDEN</City>
            <StateProvinceCode>HIDDEN</StateProvinceCode>
            <PostalCode>HIDDEN</PostalCode>
            <CountryCode>HIDDEN</CountryCode>
        </Address>
    </ShipTo>";
    $xmlRequest->shipper="<ShipFrom>
        <CompanyName>HIDDEN</CompanyName>
        <AttentionName></AttentionName>
        <PhoneNumber>HIDDEN</PhoneNumber>
        <TaxIdentificationNumber>HIDDEN</TaxIdentificationNumber>
        <Address>
            <AddressLine1>HIDDEN</AddressLine1>
            <City>HIDDEN</City>
            <StateProvinceCode>HIDDEN</StateProvinceCode>
            <PostalCode>HIDDEN</PostalCode>
            <CountryCode>HIDDEN</CountryCode>
        </Address>
    </ShipFrom>";
    $xmlRequest->payment="<PaymentInformation>
        <Prepaid>
            <BillShipper>
                <AccountNumber>HIDDEN</AccountNumber>
            </BillShipper>
        </Prepaid>
    </PaymentInformation>";
    $xmlRequest->service="<Service>
        <Code>03</Code>
        <Description>Ground</Description>
    </Service>";
    for($i = 1; $i <= count($pkgs); $i++)  {
        $xmlRequest->$i ="<Package>
        <PackagingType>
            <Code>02</Code>
            <Description>Customer Supplied</Description>
        </PackagingType>
        <Description>Package</Description>
        <ReferenceNumber>
            <Code></Code>
            <Value></Value>
        </ReferenceNumber>
        <Dimensions>
            <UnitOfMeasurement>
                <Code>IN</Code>
            </UnitOfMeasurement>
                <Length>22</Length>
                <Width>20</Width>
                <Height>18</Height>
        </Dimensions>
       <PackageWeight>
        <Weight>14.1</Weight>
        </PackageWeight>
        <AdditionalHandling>0</AdditionalHandling>
    </Package>";
    }
    $xmlRequest->footer="</Shipment>
</ShipmentConfirmRequest>";
return $xmlRequest;

Cool that works. Now I feed it thru a few other functions to get my digest.

    public function ups_send($assemble_xml){
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, "https://wwwcie.ups.com/ups.app/xml/ShipConfirm");
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $assemble_xml);
    curl_setopt($ch, CURLOPT_TIMEOUT, 3600);
    $xmlResponse = curl_exec ($ch);
    return $xmlResponse;



    public function get_confirm_response($xmlResponse){
    preg_match_all( "/\<ShipmentConfirmResponse\>(.*?)\<\/ShipmentConfirmResponse\>/s",
    $xmlResponse, $bookblocks );
    foreach( $bookblocks[1] as $block )
    {
    preg_match_all( "/\<ShipmentDigest\>(.*?)\<\/ShipmentDigest\>/",
        $block, $author ); // SHIPPING DIGEST

    $digest = $author[1][0];
    $this->decode_label($digest);

    }
    }



    public function decode_label($digest){
    $xmlRequest1="<?xml version='1.0' encoding='ISO-8859-1'?>
                    <AccessRequest>
                            <AccessLicenseNumber>HIDDEN</AccessLicenseNumber>
                        <UserId>HIDDEN</UserId>
                        <Password>HIDDEN</Password>
                    </AccessRequest>
                    <?xml version=”1.0? encoding=”ISO-8859-1??>
                    <ShipmentAcceptRequest>
                        <Request>
                            <TransactionReference>
                                <CustomerContext>Customer Comment</CustomerContext>
                            </TransactionReference>
                            <RequestAction>ShipAccept</RequestAction>
                            <RequestOption>1</RequestOption>
                        </Request>
                        <ShipmentDigest>$digest</ShipmentDigest>
                    </ShipmentAcceptRequest>";

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, "https://wwwcie.ups.com/ups.app/xml/ShipAccept");
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $xmlRequest1);
    curl_setopt($ch, CURLOPT_TIMEOUT, 3600);

    $xmlResponse = curl_exec ($ch); // SHIP ACCEPT RESPONSE

    $xml = $xmlResponse;



    preg_match_all( "/\<ShipmentAcceptResponse\>(.*?)\<\/ShipmentAcceptResponse\>/s",
        $xml, $bookblocks );

    foreach( $bookblocks[1] as $block )
    {

        preg_match_all( "/\<GraphicImage\>(.*?)\<\/GraphicImage\>/",
        $block, $author ); // GET LABEL


        for($l=0; $l<=count($author[0])-1; $l++){

            echo '<img src="data:image/gif;base64,'. $author[1][$l]. '"/>';

        }

    }

}

This all works with 1 or 2 labels, the labels are successfully decoded into label 1 of 2 and 2 of 2. BUT when I try to make 3 or more labels I get a successful response xml from UPS but I no labels are generated. I have been banging my head against my desk for days over this and could really use the expertise of SO to give me a nudge in the right direction about what I'm doing wrong. Why does 1 or 2 labels work but 3 or more doesn't? WHAT GIVES!

If its the regex thats wrong then why does it work if only 2 labels are requested?

There is a postscript you might be interested in.

Here is a pastebin of the xml response from UPS containing the labels.

http://pastebin.com/h3nhNQ0R

Upvotes: 0

Views: 251

Answers (1)

MDS
MDS

Reputation: 507

After reading the links you folks provided, I learned that not only was I losing my mind trying to do this when clearly a more appropriate solution was available but also

"Giving in to Them and their blasphemous ways which doom us all to inhuman toil for the One whose Name cannot be expressed." ~bobince

I replaced this unholy weeping child

    preg_match_all( "/\<ShipmentAcceptResponse\>(.*?)\<\/ShipmentAcceptResponse\>/s",
        $xml, $bookblocks );

    foreach( $bookblocks[1] as $block )
    {

        preg_match_all( "/\<GraphicImage\>(.*?)\<\/GraphicImage\>/",
        $block, $author ); // GET LABEL


        for($l=0; $l<=count($author[0])-1; $l++){

            echo '<img src="data:image/gif;base64,'. $author[1][$l]. '"/>';

        }

    }

with this beautiful solution

    $label_resp = new SimpleXMLElement($xml);
    foreach($label_resp->ShipmentResults->PackageResults as $package ){
        echo '<img src="data:image/gif;base64,'. $package->LabelImage->GraphicImage. '"/>';
    }

Not only does it worked perfectly, it also runs circles around the original solution speed wise.

Thank you, saviors of mankind, for your push in the right direction.

Upvotes: 1

Related Questions