我正在使用Consolibyte提供的优秀Quickbooks PHP Dev Kit,我正在将销售代表导入到数据库中。下面的代码是我对请求xml的代码。 Quickbooks文件有超过3000个销售代表,响应xml无效。我知道我可以使用metaData来获取计数并使用MaxReturned来获取有限的记录。不确定迭代器中是否存在?
我将xml传递给mssql数据库并在那里进行解析。问题是当xml无效时,它会导致sqlserver在查询运行时挂起 - 所以我需要以某种方式验证xml,然后再将其传递给sql。
任何帮助都将不胜感激。
$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;
----使用以下代码更新--- @keith - 感谢您抽出宝贵时间作出回应。以下是我的请求/响应函数
//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;
}
这是我在传递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
- 所以发生的事情是从quickbooks返回的响应没有很好的形成xml - 它最终被切断了。我猜是因为xml中的数据太多了。因此,当它被传递给sql存储过程时 - 它会锁定插入/更新,因为它没有很好地形成xml。所以我希望以某种方式验证xml并能够检索小块。
我使用SalesRepQueryRq中的metaData获得了总记录数。如果我在请求中将MaxRuturned设置为50,那么一切都可以正常运行。
这是来自网络连接器的信息
描述: QBWC1042:ReceiveResponseXML失败 错误消息:操作已超时请参阅QWCLog以获取更多详细信息。记得打开登录。
我使用了QUICKBOOKS_LOG_DEVELOP,最后一行是 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
这是xml结束的方式
答案 0 :(得分:1)
- 所以发生的事情是从quickbooks返回的响应没有很好地形成xml
不,这不是正在发生的事情。 XML QuickBooks返回完全没问题。
我猜是因为xml中有太多数据。
您的问题与有关,因为存在大量数据......但 实际上与QuickBooks中的无效XML无关。
因此,当它被传递给sql存储过程时 - 它会锁定插入/更新,因为它没有很好地形成xml。
不,这不是事情爆发的原因。
所以我希望以某种方式验证xml并能够检索小块。
无需验证XML。返回的XML QuickBooks完全有效。
然而,将结果分解为较小的块 是个好主意。
如果我在请求中将MaxRuturned设置为50,那么一切都可以正常运行。
这是一个很大的暗示。它与无效的XML无关......您的问题与在XML中返回了多少结果有关。
描述:QBWC1042:ReceiveResponseXML失败错误消息:操作已超时请参阅QWCLog以获取更多详细信息。记得打开登录。
现在我们处于重要位置!
这是关键:
不幸的是,你没有发布Web连接器日志文件的其余部分,所以我们没有得到其他有用的信息。
Web连接器具有硬编码,2分钟超时。如果您已发布其余日志,我认为我们会看到Web连接器日志中的时间戳显示Web连接器开始向您发送数据与连接关闭以及错误显示之间有2分钟的差距在日志中。
我敢打赌,如果您对代码进行基准测试,您还会发现代码需要2分钟以上才能处理来自QuickBooks的响应。
我使用了QUICKBOOKS_LOG_DEVELOP,最后一行是receiveResponseXML()
我假设你是从quickbooks_log
SQL表中提取的。我打赌如果你检查了你的列类型,你会发现列上的最大长度只是切断了XML,因为它无法将所有数据都放入列中。
不确定是否存在迭代器?
此时您可以查看文档:
并且很容易确定SalesRepQueryRq
不支持迭代器。
但是,您可以通过查询数据块伪造迭代器。例如,使用NameRangeFilter
:
<NameRangeFilter> <!-- optional -->
<FromName >STRTYPE</FromName> <!-- optional -->
<ToName >STRTYPE</ToName> <!-- optional -->
</NameRangeFilter>
检索从Aa
到Az
的所有内容。然后对Ba
到Bz
执行相同的操作。然后是Ca
到Cz
等等。您最终会获得所有数据,但是会以较小的块数获得。
TLDR:查看其余日志。下次,从日志中发布整个相关部分。您的代码很可能花费的时间太长,超出Web连接器2分钟超时。
答案 1 :(得分:0)
嗯,这适用于SQL-Server:
declare @xml xml=
'<?xml version="1.0" encoding="utf-8"?>
<?qbxml version="3"?>
<QBXML>
<QBXMLMsgsRq onError="stopOnError">
<SalesRepQueryRq>
<ActiveStatus>ActiveOnly</ActiveStatus>
<FromModifiedDate>2017-01-27T08:30:15</FromModifiedDate>
<IncludeRetElement>ListID</IncludeRetElement>
<IncludeRetElement>SalesRepEntityRef</IncludeRetElement>
</SalesRepQueryRq>
</QBXMLMsgsRq>
</QBXML>';
select @xml;
你是如何将它传递给MS-Sql-Server的?这是一个related answer,它解释了编码和参数类型可能出现的麻烦来源。
提示:让SQL-Server中的参数为NVARCHAR(MAX)
类型。我开始在没有<? ... ?>
(处理指令)的情况下传递XML。关闭第一行,让这从<QBXML>
开始。并确保填入. $ last .
的日期为ISO8601(2017-01-27T08:30:15
)。
在SQL Server中,您可以将传入的字符串分配给XML类型的变量。