2016-09-05 5 views
3

가지고 다음과 같은 구성 : 델파이 XE7 MS SQL 서버 2008 FireDACNVARCHAR XML 구문 분석 오류 (최대)

와 SQL 서버에 연결

나는 모든 세부 레코드가있는 테이블을 검색하는 저장 프로 시저를 사용 해요 XML 형식의 SQL Server에서 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; 

내가 XML에로드,이 저장 프로 시저를 호출하고있어 나는 개체의 로컬 목록으로 변환하기 위해 구문 분석하려고 해요 예를 들면 다음과 같습니다. 이런 식으로 뭔가 다음

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

라인이 Xml.XMLDoc 단위로 어딘가에 깊은 예외를 반환 위의 코드에서

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; 

. 문제를 해결할 수있는 오류 메시지가 아닙니다. xmlDoc을 xml 파일에 저장해 보았는데 괜찮습니까 (파이어 폭스와 같은 모든 종류의 도구로 열 수 있음).

이상한 점은 @ReturnData를 varchar (max)로 변경하면 더 이상이 오류가 발생하지 않는다는 것입니다.

내가 뭘 잘못하고 있는지 아는 사람이 있습니까?

답변

0

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; 

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