2016-09-05 2 views
3

Есть следующая конфигурация: Delphi XE7 MS SQL Server 2008 Подключение к серверу SQL с FireDACNVARCHAR (макс) ошибки синтаксического анализа XML

Я с помощью хранимых процедур для получения таблиц со всеми детализирующих записей от SQL-сервера в формате XML, преобразованного в nvarchar (max). Вот пример:

CREATE PROCEDURE uspUsers_GetAll 
    @ReturnData nvarchar(max) = NULL OUTPUT 
AS 
BEGIN 
    SET NOCOUNT ON; 
    SET @ReturnData = CONVERT(nvarchar(max), 
       (SELECT *, ( SELECT UserID, RightType 
           FROM UserRights 
           WHERE UserRights.UserID = Users.ID 
           FOR XML RAW('UserRight'), 
           ROOT('UserRights'), ELEMENTS, TYPE) 
       FROM Users 
       FOR XML RAW('Users'), 
       ROOT('root') , ELEMENTS)); 
END; 

На стороне Delphi я звоню эту хранимую процедуру, загрузите его в XML, и я пытаюсь разобрать его, чтобы превратить его в локальный список объектов. Что-то вроде этого:

procedure TUsers.LoadFromDatabase; 
var 
    usersXML: String; 
    xmlDoc: IXMLDocument; 
    workNode: IXMLNode; 
    userObj: TUser; 
begin 
    Items.Clear; 

    with dmApp.uspWork do 
    begin 
    Close; 
    if Prepared then 
     Prepared := False; 
    Params.Clear; 
    StoredProcName := 'uspUsers_GetAll'; 
    Prepare; 
    ExecProc; 
    end; 

    usersXML := dmApp.uspWork.Params.ParamByName('@ReturnData').Value; 
    xmlDoc := TXMLDocument.Create(nil); 
    xmlDoc.LoadFromXML(usersXML); 
    workNode := xmlDoc.DocumentElement; 
    workNode := workNode.ChildNodes.FindNode('Users'); 

    while (workNode <> nil) and (workNode.NodeName = 'Users') do 
    begin 
    userObj := TUser.Create; 
    userObj.LoadFromXMLNode(workNode); 
    Items.Add(userObj); 

    workNode := workNode.NextSibling; 
    end; 
end; 

В приведенном выше коде

workNode := workNode.ChildNodes.FindNode('Users'); 

линия возвращает исключение где-то глубоко в блоке Xml.XMLDoc. Не сообщение об ошибке с конкретной проблемой, которую я мог бы исправить. Попробовал с сохранением xmlDoc в XML-файл, и он выглядит нормально (можно открыть его со всеми типами инструментов, таких как Firefox).

Странно, что если я изменю @ReturnData на varchar (max), я больше не получу эту ошибку.

Любая идея, что я делаю неправильно?

ответ

0

Для XML избегайте использования * и неназванных столбцов. Кроме того, не используйте ROOT в своем вложенном XML, вместо этого объявляйте его как именованное поле. Например:

CREATE PROCEDURE uspUsers_GetAll 
    @ReturnData nvarchar(max) = NULL OUTPUT 
AS 
BEGIN 
    SET NOCOUNT ON; 
    SET @ReturnData = CONVERT(nvarchar(max), 
       (SELECT givenname = Users.GivenName,surname = Users.Surname , emailaddress = Users.Email , userrights = ( SELECT userid = UserRights.UserID, righttype = UserRights.RightType 
           FROM UserRights 
           WHERE UserRights.UserID = Users.ID 
           FOR XML RAW('userrights'), 
           ELEMENTS, TYPE) 
       FROM Users 
       FOR XML RAW('user'), 
       ROOT('root') , ELEMENTS)); 
END; 

BTW Я всегда избегаю заглавных букв xml, назовите меня старомодным. Также обратите внимание, что «теги» тега строки должны быть «пользователем», так как это относится к одному пользователю. Это должно дать вам

<root> 
    <user> 
     <givenname>Jo</givenname> 
     <surname>Shmo</surname> 
       <userrights> 
        <userid>12</userid> 
        <righttype>some_type</righttype> 
       </userrights> 
       <userrights> 
        <userid>12</userid> 
        <righttype>some_type</righttype> 
       </userrights> 
    </user> 
    <user> 
    .... 
    </user> 
</root> 
+0

Спасибо за ответ, но я давно изменил подход, поэтому я не могу протестировать сейчас, если ваше решение является правильным ... – BenjiK

Смежные вопросы