Some of the poor performance is down to your xpath and the use of both .vaue and .query.
This is somewhat quicker. (Though it is never going to be as quick as using a table variable parameter)
ALTER PROCEDURE [dbo].[UpdateTableViaXML3]
(
@data xml
)
AS
SET NOCOUNT ON
DECLARE @ErrMsg varchar(100),
@ErrNo int,
@ErrSeverity varchar(100)
BEGIN TRY
UPDATE PODetailTest
SET OrderQty = T.PO.value('(OrderQty/text())[1]', 'smallint') ,
UnitPrice = T.PO.value('(UnitPrice/text())[1]','money')
FROM @data.nodes('Root/PurchaseOrderDetail') AS T(PO)
WHERE T.PO.value('(PurchaseOrderDetailID/text())[1]','int') = PODetailTest.PurchaseOrderDetailID
END TRY
BEGIN CATCH
SELECT @ErrMsg = 'An error occurred in stored procedure ' + ERROR_PROCEDURE() + ': ' + ERROR_MESSAGE(),
@ErrSeverity = ERROR_SEVERITY()
RAISERROR(@ErrMsg, @ErrSeverity, 1)
END CATCH
GO