#!perl -Tw
use strict;
use DBI;
use Win32::OLE;
use XML::Generator;
my $list_id = '40000-1022206382';
my $request_id = 1;
# Be paranoid about error messages
Win32::OLE->Option(Warn => 3);
# Start the Processor
my $connection = Win32::OLE->new('QBXMLRP.RequestProcessor');
# Name your program
$connection->OpenConnection("qbtmr", "Timer Import");
# Open the currently open QuickBooks file, in "DoNotCare" mode.
my $ticket = $connection->BeginSession('', 2);
my $dbh = DBI->connect("DBI:CSV:")
or die "Cannot connect: " . $DBI::errstr;
my $sth = $dbh->prepare("SELECT Customer, Service, Duration, Date FROM
+ data")
or die "Cannot prepare: " . $dbh->errstr();
$sth->execute() or die "Cannot execute: " . $sth->errstr();
$sth->bind_columns(\my($customer, $service, $duration, $date));
my @items;
while ($sth->fetch) {
push (@items, {
date => $date,
customer=> $customer,
service => $service,
duration=> $duration
});
}
$sth->finish();
$dbh->disconnect();
foreach my $item (@items) {
my $gen = XML::Generator->new(
escape => 'always',
conformance => 'strict',
pretty => 2,
dtd => [ 'QBXML', 'PUBLIC', "'-//INTUIT//DTD", "
+QBXML QBD 1.1//EN'"],
version => '1.0'
);
my $xml = $gen->xmldecl;
$xml = $gen->QBXML(
$gen->QBXMLMsgsRq(
{'onError' => 'stopOnError'},
$gen->TimeTrackingAddRq({requestID => 1},
$gen->TimeTrackingAdd(
$gen->TxnDate($item->{date}),
$gen->EntityRef(
$gen->ListID($list_id)
),
$gen->CustomerRef(
$gen->FullName($item->{customer})
),
$gen->ItemServiceRef(
$gen->FullName($item->{service})
),
$gen->Duration($item->{duration}),
),
),
),
);
my $xml_req = $gen->xml($xml);
$request_id++;
open (CHANGE, ">change.xml") or die "Can't open change.xml for wri
+ting - $!";
print CHANGE $xml_req;
close CHANGE;
my $xml_res= $connection->ProcessRequest($ticket, $xml_req);
}
# Gracefully end everything
$connection->EndSession($ticket);
$connection->CloseConnection;
Contents of change.xml. It is precisely the same as actual.xml and reinvent.xml. I've verified this using "Beyond Compare" and then again after using diotalevi's regex.:
<?xml version="1.0" standalone="no"?>
<!DOCTYPE QBXML PUBLIC '-//INTUIT//DTD QBXML QBD 1.1//EN'>
<QBXML>
<QBXMLMsgsRq onError="stopOnError">
<TimeTrackingAddRq requestID="1">
<TimeTrackingAdd>
<TxnDate>2003-01-01</TxnDate>
<EntityRef>
<ListID>40000-1022206382</ListID>
</EntityRef>
<CustomerRef>
<FullName>Cahoots Sports Bar & Grill</FullName>
</CustomerRef>
<ItemServiceRef>
<FullName>AP</FullName>
</ItemServiceRef>
<Duration>PT00H01M</Duration>
</TimeTrackingAdd>
</TimeTrackingAddRq>
</QBXMLMsgsRq>
</QBXML>
Same exact error message. But your suggestion got me thinking. So I modified the program in this post by moving all the Win32 connection crap (between the request_id and the start of the dbi stuff) to right before the foreach loop ( my goal to make all the dbi stuff happen first and the QB stuff happen second) and ran it again. XML came out exact, again. And the error message still happened. |