xmlsquad / gsheet-to-xml

Given the url of a Google Sheet, this Symfony Console command fetches the Google Sheet and outputs it in the form of Xml.
Apache License 2.0
3 stars 1 forks source link

Task: Test the app since recursive feature implemented #18

Closed forikal-uk closed 6 years ago

forikal-uk commented 6 years ago

Goal

Task: Test the app since recursive feature implemented

Why

@zoka123 has implemented a recursive feature since I last tested the code. So, I want to re-test it to

How

forikal-uk commented 6 years ago

I have changed into my local instance of this project and done a git pull.

Let's try the command

I am trying it on a folder at: https://drive.google.com/drive/u/0/folders/1pgdgRTKQYfMVc1-Kg29FifW-RebwN2Wq

I noticed that the output had these lines:

    <Inventory src-sheet="PrivateFile" src-tab="Sheet1" src-sheet-url="https://docs.google.com/spreadsheets/d/12j2CrvWbZUU2_OJiIIr-sRkut2N-Gid4uwA0ZpkVks0/"></Inventory>
  </Product>

This is because I own that folder and had created a file which only I know about. So, although it is invalid, it shows up in my results. This is new behaviour since we started using the OAuth technique. The previous auth strategy would not have known about this file and hence it was not an issue. I ought to rename it to PrivateFile_. So, this is fine.

forikal-uk commented 6 years ago

I have tested the recursive aspect and it seems to work OK.

When used in a standalone context, to run the command one must specificy the filename and not add the command name in the argument.

I also tried to run the command without performing a composer update which had caused some failed requires.

In the end I got it all working.

Here, for the record, is my series of commands and output:

$ cd XmlAuthoring/
$ ls
bin-ping            tmp-access-token
capture-lookups         xml-authoring-library
csvs                xml-authoring-project
gsheet-to-xml           xml-authoring-tools
ping-parent         xmlauthor-example-command
scapesettings.yaml
$ cd gsheet-to-xml/
$ ls
DOCUMENTATION.md    client_secret.json.dist src
LICENSE         composer.json       tests
README.md       composer.lock       vendor
bin         phpunit.xml.dist
$ git status
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean
$ git pull
Enter passphrase for key '/Users/x/.ssh/id_rsa': 
remote: Counting objects: 34, done.
remote: Compressing objects: 100% (12/12), done.
remote: Total 34 (delta 19), reused 27 (delta 14), pack-reused 0
Unpacking objects: 100% (34/34), done.
From github.com:forikal-uk/gsheet-to-xml
   09663d8..268d2e7  master     -> origin/master
Updating 09663d8..268d2e7
Fast-forward
 DOCUMENTATION.md                                   |   9 +-
 composer.json                                      |   3 +-
 composer.lock                                      | 215 ++++++++++++++++++++-
 src/Application/Service/GoogleClientFactory.php    |  22 ---
 .../Service/GoogleDriveFolderReadService.php       |  25 ++-
 .../Service/GoogleDriveProcessService.php          |  34 ++--
 .../Service/GoogleSpreadsheetReadService.php       |  47 ++++-
 src/Application/Service/XmlSerializer.php          |   2 +-
 src/Command/GsheetToXmlCommand.php                 |  50 ++++-
 .../Test/GoogleDriveProcessServiceTest.php         |  10 +-
 .../Test/InventoryXmlSerializationTest.php         |   2 +-
 11 files changed, 341 insertions(+), 78 deletions(-)
 delete mode 100644 src/Application/Service/GoogleClientFactory.php
$ ls
DOCUMENTATION.md    client_secret.json.dist src
LICENSE         composer.json       tests
README.md       composer.lock       vendor
bin         phpunit.xml.dist

See what happens when command is invoked with no arguments.

$ php bin/gsheet-to-xml.php 

  Not enough arguments (missing: "drive-url").  

forikal:gsheet-to-xml [-r|--recursive] [--client-secret-file CLIENT-SECRET-FILE] [--access-token-file ACCESS-TOKEN-FILE] [--force-authenticate] [--] <drive-url>

Look at the help


$ php bin/gsheet-to-xml.php  --jelp

  The "--jelp" option does not exist.  

forikal:gsheet-to-xml [-r|--recursive] [--client-secret-file CLIENT-SECRET-FILE] [--access-token-file ACCESS-TOKEN-FILE] [--force-authenticate] [--] <drive-url>

$ php bin/gsheet-to-xml.php  --help
Usage:
  forikal:gsheet-to-xml [options] [--] <drive-url>

Arguments:
  drive-url                                    The URL of the Google Drive entity (Google Sheet or Google Drive folder). is-recursive: if the Google Drive entity is a Google Drive folder, this option specifies whether or not to recurse through sub-directories to find sheets.

Options:
  -r, --recursive                              if the Google Drive entity is a Google Drive folder, this option specifies whether or not to recurse through sub-directories to find sheets.
      --client-secret-file=CLIENT-SECRET-FILE  The path to an application client secret file.
      --access-token-file=ACCESS-TOKEN-FILE    The path to an access token file. The file may not exists. If an access token file is used, the command remembers user credentials and doesn't require a Google authentication next time.
      --force-authenticate                     If set, you will be asked to authenticate even if an access token exist.
  -h, --help                                   Display this help message
  -q, --quiet                                  Do not output any message
  -V, --version                                Display this application version
      --ansi                                   Force ANSI output
      --no-ansi                                Disable ANSI output
  -n, --no-interaction                         Do not ask any interactive question
  -v|vv|vvv, --verbose                         Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug

Help:
  Fetch and convert Google Drive Folder / Sheets to XML.

Try it on a folder


$ php bin/gsheet-to-xml.php   --client-secret-file="../../../../APIKeys/OAuth-client_secret_596511451672-flbjqooi8bemek6b96v1oq61jf414oja.apps.googleusercontent.com.json" -v --access-token-file="tmp-access-token" \
> https://drive.google.com/drive/u/0/folders/1pgdgRTKQYfMVc1-Kg29FifW-RebwN2Wq

Fatal error: Uncaught Error: Class 'Forikal\Library\GoogleAPI\GoogleAPIClient' not found in /Users/x/Documents/Projects/XmlAuthoring/gsheet-to-xml/src/Command/GsheetToXmlCommand.php:75
Stack trace:
#0 /Users/x/Documents/Projects/XmlAuthoring/gsheet-to-xml/vendor/symfony/console/Command/Command.php(251): Forikal\GsheetXml\Command\GsheetToXmlCommand->execute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#1 /Users/x/Documents/Projects/XmlAuthoring/gsheet-to-xml/vendor/symfony/console/Application.php(946): Symfony\Component\Console\Command\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#2 /Users/x/Documents/Projects/XmlAuthoring/gsheet-to-xml/vendor/symfony/console/Application.php(248): Symfony\Component\Console\Application->doRunCommand(Object(Forikal\GsheetXml\Command\GsheetToXmlCommand), Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOut in /Users/x/Documents/Projects/XmlAuthoring/gsheet-to-xml/src/Command/GsheetToXmlCommand.php on line 75

$ php bin/gsheet-to-xml.php   --client-secret-file="../../../../APIKeys/OAuth-client_secret_596511451672-flbjqooi8bemek6b96v1oq61jf414oja.apps.googleusercontent.com.json" -v --access-token-file="tmp-access-token" -r https://drive.google.com/drive/u/0/folders/1pgdgRTKQYfMVc1-Kg29FifW-RebwN2Wq

Fatal error: Uncaught Error: Class 'Forikal\Library\GoogleAPI\GoogleAPIClient' not found in /Users/x/Documents/Projects/XmlAuthoring/gsheet-to-xml/src/Command/GsheetToXmlCommand.php:75
Stack trace:
#0 /Users/x/Documents/Projects/XmlAuthoring/gsheet-to-xml/vendor/symfony/console/Command/Command.php(251): Forikal\GsheetXml\Command\GsheetToXmlCommand->execute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#1 /Users/x/Documents/Projects/XmlAuthoring/gsheet-to-xml/vendor/symfony/console/Application.php(946): Symfony\Component\Console\Command\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#2 /Users/x/Documents/Projects/XmlAuthoring/gsheet-to-xml/vendor/symfony/console/Application.php(248): Symfony\Component\Console\Application->doRunCommand(Object(Forikal\GsheetXml\Command\GsheetToXmlCommand), Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOut in /Users/x/Documents/Projects/XmlAuthoring/gsheet-to-xml/src/Command/GsheetToXmlCommand.php on line 75
$ php bin/gsheet-to-xml.php   --client-secret-file="../../../../APIKeys/OAuth-client_secret_596511451672-flbjqooi8bemek6b96v1oq61jf414oja.apps.googleusercontent.com.json" -v --access-token-file="tmp-access-token" -r https://drive.google.com/drive/u/0/folders/1pgdgRTKQYfMVc1-Kg29FifW-RebwN2Wq
$ ls bin/gsheet-to-xml.php 
.git/                    bin/                     src/
.gitignore               client_secret.json.dist  tests/
DOCUMENTATION.md         composer.json            vendor/
LICENSE                  composer.lock            
README.md                phpunit.xml.dist         
$ ls bin/gsheet-to-xml.php 
.git/                    bin/                     src/
.gitignore               client_secret.json.dist  tests/
DOCUMENTATION.md         composer.json            vendor/
LICENSE                  composer.lock            
README.md                phpunit.xml.dist         

$ ls bin/
gsheet-to-xml.php
$ php bin/gsheet-to-xml.php forikal:gsheet-to-xml  --client-secret-file="../../../../APIKeys/OAuth-client_secret_596511451672-flbjqooi8bemek6b96v1oq61jf414oja.apps.googleusercontent.com.json" -v --access-token-file="tmp-access-token" -r https://drive.google.com/drive/u/0/folders/1pgdgRTKQYfMVc1-Kg29FifW-RebwN2Wq

In ArgvInput.php line 187:

  [Symfony\Component\Console\Exception\RuntimeException]  
  Too many arguments, expected arguments "drive-url".     

Exception trace:
 Symfony\Component\Console\Input\ArgvInput->parseArgument() at /Users/x/Documents/Projects/XmlAuthoring/gsheet-to-xml/vendor/symfony/console/Input/ArgvInput.php:86
 Symfony\Component\Console\Input\ArgvInput->parse() at /Users/x/Documents/Projects/XmlAuthoring/gsheet-to-xml/vendor/symfony/console/Input/Input.php:55
 Symfony\Component\Console\Input\Input->bind() at /Users/x/Documents/Projects/XmlAuthoring/gsheet-to-xml/vendor/symfony/console/Command/Command.php:210
 Symfony\Component\Console\Command\Command->run() at /Users/x/Documents/Projects/XmlAuthoring/gsheet-to-xml/vendor/symfony/console/Application.php:946
 Symfony\Component\Console\Application->doRunCommand() at /Users/x/Documents/Projects/XmlAuthoring/gsheet-to-xml/vendor/symfony/console/Application.php:248
 Symfony\Component\Console\Application->doRun() at /Users/x/Documents/Projects/XmlAuthoring/gsheet-to-xml/vendor/symfony/console/Application.php:148
 Symfony\Component\Console\Application->run() at /Users/x/Documents/Projects/XmlAuthoring/gsheet-to-xml/bin/gsheet-to-xml.php:14

forikal:gsheet-to-xml [-r|--recursive] [--client-secret-file CLIENT-SECRET-FILE] [--access-token-file ACCESS-TOKEN-FILE] [--force-authenticate] [--] <drive-url>
$ php bin/gsheet-to-xml.php forikal:gsheet-to-xml --client-secret-file="../../../../APIKeys/OAuth-client_secret_596511451672-flbjqooi8bemek6b96v1oq61jf414oja.apps.googleusercontent.com.json" -v --access-token-file="tmp-access-token" \
> https://docs.google.com/spreadsheets/d/1hdKksm6Xj6SiL3r8paCzlW2gBMRnm445ZBflUL-591M/edit#gid=311423522

In ArgvInput.php line 187:

  [Symfony\Component\Console\Exception\RuntimeException]  
  Too many arguments, expected arguments "drive-url".     

Exception trace:
 Symfony\Component\Console\Input\ArgvInput->parseArgument() at /Users/x/Documents/Projects/XmlAuthoring/gsheet-to-xml/vendor/symfony/console/Input/ArgvInput.php:86
 Symfony\Component\Console\Input\ArgvInput->parse() at /Users/x/Documents/Projects/XmlAuthoring/gsheet-to-xml/vendor/symfony/console/Input/Input.php:55
 Symfony\Component\Console\Input\Input->bind() at /Users/x/Documents/Projects/XmlAuthoring/gsheet-to-xml/vendor/symfony/console/Command/Command.php:210
 Symfony\Component\Console\Command\Command->run() at /Users/x/Documents/Projects/XmlAuthoring/gsheet-to-xml/vendor/symfony/console/Application.php:946
 Symfony\Component\Console\Application->doRunCommand() at /Users/x/Documents/Projects/XmlAuthoring/gsheet-to-xml/vendor/symfony/console/Application.php:248
 Symfony\Component\Console\Application->doRun() at /Users/x/Documents/Projects/XmlAuthoring/gsheet-to-xml/vendor/symfony/console/Application.php:148
 Symfony\Component\Console\Application->run() at /Users/x/Documents/Projects/XmlAuthoring/gsheet-to-xml/bin/gsheet-to-xml.php:14

forikal:gsheet-to-xml [-r|--recursive] [--client-secret-file CLIENT-SECRET-FILE] [--access-token-file ACCESS-TOKEN-FILE] [--force-authenticate] [--] <drive-url>

Aaagh! composer update!!!

$ composer update
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 4 installs, 11 updates, 0 removals
  - Updating google/apiclient-services (v0.61 => v0.63): Downloading (100%)       - Installing symfony/polyfill-ctype (dev-master 9d31bef): Cloning 9d31bef82d from cache
  - Installing symfony/yaml (3.4.x-dev c5010cc): Cloning c5010cc169 from cache
  - Installing symfony/filesystem (3.4.x-dev 8e03ca3): Cloning 8e03ca3fa5 from cache
  - Installing forikal-uk/xml-authoring-library (dev-master 9b6859b): Cloning 9b6859b3d3 from cache
  - Updating google/apiclient dev-master (ceb9e53 => de3bd7a):  Checking out de3bd7a68e
  - Updating guzzlehttp/psr7 dev-master (7fa8852 => 58f6e26):  Checking out 58f6e264ef
  - Updating monolog/monolog 1.x-dev (fd8c787 => 120c434):  Checking out 120c434db9
  - Updating myclabs/deep-copy 1.x-dev (2327345 => 3e01bda):  Checking out 3e01bdad3e
  - Updating phpunit/php-file-iterator dev-master (e20525b => cecbc68):  Checking out cecbc68460
  - Updating phpunit/php-timer dev-master (0753e54 => 9ef9968):  Checking out 9ef9968ba2
  - Updating phpunit/php-token-stream dev-master (ddd3bcc => 711ca0c):  Checking out 711ca0c13c
  - Updating phpunit/phpunit dev-master (2629ff1 => ac4eee5):  Checking out ac4eee55bc
  - Updating sebastian/diff dev-master (2a0d4bd => 366541b):  Checking out 366541b989
  - Updating symfony/debug dev-master (09f5c09 => ef8bd62):  Checking out ef8bd62973
forikal-uk/xml-authoring-library suggests installing forikal-uk/xmlauthor-example-command (To see example how to use AbstractCommand)
Writing lock file
Generating autoload files
$ php bin/gsheet-to-xml.php forikal:gsheet-to-xml --client-secret-file="../../../../APIKeys/OAuth-client_secret_596511451672-flbjqooi8bemek6b96v1oq61jf414oja.apps.googleusercontent.com.json" -v --access-token-file="tmp-access-token" https://docs.google.com/spreadsheets/d/1hdKksm6Xj6SiL3r8paCzlW2gBMRnm445ZBflUL-591M/edit#gid=311423522

In ArgvInput.php line 187:

  [Symfony\Component\Console\Exception\RuntimeException]  
  Too many arguments, expected arguments "drive-url".     

Exception trace:
 Symfony\Component\Console\Input\ArgvInput->parseArgument() at /Users/x/Documents/Projects/XmlAuthoring/gsheet-to-xml/vendor/symfony/console/Input/ArgvInput.php:86
 Symfony\Component\Console\Input\ArgvInput->parse() at /Users/x/Documents/Projects/XmlAuthoring/gsheet-to-xml/vendor/symfony/console/Input/Input.php:55
 Symfony\Component\Console\Input\Input->bind() at /Users/x/Documents/Projects/XmlAuthoring/gsheet-to-xml/vendor/symfony/console/Command/Command.php:210
 Symfony\Component\Console\Command\Command->run() at /Users/x/Documents/Projects/XmlAuthoring/gsheet-to-xml/vendor/symfony/console/Application.php:946
 Symfony\Component\Console\Application->doRunCommand() at /Users/x/Documents/Projects/XmlAuthoring/gsheet-to-xml/vendor/symfony/console/Application.php:248
 Symfony\Component\Console\Application->doRun() at /Users/x/Documents/Projects/XmlAuthoring/gsheet-to-xml/vendor/symfony/console/Application.php:148
 Symfony\Component\Console\Application->run() at /Users/x/Documents/Projects/XmlAuthoring/gsheet-to-xml/bin/gsheet-to-xml.php:14

forikal:gsheet-to-xml [-r|--recursive] [--client-secret-file CLIENT-SECRET-FILE] [--access-token-file ACCESS-TOKEN-FILE] [--force-authenticate] [--] <drive-url>

$ php bin/gsheet-to-xml.php forikal:gsheet-to-xml --client-secret-file="../../../../APIKeys/OAuth-client_secret_596511451672-flbjqooi8bemek6b96v1oq61jf414oja.apps.googleusercontent.com.json" --access-token-file="tmp-access-token" -- https://docs.google.com/spreadsheets/d/1hdKksm6Xj6SiL3r8paCzlW2gBMRnm445ZBflUL-591M/edit#gid=311423522

  Too many arguments, expected arguments "drive-url".  

forikal:gsheet-to-xml [-r|--recursive] [--client-secret-file CLIENT-SECRET-FILE] [--access-token-file ACCESS-TOKEN-FILE] [--force-authenticate] [--] <drive-url>
$ php bin/gsheet-to-xml.php --client-secret-file="../../../../APIKeys/OAuth-client_secret_596511451672-flbjqooi8bemek6b96v1oq61jf414oja.apps.googleusercontent.com.json" --access-token-file="tmp-access-token" -- https://docs.google.com/spreadsheets/d/1hdKksm6Xj6SiL3r8paCzlW2gBMRnm445ZBflUL-591M/edit#gid=311423522
You need to authenticate to your Google account to proceed
Open the following URL in a browser, get an auth code and paste it below:

https://accounts.google.com/o/oauth2/auth?response_type=code&access_type=offline&client_id=596511451672-flbjqooi8bemek6b96v1oq61jf414oja.apps.googleusercontent.com&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&state&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive.readonly%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fspreadsheets.readonly&approval_prompt=auto

Auth code: 4/AACMEbGvyg1gdyEUmLr1Yz5eDVNcLtI7Vo4EjgEIHep6o0StlFItDWU
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Products>
  <Product>
    <Inventory src-sheet="_GoodSheet" src-tab="InventoryTabA" src-sheet-url="https://docs.google.com/spreadsheets/d/1hdKksm6Xj6SiL3r8paCzlW2gBMRnm445ZBflUL-591M/edit#gid=311423522">
      <StockItem>
        <KNumberExists>true</KNumberExists>
        <KNumber>1111111</KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber></AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>baz</Name>
        <Purposes>
          <Purpose>11</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>foo</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
    </Inventory>
  </Product>
  <Product>
    <Inventory src-sheet="_GoodSheet" src-tab="InventoryTabB" src-sheet-url="https://docs.google.com/spreadsheets/d/1hdKksm6Xj6SiL3r8paCzlW2gBMRnm445ZBflUL-591M/edit#gid=311423522">
      <StockItem>
        <KNumberExists>true</KNumberExists>
        <KNumber>5555555</KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber></AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>baz</Name>
        <Purposes>
          <Purpose>5</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>55</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>_GoodSheet &gt; InventoryTabB</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>5</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>55</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
    </Inventory>
  </Product>
</Products>

By jove! It worked!

$ php bin/gsheet-to-xml.php forikal:gsheet-to-xml --client-secret-file="../../../../APIKeys/OAuth-client_secret_596511451672-flbjqooi8bemek6b96v1oq61jf414oja.apps.googleusercontent.com.json" -v --access-token-file="tmp-access-token" https://docs.google.com/spreadsheets/d/1hdKksm6Xj6SiL3r8paCzlW2gBMRnm445ZBflUL-591M/edit#gid=311423522

In ArgvInput.php line 187:

  [Symfony\Component\Console\Exception\RuntimeException]  
  Too many arguments, expected arguments "drive-url".     

Exception trace:
 Symfony\Component\Console\Input\ArgvInput->parseArgument() at /Users/x/Documents/Projects/XmlAuthoring/gsheet-to-xml/vendor/symfony/console/Input/ArgvInput.php:86
 Symfony\Component\Console\Input\ArgvInput->parse() at /Users/x/Documents/Projects/XmlAuthoring/gsheet-to-xml/vendor/symfony/console/Input/Input.php:55
 Symfony\Component\Console\Input\Input->bind() at /Users/x/Documents/Projects/XmlAuthoring/gsheet-to-xml/vendor/symfony/console/Command/Command.php:210
 Symfony\Component\Console\Command\Command->run() at /Users/x/Documents/Projects/XmlAuthoring/gsheet-to-xml/vendor/symfony/console/Application.php:946
 Symfony\Component\Console\Application->doRunCommand() at /Users/x/Documents/Projects/XmlAuthoring/gsheet-to-xml/vendor/symfony/console/Application.php:248
 Symfony\Component\Console\Application->doRun() at /Users/x/Documents/Projects/XmlAuthoring/gsheet-to-xml/vendor/symfony/console/Application.php:148
 Symfony\Component\Console\Application->run() at /Users/x/Documents/Projects/XmlAuthoring/gsheet-to-xml/bin/gsheet-to-xml.php:14

forikal:gsheet-to-xml [-r|--recursive] [--client-secret-file CLIENT-SECRET-FILE] [--access-token-file ACCESS-TOKEN-FILE] [--force-authenticate] [--] <drive-url>
$ php bin/gsheet-to-xml.php --client-secret-file="../../../../APIKeys/OAuth-client_secret_596511451672-flbjqooi8bemek6b96v1oq61jf414oja.apps.googleusercontent.com.json" --access-token-file="tmp-access-tor -- https://drive.google.com/drive/u/0/folders/1pgdgRTKQYfMVc1-Kg29FifW-RebwN2Wq
> ;
> 
$ php bin/gsheet-to-xml.php forikal:gsheet-to-xml --client-secret-file="../../../../APIKeys/OAuth-client_secret_596511451672-flbjqooi8bemek6b96v1oq61jf414oja.apps.googleusercontent.com.json" -v --access-token-file="tmp-access-token" https://docs.google.com/spreadsheets/d/1hdKksm6Xj6SiL3r8paCzlW2gBMRnm445ZBflUL-591M/edit#gid=311423522

In ArgvInput.php line 187:

  [Symfony\Component\Console\Exception\RuntimeException]  
  Too many arguments, expected arguments "drive-url".     

Exception trace:
 Symfony\Component\Console\Input\ArgvInput->parseArgument() at /Users/x/Documents/Projects/XmlAuthoring/gsheet-to-xml/vendor/symfony/console/Input/ArgvInput.php:86
 Symfony\Component\Console\Input\ArgvInput->parse() at /Users/x/Documents/Projects/XmlAuthoring/gsheet-to-xml/vendor/symfony/console/Input/Input.php:55
 Symfony\Component\Console\Input\Input->bind() at /Users/x/Documents/Projects/XmlAuthoring/gsheet-to-xml/vendor/symfony/console/Command/Command.php:210
 Symfony\Component\Console\Command\Command->run() at /Users/x/Documents/Projects/XmlAuthoring/gsheet-to-xml/vendor/symfony/console/Application.php:946
 Symfony\Component\Console\Application->doRunCommand() at /Users/x/Documents/Projects/XmlAuthoring/gsheet-to-xml/vendor/symfony/console/Application.php:248
 Symfony\Component\Console\Application->doRun() at /Users/x/Documents/Projects/XmlAuthoring/gsheet-to-xml/vendor/symfony/console/Application.php:148
 Symfony\Component\Console\Application->run() at /Users/x/Documents/Projects/XmlAuthoring/gsheet-to-xml/bin/gsheet-to-xml.php:14

forikal:gsheet-to-xml [-r|--recursive] [--client-secret-file CLIENT-SECRET-FILE] [--access-token-file ACCESS-TOKEN-FILE] [--force-authenticate] [--] <drive-url>
$ php bin/gsheet-to-xml.php  --client-secret-file="../../../../APIKeys/OAuth-client_secret_596511451672-flbjqooi8bemek6b96v1oq61jf414oja.apps.googleusercontent.com.json" -v --access-token-file="tmp-access-token" https://docs.google.com/spreadsheets/d/1hdKksm6Xj6SiL3r8paCzlW2gBMRnm445ZBflUL-591M/edit#gid=311423522
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Products>
  <Product>
    <Inventory src-sheet="_GoodSheet" src-tab="InventoryTabA" src-sheet-url="https://docs.google.com/spreadsheets/d/1hdKksm6Xj6SiL3r8paCzlW2gBMRnm445ZBflUL-591M/edit#gid=311423522">
      <StockItem>
        <KNumberExists>true</KNumberExists>
        <KNumber>1111111</KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber></AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>baz</Name>
        <Purposes>
          <Purpose>11</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>foo</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
    </Inventory>
  </Product>
  <Product>
    <Inventory src-sheet="_GoodSheet" src-tab="InventoryTabB" src-sheet-url="https://docs.google.com/spreadsheets/d/1hdKksm6Xj6SiL3r8paCzlW2gBMRnm445ZBflUL-591M/edit#gid=311423522">
      <StockItem>
        <KNumberExists>true</KNumberExists>
        <KNumber>5555555</KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber></AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>baz</Name>
        <Purposes>
          <Purpose>5</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>55</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>_GoodSheet &gt; InventoryTabB</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>5</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>55</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
    </Inventory>
  </Product>
</Products>
$ php bin/gsheet-to-xml.php  --client-secret-file="../../../../APIKeys/OAuth-client_secret_596511451672-flbjqooi8bemek6b96v1oq61jf414oja.apps.googleusercontent.com.json" -v --access-token-file="tmp-access-token" \
> https://drive.google.com/drive/u/0/folders/1pgdgRTKQYfMVc1-Kg29FifW-RebwN2Wq
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Products>
  <Product>
    <Inventory src-sheet="TabEndingInUnderscore" src-tab="InventoryTab" src-sheet-url="https://docs.google.com/spreadsheets/d/1Y-rtreSasax15UZ5xQwD48Ou8bVhdQfZOGoq4NxXRLE/">
      <StockItem>
        <KNumberExists>true</KNumberExists>
        <KNumber>1111111</KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber></AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>baz</Name>
        <Purposes>
          <Purpose>11</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>foo</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>foo,bar</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>foo "bar"</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
    </Inventory>
  </Product>
  <Product>
    <Inventory src-sheet="TabEndingInUnderscore" src-tab="AnotherInventoryTab" src-sheet-url="https://docs.google.com/spreadsheets/d/1Y-rtreSasax15UZ5xQwD48Ou8bVhdQfZOGoq4NxXRLE/">
      <StockItem>
        <KNumberExists>true</KNumberExists>
        <KNumber>9999999</KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber></AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>baz</Name>
        <Purposes>
          <Purpose>11</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>11</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>bat</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>11</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>baz,bom</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>11</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>bing "boo"</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>11</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
    </Inventory>
  </Product>
  <Product>
    <Inventory src-sheet="PrivateFile" src-tab="Sheet1" src-sheet-url="https://docs.google.com/spreadsheets/d/12j2CrvWbZUU2_OJiIIr-sRkut2N-Gid4uwA0ZpkVks0/"></Inventory>
  </Product>
  <Product>
    <Inventory src-sheet="_GoodSheet" src-tab="InventoryTabA" src-sheet-url="https://docs.google.com/spreadsheets/d/1hdKksm6Xj6SiL3r8paCzlW2gBMRnm445ZBflUL-591M/">
      <StockItem>
        <KNumberExists>true</KNumberExists>
        <KNumber>1111111</KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber></AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>baz</Name>
        <Purposes>
          <Purpose>11</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>foo</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
    </Inventory>
  </Product>
  <Product>
    <Inventory src-sheet="_GoodSheet" src-tab="InventoryTabB" src-sheet-url="https://docs.google.com/spreadsheets/d/1hdKksm6Xj6SiL3r8paCzlW2gBMRnm445ZBflUL-591M/">
      <StockItem>
        <KNumberExists>true</KNumberExists>
        <KNumber>5555555</KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber></AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>baz</Name>
        <Purposes>
          <Purpose>5</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>55</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>_GoodSheet &gt; InventoryTabB</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>5</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>55</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
    </Inventory>
  </Product>
  <Product>
    <Inventory src-sheet="EmptyRowsSkippedWithoutNotice" src-tab="InventoryTab" src-sheet-url="https://docs.google.com/spreadsheets/d/17BmFwI3yDuHtcGL9uFKkxXHWHD0Mp-TPVp8btG81iQU/">
      <StockItem>
        <KNumberExists>true</KNumberExists>
        <KNumber>1111111</KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber></AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>baz</Name>
        <Purposes>
          <Purpose>11</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>foo</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
    </Inventory>
  </Product>
</Products>
$ php bin/gsheet-to-xml.php  --client-secret-file="../../../../APIKeys/OAuth-client_secret_596511451672-flbjqooi8bemek6b96v1oq61jf414oja.apps.googleusercontent.com.json" -r --access-token-file="tmp-access-token" https://drive.google.com/drive/u/0/folders/1pgdgRTKQYfMVc1-Kg29FifW-RebwN2Wq
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Products>
  <Product>
    <Inventory src-sheet="TabEndingInUnderscore" src-tab="InventoryTab" src-sheet-url="https://docs.google.com/spreadsheets/d/1Y-rtreSasax15UZ5xQwD48Ou8bVhdQfZOGoq4NxXRLE/">
      <StockItem>
        <KNumberExists>true</KNumberExists>
        <KNumber>1111111</KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber></AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>baz</Name>
        <Purposes>
          <Purpose>11</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>foo</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>foo,bar</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>foo "bar"</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
    </Inventory>
  </Product>
  <Product>
    <Inventory src-sheet="TabEndingInUnderscore" src-tab="AnotherInventoryTab" src-sheet-url="https://docs.google.com/spreadsheets/d/1Y-rtreSasax15UZ5xQwD48Ou8bVhdQfZOGoq4NxXRLE/">
      <StockItem>
        <KNumberExists>true</KNumberExists>
        <KNumber>9999999</KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber></AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>baz</Name>
        <Purposes>
          <Purpose>11</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>11</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>bat</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>11</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>baz,bom</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>11</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>bing "boo"</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>11</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
    </Inventory>
  </Product>
  <Product>
    <Inventory src-sheet="PrivateFile" src-tab="Sheet1" src-sheet-url="https://docs.google.com/spreadsheets/d/12j2CrvWbZUU2_OJiIIr-sRkut2N-Gid4uwA0ZpkVks0/"></Inventory>
  </Product>
  <Product>
    <Inventory src-sheet="_GoodSheet" src-tab="InventoryTabA" src-sheet-url="https://docs.google.com/spreadsheets/d/1hdKksm6Xj6SiL3r8paCzlW2gBMRnm445ZBflUL-591M/">
      <StockItem>
        <KNumberExists>true</KNumberExists>
        <KNumber>1111111</KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber></AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>baz</Name>
        <Purposes>
          <Purpose>11</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>foo</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
    </Inventory>
  </Product>
  <Product>
    <Inventory src-sheet="_GoodSheet" src-tab="InventoryTabB" src-sheet-url="https://docs.google.com/spreadsheets/d/1hdKksm6Xj6SiL3r8paCzlW2gBMRnm445ZBflUL-591M/">
      <StockItem>
        <KNumberExists>true</KNumberExists>
        <KNumber>5555555</KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber></AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>baz</Name>
        <Purposes>
          <Purpose>5</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>55</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>_GoodSheet &gt; InventoryTabB</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>5</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>55</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
    </Inventory>
  </Product>
  <Product>
    <Inventory src-sheet="_GoodSheet-Level2" src-tab="InventoryTab" src-sheet-url="https://docs.google.com/spreadsheets/d/1OKIJ1ImBmWYpR0ItNtj7BJpz_cMKfOlDelk0y4yaqPE/">
      <StockItem>
        <KNumberExists>true</KNumberExists>
        <KNumber>1111111</KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber></AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>baz</Name>
        <Purposes>
          <Purpose>11</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>_GoodSheet-Level2</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
    </Inventory>
  </Product>
  <Product>
    <Inventory src-sheet="_GoodSheet-Level3" src-tab="InventoryTab" src-sheet-url="https://docs.google.com/spreadsheets/d/1Xdp4gbjTovVldrqJ5jkISgOUXrJMAH20WGC3ulK4ycg/">
      <StockItem>
        <KNumberExists>true</KNumberExists>
        <KNumber>1111111</KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber></AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>baz</Name>
        <Purposes>
          <Purpose>11</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>_GoodSheet-Level3</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
    </Inventory>
  </Product>
  <Product>
    <Inventory src-sheet="TabEndingInUnderscore-Level3" src-tab="InventoryTab" src-sheet-url="https://docs.google.com/spreadsheets/d/1gjrOhz9LNbaXXnYbc2PeGXTnDSp2jeptoxNvrrAEl8c/">
      <StockItem>
        <KNumberExists>true</KNumberExists>
        <KNumber>1111111</KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber></AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>baz</Name>
        <Purposes>
          <Purpose>11</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>TabEndingInUnderscore-Level3</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
    </Inventory>
  </Product>
  <Product>
    <Inventory src-sheet="EmptyRowsSkippedWithoutNotice-Level3" src-tab="InventoryTab" src-sheet-url="https://docs.google.com/spreadsheets/d/1TsTTE9G7RYq8EcYhTm169NZyzy4SwgXWP0Hfebo3rfY/">
      <StockItem>
        <KNumberExists>true</KNumberExists>
        <KNumber>1111111</KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber></AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>baz</Name>
        <Purposes>
          <Purpose>11</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>EmptyRowsSkippedWithoutNotice-Level3</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
    </Inventory>
  </Product>
  <Product>
    <Inventory src-sheet="EmptyRowsSkippedWithoutNotice" src-tab="InventoryTab" src-sheet-url="https://docs.google.com/spreadsheets/d/17BmFwI3yDuHtcGL9uFKkxXHWHD0Mp-TPVp8btG81iQU/">
      <StockItem>
        <KNumberExists>true</KNumberExists>
        <KNumber>1111111</KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber></AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>baz</Name>
        <Purposes>
          <Purpose>11</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>foo</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
    </Inventory>
  </Product>
</Products>

So, this is running the command on a Google Drive Folder which contains subfolders of gsheets to write out to Xml.

$ php bin/gsheet-to-xml.php  --client-secret-file="../../../../APIKeys/OAuth-client_secret_596511451672-flbjqooi8bemek6b96v1oq61jf414oja.apps.googleusercontent.com.json" -r --access-token-file="tmp-access-token" https://drive.google.com/drive/u/0/folders/1pgdgRTKQYfMVc1-Kg29FifW-RebwN2Wq
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Products>
  <Product>
    <Inventory src-sheet="_GoodSheet" src-tab="InventoryTabA" src-sheet-url="https://docs.google.com/spreadsheets/d/1hdKksm6Xj6SiL3r8paCzlW2gBMRnm445ZBflUL-591M/">
      <StockItem>
        <KNumberExists>true</KNumberExists>
        <KNumber>1111111</KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber></AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>baz</Name>
        <Purposes>
          <Purpose>11</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>foo</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
    </Inventory>
  </Product>
  <Product>
    <Inventory src-sheet="_GoodSheet" src-tab="InventoryTabB" src-sheet-url="https://docs.google.com/spreadsheets/d/1hdKksm6Xj6SiL3r8paCzlW2gBMRnm445ZBflUL-591M/">
      <StockItem>
        <KNumberExists>true</KNumberExists>
        <KNumber>5555555</KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber></AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>baz</Name>
        <Purposes>
          <Purpose>5</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>55</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>_GoodSheet &gt; InventoryTabB</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>5</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>55</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
    </Inventory>
  </Product>
  <Product>
    <Inventory src-sheet="TabEndingInUnderscore" src-tab="InventoryTab" src-sheet-url="https://docs.google.com/spreadsheets/d/1Y-rtreSasax15UZ5xQwD48Ou8bVhdQfZOGoq4NxXRLE/">
      <StockItem>
        <KNumberExists>true</KNumberExists>
        <KNumber>1111111</KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber></AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>baz</Name>
        <Purposes>
          <Purpose>11</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>foo</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>foo,bar</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>foo "bar"</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
    </Inventory>
  </Product>
  <Product>
    <Inventory src-sheet="TabEndingInUnderscore" src-tab="AnotherInventoryTab" src-sheet-url="https://docs.google.com/spreadsheets/d/1Y-rtreSasax15UZ5xQwD48Ou8bVhdQfZOGoq4NxXRLE/">
      <StockItem>
        <KNumberExists>true</KNumberExists>
        <KNumber>9999999</KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber></AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>baz</Name>
        <Purposes>
          <Purpose>11</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>11</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>bat</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>11</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>baz,bom</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>11</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>bing "boo"</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>11</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
    </Inventory>
  </Product>
  <Product>
    <Inventory src-sheet="PrivateFile" src-tab="Sheet1" src-sheet-url="https://docs.google.com/spreadsheets/d/12j2CrvWbZUU2_OJiIIr-sRkut2N-Gid4uwA0ZpkVks0/"></Inventory>
  </Product>
  <Product>
    <Inventory src-sheet="_GoodSheet-Level2" src-tab="InventoryTab" src-sheet-url="https://docs.google.com/spreadsheets/d/1OKIJ1ImBmWYpR0ItNtj7BJpz_cMKfOlDelk0y4yaqPE/">
      <StockItem>
        <KNumberExists>true</KNumberExists>
        <KNumber>1111111</KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber></AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>baz</Name>
        <Purposes>
          <Purpose>11</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>_GoodSheet-Level2</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
    </Inventory>
  </Product>
  <Product>
    <Inventory src-sheet="_GoodSheet-Level3" src-tab="InventoryTab" src-sheet-url="https://docs.google.com/spreadsheets/d/1Xdp4gbjTovVldrqJ5jkISgOUXrJMAH20WGC3ulK4ycg/">
      <StockItem>
        <KNumberExists>true</KNumberExists>
        <KNumber>1111111</KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber></AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>baz</Name>
        <Purposes>
          <Purpose>11</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>_GoodSheet-Level3</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
    </Inventory>
  </Product>
  <Product>
    <Inventory src-sheet="EmptyRowsSkippedWithoutNotice-Level3" src-tab="InventoryTab" src-sheet-url="https://docs.google.com/spreadsheets/d/1TsTTE9G7RYq8EcYhTm169NZyzy4SwgXWP0Hfebo3rfY/">
      <StockItem>
        <KNumberExists>true</KNumberExists>
        <KNumber>1111111</KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber></AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>baz</Name>
        <Purposes>
          <Purpose>11</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>EmptyRowsSkippedWithoutNotice-Level3</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
    </Inventory>
  </Product>
  <Product>
    <Inventory src-sheet="TabEndingInUnderscore-Level3" src-tab="InventoryTab" src-sheet-url="https://docs.google.com/spreadsheets/d/1gjrOhz9LNbaXXnYbc2PeGXTnDSp2jeptoxNvrrAEl8c/">
      <StockItem>
        <KNumberExists>true</KNumberExists>
        <KNumber>1111111</KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber></AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>baz</Name>
        <Purposes>
          <Purpose>11</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>TabEndingInUnderscore-Level3</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
    </Inventory>
  </Product>
  <Product>
    <Inventory src-sheet="EmptyRowsSkippedWithoutNotice" src-tab="InventoryTab" src-sheet-url="https://docs.google.com/spreadsheets/d/17BmFwI3yDuHtcGL9uFKkxXHWHD0Mp-TPVp8btG81iQU/">
      <StockItem>
        <KNumberExists>true</KNumberExists>
        <KNumber>1111111</KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber></AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>baz</Name>
        <Purposes>
          <Purpose>11</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>foo</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
    </Inventory>
  </Product>
</Products>
forikal-uk commented 6 years ago

I have a bit of time to check the recursive aspect with a little more careful methodology.

The final command, in the comment above, was run against the following Google Drive folder:

screen shot 2018-06-23 at 17 02 09

with FolderLevel2 containing

screen shot 2018-06-23 at 17 02 22

with FolderLevel3 containing

screen shot 2018-06-23 at 17 02 28

Which has the following structure of folders, files and tabs:

FolderLevel2/
  FolderLevel2/
    _GoodSheet-Level3
      InventoryTab
      ignoreMe_
    EmptyRowsSkippedWithoutNotice-Level3
      InventoryTab
    FileEndingInUnderscore-Level3_
      InventoryTab
    NotAGoogleSheet-Level3.xlsx
    TabEndingInUnderscore-Level3
      InventoryTab
      ignoreMe_
  _GoodSheet-Level2
    InventoryTab
    ignoreMe_
_GoodSheet
  InventoryTabA
  InventoryTabB
  ignoreMe_
EmptyRowsSkippedWithoutNotice
  InventoryTab
FileEndingInUnderscore_
  InventoryTab
NotAGoogleSheet.xlsx
PrivateFile
TabEndingInUnderScore
  InventoryTab
  AnotherInventoryTab
  ignoreMe_

So, let's rerun that final command on the folder.

$ pwd
/Users/x/Documents/Projects/XmlAuthoring
$ cd gsheet-to-xml/
$ php bin/gsheet-to-xml.php  --client-secret-file="../../../../APIKeys/OAuth-client_secret_596511451672-flbjqooi8bemek6b96v1oq61jf414oja.apps.googleusercontent.com.json" -r --access-token-file="tmp-access-token" https://drive.google.com/drive/u/0/folders/1pgdgRTKQYfMVc1-Kg29FifW-RebwN2Wq

Which outputs:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Products>
  <Product>
    <Inventory src-sheet="_GoodSheet" src-tab="InventoryTabA" src-sheet-url="https://docs.google.com/spreadsheets/d/1hdKksm6Xj6SiL3r8paCzlW2gBMRnm445ZBflUL-591M/">
      <StockItem>
        <KNumberExists>true</KNumberExists>
        <KNumber>1111111</KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber></AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>baz</Name>
        <Purposes>
          <Purpose>11</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>foo</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
    </Inventory>
  </Product>
  <Product>
    <Inventory src-sheet="_GoodSheet" src-tab="InventoryTabB" src-sheet-url="https://docs.google.com/spreadsheets/d/1hdKksm6Xj6SiL3r8paCzlW2gBMRnm445ZBflUL-591M/">
      <StockItem>
        <KNumberExists>true</KNumberExists>
        <KNumber>5555555</KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber></AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>baz</Name>
        <Purposes>
          <Purpose>5</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>55</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>_GoodSheet &gt; InventoryTabB</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>5</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>55</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
    </Inventory>
  </Product>
  <Product>
    <Inventory src-sheet="TabEndingInUnderscore" src-tab="InventoryTab" src-sheet-url="https://docs.google.com/spreadsheets/d/1Y-rtreSasax15UZ5xQwD48Ou8bVhdQfZOGoq4NxXRLE/">
      <StockItem>
        <KNumberExists>true</KNumberExists>
        <KNumber>1111111</KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber></AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>baz</Name>
        <Purposes>
          <Purpose>11</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>foo</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>foo,bar</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>foo "bar"</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
    </Inventory>
  </Product>
  <Product>
    <Inventory src-sheet="TabEndingInUnderscore" src-tab="AnotherInventoryTab" src-sheet-url="https://docs.google.com/spreadsheets/d/1Y-rtreSasax15UZ5xQwD48Ou8bVhdQfZOGoq4NxXRLE/">
      <StockItem>
        <KNumberExists>true</KNumberExists>
        <KNumber>9999999</KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber></AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>baz</Name>
        <Purposes>
          <Purpose>11</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>11</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>bat</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>11</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>baz,bom</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>11</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>bing "boo"</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>11</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
    </Inventory>
  </Product>
  <Product>
    <Inventory src-sheet="PrivateFile" src-tab="Sheet1" src-sheet-url="https://docs.google.com/spreadsheets/d/12j2CrvWbZUU2_OJiIIr-sRkut2N-Gid4uwA0ZpkVks0/"></Inventory>
  </Product>
  <Product>
    <Inventory src-sheet="_GoodSheet-Level2" src-tab="InventoryTab" src-sheet-url="https://docs.google.com/spreadsheets/d/1OKIJ1ImBmWYpR0ItNtj7BJpz_cMKfOlDelk0y4yaqPE/">
      <StockItem>
        <KNumberExists>true</KNumberExists>
        <KNumber>1111111</KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber></AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>baz</Name>
        <Purposes>
          <Purpose>11</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>_GoodSheet-Level2</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
    </Inventory>
  </Product>
  <Product>
    <Inventory src-sheet="_GoodSheet-Level3" src-tab="InventoryTab" src-sheet-url="https://docs.google.com/spreadsheets/d/1Xdp4gbjTovVldrqJ5jkISgOUXrJMAH20WGC3ulK4ycg/">
      <StockItem>
        <KNumberExists>true</KNumberExists>
        <KNumber>1111111</KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber></AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>baz</Name>
        <Purposes>
          <Purpose>11</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>_GoodSheet-Level3</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
    </Inventory>
  </Product>
  <Product>
    <Inventory src-sheet="EmptyRowsSkippedWithoutNotice-Level3" src-tab="InventoryTab" src-sheet-url="https://docs.google.com/spreadsheets/d/1TsTTE9G7RYq8EcYhTm169NZyzy4SwgXWP0Hfebo3rfY/">
      <StockItem>
        <KNumberExists>true</KNumberExists>
        <KNumber>1111111</KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber></AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>baz</Name>
        <Purposes>
          <Purpose>11</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>EmptyRowsSkippedWithoutNotice-Level3</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
    </Inventory>
  </Product>
  <Product>
    <Inventory src-sheet="TabEndingInUnderscore-Level3" src-tab="InventoryTab" src-sheet-url="https://docs.google.com/spreadsheets/d/1gjrOhz9LNbaXXnYbc2PeGXTnDSp2jeptoxNvrrAEl8c/">
      <StockItem>
        <KNumberExists>true</KNumberExists>
        <KNumber>1111111</KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber></AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>baz</Name>
        <Purposes>
          <Purpose>11</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>TabEndingInUnderscore-Level3</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
    </Inventory>
  </Product>
  <Product>
    <Inventory src-sheet="EmptyRowsSkippedWithoutNotice" src-tab="InventoryTab" src-sheet-url="https://docs.google.com/spreadsheets/d/17BmFwI3yDuHtcGL9uFKkxXHWHD0Mp-TPVp8btG81iQU/">
      <StockItem>
        <KNumberExists>true</KNumberExists>
        <KNumber>1111111</KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber></AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>baz</Name>
        <Purposes>
          <Purpose>11</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
      <StockItem>
        <KNumberExists>false</KNumberExists>
        <KNumber></KNumber>
        <AdditionalKNumbers></AdditionalKNumbers>
        <AlternativeNumber>foo</AlternativeNumber>
        <InventoryContainerID></InventoryContainerID>
        <Name>bar</Name>
        <Purposes>
          <Purpose>2</Purpose>
        </Purposes>
        <PurposeOther></PurposeOther>
        <InventoryQuantity>99</InventoryQuantity>
        <HandlingStatus></HandlingStatus>
        <SupplierRegistrationNumber></SupplierRegistrationNumber>
      </StockItem>
    </Inventory>
  </Product>
</Products>

So, let's check the results.

Is the Xml well-formed?

Try opening it in Oxygen Xml Editor and look for the green square:

screen shot 2018-06-23 at 17 29 56

Yep. Nice little green square all present and correct.

Use Oxygen's Find All to search for the <Inventory element to give us:

<Inventory src-sheet="_GoodSheet-Level2" src-tab="InventoryTab" src-sheet-url="https://d...
<Inventory src-sheet="_GoodSheet-Level3" src-tab="InventoryTab" src-sheet-url="https://d...
<Inventory src-sheet="_GoodSheet" src-tab="InventoryTabA" src-sheet-url="https://docs.go...
<Inventory src-sheet="_GoodSheet" src-tab="InventoryTabB" src-sheet-url="https://docs.go...
<Inventory src-sheet="EmptyRowsSkippedWithoutNotice-Level3" src-tab="InventoryTab" src-s...
<Inventory src-sheet="EmptyRowsSkippedWithoutNotice" src-tab="InventoryTab" src-sheet-ur...
<Inventory src-sheet="PrivateFile" src-tab="Sheet1" src-sheet-url="https://docs.google.c...
<Inventory src-sheet="TabEndingInUnderscore-Level3" src-tab="InventoryTab" src-sheet-url...
<Inventory src-sheet="TabEndingInUnderscore" src-tab="AnotherInventoryTab" src-sheet-url...
<Inventory src-sheet="TabEndingInUnderscore" src-tab="InventoryTab" src-sheet-url="https...

Which is pruned to:

Compare that to what we have in the folder

FolderLevel2/
  FolderLevel2/
    _GoodSheet-Level3
      InventoryTab ** - Assert In Xml - Pass **
      ignoreMe_ ** - Assert Skipped - Pass **
    EmptyRowsSkippedWithoutNotice-Level3
      InventoryTab ** - Assert In Xml - Pass **
    FileEndingInUnderscore-Level3_
      InventoryTab ** - Assert Skipped - Pass **
    NotAGoogleSheet-Level3.xlsx ** - Assert Skipped - Pass **
    TabEndingInUnderscore-Level3
      InventoryTab ** - Assert In Xml - Pass **
      ignoreMe_ ** - Assert Skipped - Pass **
  _GoodSheet-Level2
    InventoryTab ** - Assert In Xml - Pass **
    ignoreMe_ ** - Assert Skipped - Pass **
_GoodSheet
  InventoryTabA ** - Assert In Xml - Pass **
  InventoryTabB ** - Assert In Xml - Pass **
  ignoreMe_ ** - Assert Skipped - Pass **
EmptyRowsSkippedWithoutNotice
  InventoryTab ** - Assert In Xml - Pass **
FileEndingInUnderscore_ ** - Assert Skipped - Pass **
  InventoryTab ** - Assert Skipped - Pass **
NotAGoogleSheet.xlsx ** - Assert Skipped - Pass **
PrivateFile
  Sheet1 ** - Assert In Xml (when accessed via owner account) - Pass **
TabEndingInUnderScore
  InventoryTab ** - Assert In Xml - Pass **
  AnotherInventoryTab ** - Assert In Xml - Pass **
  ignoreMe_ ** - Assert Skipped - Pass **

So, all assertions Pass.

So, I can categorically say that the recursive and skip features pass our test and work OK.

Nice!

forikal-uk commented 6 years ago

To do

At some point we'll have to write a test to automate the procedure outlined in the comment above.