Sql server NVarchar(最大)到XML解析错误

Sql server NVarchar(最大)到XML解析错误,sql-server,xml,delphi,nvarchar,firedac,Sql Server,Xml,Delphi,Nvarchar,Firedac,具有以下配置: 德尔福XE7 MS SQL Server 2008 使用FireDAC连接到SQL server 我正在使用存储过程从SQLServer中检索表,表中的所有详细记录都以XML格式转换为nvarchar(max)。以下是一个例子: CREATE PROCEDURE uspUsers_GetAll @ReturnData nvarchar(max) = NULL OUTPUT AS BEGIN SET NOCOUNT ON; SET @ReturnData = CONVE

具有以下配置: 德尔福XE7 MS SQL Server 2008 使用FireDAC连接到SQL server

我正在使用存储过程从SQLServer中检索表,表中的所有详细记录都以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;
第行返回Xml.XMLDoc单元深处的异常。不是一条带有我可以修复的特定问题的错误消息。我尝试过将xmlDoc保存到一个xml文件中,它看起来还可以(可以用像Firefox这样的各种工具打开它)

奇怪的是,如果我将@ReturnData更改为varchar(max),我就不会再收到这个错误


知道我做错了什么吗?

对于XML,避免使用*和未命名列。另外,不要在嵌套XML中使用ROOT,而是将其声明为命名字段。例如:

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;
顺便说一句,我总是避免使用大写的xml标记,称我为老式。另请注意,行标记“users”应为“user”,因为这指的是单个用户。这应该给你

<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>

乔
Shmo
12
某种类型的
12
某种类型的
....

谢谢您的回答,但我很久以前就改变了方法,所以现在无法测试您的解决方案是否正确。。。
<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>