I am using the excellent Quickbooks PHP Dev Kit provided by Consolibyte and I am doing the sales rep import into a database. The code below is what I have for the request xml. The Quickbooks file has over 3000 sales reps and response xml is invalid. I know I can use the metaData to get the count and use MaxReturned to get limited records. by not sure if there in iterator?
I am passing the xml to mssql database and parsing it there. The problem is when the xml is invalid, it causes the sqlserver to hang as query is running - so I need to somehow the validate the xml before passing it on to sql.
Any help would be appreciated.
$xml = '<?xml version="1.0" encoding="utf-8"?>
<?qbxml version="' . $version . '"?>
<QBXML>
<QBXMLMsgsRq onError="stopOnError">
<SalesRepQueryRq>
<ActiveStatus>ActiveOnly</ActiveStatus>
<FromModifiedDate>' . $last . '</FromModifiedDate>
<IncludeRetElement>ListID</IncludeRetElement>
<IncludeRetElement>SalesRepEntityRef</IncludeRetElement>
</SalesRepQueryRq>
</QBXMLMsgsRq>
</QBXML>';
return $xml;
----updated with code below--- @keith - thanks for taking the time to respond. below is what I have for request/response functions
//sales rep list import request
function _quickbooks_salesrep_import_request($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $version, $locale)
{
$last = _quickbooks_get_last_run($user, $action); //get last run time
_quickbooks_set_last_run($user, $action); //set current run
// Build the request
$xml = '<?xml version="1.0" encoding="utf-8"?>
<?qbxml version="' . $version . '"?>
<QBXML>
<QBXMLMsgsRq onError="stopOnError">
<SalesRepQueryRq>
<ActiveStatus>ActiveOnly</ActiveStatus>
<FromModifiedDate>' . $last . '</FromModifiedDate>
<IncludeRetElement>ListID</IncludeRetElement>
<IncludeRetElement>SalesRepEntityRef</IncludeRetElement>
</SalesRepQueryRq>
</QBXMLMsgsRq>
</QBXML>';
return $xml;
}
//sales rep list import response
function _quickbooks_salesrep_import_response ($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $xml, $idents)
{
global $conn;
$sql = '{call dbo.spQBAddUpdateSalesRep (?)}';
$params = array($xml);
$stmt = dbQuery($sql,$conn,$params);
dbCloseQuery($stmt);
//QuickBooks_Utilities::log(QB_QUICKBOOKS_DSN, 'rep xml - ' . $xml);
return true;
}
Here's what I have in the stored procedure where I pass the xml
@strXML XML --- this is passed as parameter
BEGIN TRY
BEGIN TRANSACTION
UPDATE dbo.qb_salesrep SET
TimeCreated = SUB.TimeCreated
,TimeModified = SUB.TimeModified
,EditSequence = SUB.EditSequence
,Initial = SUB.Initial
,IsActive = SUB.IsActive
,SalesRepEntityRef_ListID = SUB.SalesRepEntityRef_ListID
,SalesRepEntityRef_FullName = SUB.SalesRepEntityRef_FullName
FROM
(SELECT
ListID = x.c.value('ListID[1]','VARCHAR(36)')
,TimeCreated = x.c.value('TimeCreated[1]','DATETIME')
,TimeModified = x.c.value('TimeModified[1]','DATETIME')
,EditSequence = x.c.value('EditSequence[1]','VARCHAR(16)')
,Initial = x.c.value('Initial[1]','VARCHAR(5)')
,IsActive = x.c.value('IsActive[1]','BIT')
,SalesRepEntityRef_ListID = x.c.value('SalesRepEntityRef[1]/ListID[1]','VARCHAR(36)')
,SalesRepEntityRef_FullName = x.c.value('SalesRepEntityRef[1]/FullName[1]','VARCHAR(41)')
FROM
@strXML.nodes('QBXML/QBXMLMsgsRs/SalesRepQueryRs/SalesRepRet') x(c)) AS SUB
WHERE
dbo.qb_salesrep.ListID = SUB.ListID
INSERT INTO dbo.qb_salesrep (
ListID
,TimeCreated
,TimeModified
,EditSequence
,Initial
,IsActive
,SalesRepEntityRef_ListID
,SalesRepEntityRef_FullName
)
SELECT
ListID = x.c.value('ListID[1]','VARCHAR(36)')
,TimeCreated = x.c.value('TimeCreated[1]','DATETIME')
,TimeModified = x.c.value('TimeModified[1]','DATETIME')
,EditSequence = x.c.value('EditSequence[1]','VARCHAR(16)')
,Initial = x.c.value('Initial[1]','VARCHAR(5)')
,IsActive = x.c.value('IsActive[1]','BIT')
,SalesRepEntityRef_ListID = x.c.value('SalesRepEntityRef[1]/ListID[1]','VARCHAR(36)')
,SalesRepEntityRef_FullName = x.c.value('SalesRepEntityRef[1]/FullName[1]','VARCHAR(41)')
FROM
@strXML.nodes('QBXML/QBXMLMsgsRs/SalesRepQueryRs/SalesRepRet') x(c)
WHERE
x.c.value('ListID[1]','VARCHAR(36)') NOT IN (SELECT ListID FROM dbo.qb_salesrep)
COMMIT TRANSACTION
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION
RETURN
END CATCH
--so whats happening is response returned from quickbooks is not well formed xml - its cut off in the end . I am guessing because of too much data in xml. So when this is passed over to sql stored procedure - it locks up on insert/update because its not well formed xml. So I was hoping to validate xml somehow and be able to retrieve small chunks.
I got the total record count using the metaData in SalesRepQueryRq. If i set MaxReturned to 50 in request, everything works without an issue.
Here's the message from web connector
Description: QBWC1042: ReceiveResponseXML failed Error message: The operation has timed out See QWCLog for more details. Remember to turn logging on.
I used QUICKBOOKS_LOG_DEVELOP and the last lines are receiveResponseXML()
Incoming XML response: <?xml version="1.0" ?> <QBXML> <QBXMLMsgsRs> <SalesRepQueryRs requestID="6" statusCode="0" statusSeverity="Info" statusMessage="Status OK"> <SalesRepRet> <ListID>31A0000-1193779738</ListID> <SalesRepEntityRef> <ListID>60F0002-1193780133</ListID> <FullName>*BRANDT'S</FullName> </SalesRepEntityRef> </SalesRepRet>
.....
.....
</Sales
This is how the xml ends