1

Is there any way to properly iterate over an array in my listener that contains the PDF byte data for each PDF and have it write each one to a separate text file? I've been working on this for three days and can only get it to write the first one and that's it.

EDIT: Here is the new code I've stripped it down to:

foreach($xml->DocumentPDFs->DocumentPDF as $value) {
    $value = $value->PDFBytes;
    $binary = base64_decode($value);
    file_put_contents($xml->EnvelopeStatus->EnvelopeID . "/" . $xml->EnvelopeStatus->DocumentStatuses->DocumentStatus->Name . ".pdf", $binary);
}

I was using this:

$docarr = array();
foreach($xml->DocumentPDFs as $DocumentPDFs){
    foreach ($DocumentPDFs->DocumentPDF as $DocumentPDF) {
        $docarr[] = $DocumentPDF->PDFBytes;
        foreach ($docarr as $pdfbyte) {
            $docfiles = $xml->EnvelopeStatus->EnvelopeID . "/" . $xml->EnvelopeStatus->DocumentStatuses->DocumentStatus->Name . '.txt';
            $doctxt = fopen($docfiles,"w");
            write($doctxt,$pdfbyte);
            fclose($doctxt);
        }
    }
}

For some reason it keeps just iterating over the first chunk, prints it, then stops there.

NEW EDIT - So I'm just loading the XML response into simplexml_load_file. This is the print_r on $xml->DocumentPDFs:

SimpleXMLElement Object
(
    [DocumentPDF] => Array
        (
            [0] => SimpleXMLElement Object
                (
                    [Name] => Corporate_Information.pdf
                    [PDFBytes] => JVBERi0xLjQKJfv8/f4KMiAwIG9iago8PAovTW9kRGF0ZSAo...
                    [DocumentType] => CONTENT
                )

            [1] => SimpleXMLElement Object
                (
                    [Name] => LLC_Information.pdf
                    [PDFBytes] => JVBERi0xLjQKJfv8/f4KMiAwIG9iago8PAovTW9kRGF0Z...
                    [DocumentType] => CONTENT
                )

            [2] => SimpleXMLElement Object
                (
                    [Name] => Demo Document.pdf
                    [PDFBytes] => JVBERi0xLjQKJfv8/f4KNiAwIG9iago8PAovUGFyZW5...
                    [DocumentType] => CONTENT
                )

            [3] => SimpleXMLElement Object
                (
                    [Name] => CertificateOfCompletion_4b79ca0d-bbc4-4b2b-9993-295755d3b3ad.pdf
                    [PDFBytes] => JVBERi0xLjQKJfv8/f4KMiAwIG9iago...
                    [DocumentType] => SUMMARY
                )

        )

    )

The print_r on $xml->DocumentPDFs->DocumentPDF:

SimpleXMLElement Object
(
    [Name] => Corporate_Information.pdf
    [PDFBytes] => JVBERi0xLjQKJfv8/f4KMiAwIG9iago8PAovTW9kRGF0ZSAoRDoyMDEzMD...
    [DocumentType] => CONTENT
)

SimpleXMLElement Object
(
    [Name] => Corporate_Information.pdf
    [PDFBytes] => JVBERi0xLjQKJfv8/f4KMiAwIG9iago8PAovTW9kRGF0ZSAoRDoyMD...
    [DocumentType] => CONTENT
)

SimpleXMLElement Object
(
    [Name] => Corporate_Information.pdf
    [PDFBytes] => JVBERi0xLjQKJfv8/f4KMiAwIG9iago8PAovTW9kRGF0ZSAoRDoyMDEzMDkx...
    [DocumentType] => CONTENT
)

SimpleXMLElement Object
(
    [Name] => Corporate_Information.pdf
    [PDFBytes] => JVBERi0xLjQKJfv8/f4KMiAwIG9iago8PAovTW9kRGF0ZSAoR...
    [DocumentType] => CONTENT
)

For some reason it returns the DocumentPDFs correctly, but when I drill down into DocumentPDF it returns basically the same PDF. Why is that?

NEWER EDIT - So I just changed the foreach call to $xml->DocumentPDFs->DocumentPDF->PDFBytes as $value, did a print_r on the same items and the print on DocumentPDFs returns the same thing but the print on DocumentPDF returns one object. I'm parsing correctly as far as I can see.

MORE NEW EDIT - I changed my foreach loop to this:

foreach($xml->DocumentPDFs as $DocumentPDFs) {
    foreach ($DocumentPDFs->DocumentPDF as $DocumentPDF) {
        foreach ($DocumentPDF->PDFBytes as $pdfbytes) {
            $binary = base64_decode($pdfbytes);
            file_put_contents($xml->EnvelopeStatus->EnvelopeID . "/" . $xml->EnvelopeStatus->DocumentStatuses->DocumentStatus->Name . ".pdf", $binary);
        }
    }
}

Then I did my prints again and the one on DocumentPDF now prints the proper information. I still can't get it to write out all the PDFs though. Any thoughts?

LATEST EDIT - So I made it a regular array:

$json = json_encode($xml);
$array = json_decode($json,TRUE);
foreach($array['DocumentPDFs']['DocumentPDF'] as $DocumentPDF){
    $binary = base64_decode($DocumentPDF['PDFBytes']);
    file_put_contents($xml->EnvelopeStatus->EnvelopeID . "/" . $xml->EnvelopeStatus->DocumentStatuses->DocumentStatus->Name . ".pdf", $file);
}

But it's still just printing that last PDF. What am I doing wrong?!

duckie715
  • 165
  • 3
  • 13
  • you should probably show your language and your code. If you can see the XML output and it looks good the issue is probably with how you parse the XML array. – mikebz Sep 19 '13 at 21:04
  • Sorry. I'm usually good at that. I've added some foreach loops I've been working with, done in PHP and also using SimpleXML. – duckie715 Sep 19 '13 at 21:38
  • With the newer loop it's actually now just grabbing the Certificate, which is the last byte of data, correct? – duckie715 Sep 19 '13 at 22:07
  • Typially, yes, the certificate is the last document, but I'm not sure if that's always true or not. – Ergin Sep 19 '13 at 22:30
  • Still not sure of what's going on. It has all the elements but still only prints out the certificate. – duckie715 Sep 20 '13 at 04:01
  • I'm wondering if there's something going on with SimpleXml, have you seen this post related to looping over simplexml objects with a foreach statement? Try doing it this way... [previous SO question](http://stackoverflow.com/questions/12154689/foreach-and-simplexml). There's also this post too where they were running into the same duplicates problem as you: [duplicate values in foreach](http://stackoverflow.com/questions/6610121/php-simplexml-repeated-data) – Ergin Sep 20 '13 at 18:44
  • I've updated my code (as above) but it's still just printing the last PDF. Driving me crazy. I'm obviously doing something wrong. – duckie715 Sep 20 '13 at 19:25
  • I've also converted all my objects to strings at one point and even that didn't work. Something weird is going on and I can't figure it out. – duckie715 Sep 20 '13 at 22:19
  • What happens if instead of using a foreach() loop you get the size of the array and use a normal for() loop to loop over that count and access each array element by index number? Do you get the same results?? – Ergin Sep 20 '13 at 22:37
  • I've updated my answer, please see the code I added and accept answer if it works for you. --Ergin – Ergin Sep 20 '13 at 23:31
  • I'm pulling in the XML as a header response and have no control over converting it to a string, so I don't know how to do this. – duckie715 Sep 21 '13 at 01:49
  • I'm wondering if SimpleXML just can't handle so much PDF byte information at one time. – duckie715 Sep 21 '13 at 03:10
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/37785/discussion-between-duckie715-and-ergin) – duckie715 Sep 21 '13 at 14:18
  • So now I have a PDF that is 1.10 MB. This has to have all the PDFs in it, but it is only displaying the first page. Do you know of any way to have it display all the pages of all the PDFs? As a way around the printing them all individually? – duckie715 Sep 24 '13 at 19:14

1 Answers1

0

In PHP the foreach() loop works only on properly formatted arrays. If you are currently looping with:

foreach($xml->DocumentPDFs->DocumentPDF as $value) 
{
...
}

and it only loops once then that means either:

1.  $xml->DocumentPDFs->DocumentPDF is not a valid / properly formatted array OR
2.  There is only one PDF in the given envelope (i.e. only 1 array element)

Assuming you are testing with an envelope that has more than one PDF in it, have you verified that you are parsing the xml correctly into your $xml object? You might want to do a var_dump() or print_r() at each level (i.e. DocumentPDFs, DocumentPDFs->DocumentPDF) during each iteration of your for loop and that will probably expose where the issue is.


UPDATE

I was able to get to this to work with the following PHP code. Try using this, it works for me. I've commented out the PDFBytes for now since it writes all that data to output, try this before un-commenting to see if your getting unique document names and types...

<?php
$xml = file_get_contents("PATH_TO_YOUR_XML_FILE");
$obj = new SimpleXMLElement($xml);

foreach($obj->{'DocumentPDFs'}->DocumentPDF as $value) 
{
    print_r($value->Name);
    print_r($value->DocumentType);
    //print_r($value->PDFBytes);        
}
?>
Ergin
  • 9,254
  • 1
  • 19
  • 28
  • I'm still unable to get this to work and can't track it down. – duckie715 Sep 20 '13 at 21:04
  • This may sound stupid, but is what I want to do even possible? I'm sure it is but I've done so many tests with so many different versions of for loops, foreach loops and even while loops, and using SimpleXML arrays and regular arrays, that I keep getting the same output each time and I'm getting nowhere. – duckie715 Sep 20 '13 at 21:51
  • In regards to your updated answer, it only returns contents from an envelope created, sent and completed on Friday the 20th. It doesn't get updated at all. I'm starting to think I will never get this figured out. – duckie715 Sep 23 '13 at 21:47
  • So a huge problem and possibly one of the issues is that there are a ton of documents sitting in the cache that never got printed and are causing a big problem right now. I've completely turned off the certificate download but they are getting added to the new documents and getting printed. How do I clear the old documents out of the cache? – duckie715 Sep 24 '13 at 23:13
  • So I have this: `foreach($xml->DocumentPDFs->DocumentPDF as $value) { $valuename = $value->Name; print("
    ".print_r($valuename,true)."
    "); $output = print_r($valuename, true); file_put_contents($docname . ".txt", $output); }`. It prints this to the screen: `SimpleXMLElement Object ( [0] => Corporate_Information ) SimpleXMLElement Object ( [0] => LLC_Information )`. It writes a file called the name of the first PDF with the title of the second PDF in it. It doesn't make sense.
    – duckie715 Sep 25 '13 at 22:57
  • As it turns out, it was a combination of both our code. I just had to reread yours in a quiet place and it all made sense. – duckie715 Sep 26 '13 at 14:16
  • Cool glad you finally cracked this one... :) – Ergin Sep 26 '13 at 17:06