sql-server – 如何在D7中解码XML Blob字段

前端之家收集整理的这篇文章主要介绍了sql-server – 如何在D7中解码XML Blob字段前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我在尝试将MS sql Server 2014实例返回的 XML数据解码为以D7编写的应用程序时遇到问题. (Indy的版本是附带的版本,9.00.10).

更新当我最初编写此q时,我的印象是blob字段的内容需要进行Base64解码,但似乎这是错误的.遵循Remy Lebeau的建议,blob流在解码之前包含字段名称和字段值中的可识别文本,但之后不包含.

在下面的代码中,AdoQuery中的sql很简单

Select * from Authors where au_lname = ‘White’ For XML Auto

Authors表是演示’pubs’数据库中的表.我添加了“Where”子句来限制结果集的大小,以便我可以显示返回的blob的十六进制转储.

根据sql Server OLH,指定’For XML Auto’时返回数据的默认类型是’binary base64-encoded format’.如果我让IDE创建这个字段,AdoQuery的单个字段的数据类型是ftBlob.

执行下面的代码生成异常“DecodeToStream中的不均匀大小”.在调用IdDecoderMIME.DecodeToString(S)时,字符串S的长度为3514,3514 mod 4为2,而不是0,因为它显然应该是,因此是例外.我已经确认字段值中的字节数是3514,因此变量的大小和字符串的长度没有区别,即两者之间没有任何区别.

procedure TForm1.FormCreate(Sender: TObject);
var
  SS : TStringStream;
  Output : String;
  S : String;
  IdDecoderMIME : TIdDecoderMIME;
begin
  SS := TStringStream.Create('');
  IdDecoderMIME := TIdDecoderMIME.Create(Nil);
  try
    AdoQuery1.Open;
    TBlobField(AdoQuery1.Fields[0]).SaveToStream(SS);
    S := SS.DataString;
    IdDecoderMIME.FillChar := #0;
    Output := IdDecoderMIME.DecodeToString(S);
    Memo1.Lines.Text := S;
  finally
    SS.Free;
    IdDecoderMIME.Free;
  end;
end;

我正在使用此代码

procedure TForm1.FormCreate(Sender: TObject);
var
  SS : TStringStream;
  MS : TMemoryStream;
  Output : String;
begin
  SS := TStringStream.Create('');
  MS := TMemoryStream.Create;
  try
    AdoQuery1.Open;
    TBlobField(AdoQuery1.Fields[0]).SaveToStream(SS);
    SS.WriteString(#13#10);
    Output := SS.DataString;
    SS.Position := 0;
    MS.CopyFrom(SS,SS.Size);
    MS.SaveToFile(ExtractFilePath(Application.ExeName) + 'Blob.txt');
  finally
    SS.Free;
    MS.Free;
  end;
end;

Blob.Txt文件的十六进制转储如下所示

00000000  44 05 61 00 75 00 5F 00 69 00 64 00 44 08 61 00  D.a.u._.i.d.D.a.
00000010  75 00 5F 00 6C 00 6E 00 61 00 6D 00 65 00 44 08  u._.l.n.a.m.e.D.
00000020  61 00 75 00 5F 00 66 00 6E 00 61 00 6D 00 65 00  a.u._.f.n.a.m.e.
00000030  44 05 70 00 68 00 6F 00 6E 00 65 00 44 07 61 00  D.p.h.o.n.e.D.a.
00000040  64 00 64 00 72 00 65 00 73 00 73 00 44 04 63 00  d.d.r.e.s.s.D.c.
00000050  69 00 74 00 79 00 44 05 73 00 74 00 61 00 74 00  i.t.y.D.s.t.a.t.
00000060  65 00 44 03 7A 00 69 00 70 00 44 08 63 00 6F 00  e.D.z.i.p.D.c.o.
00000070  6E 00 74 00 72 00 61 00 63 00 74 00 44 07 61 00  n.t.r.a.c.t.D.a.
00000080  75 00 74 00 68 00 6F 00 72 00 73 00 01 0A 02 01  u.t.h.o.r.s.....
00000090  10 E4 04 00 00 0B 00 31 37 32 2D 33 32 2D 31 31  .......172-32-11
000000A0  37 36 02 02 10 E4 04 00 00 05 00 57 68 69 74 65  76.........White
000000B0  02 03 10 E4 04 00 00 07 00 4A 6F 68 6E 73 6F 6E  .........Johnson
000000C0  02 04 0D E4 04 00 00 0C 00 34 30 38 20 34 39 36  .........408 496
000000D0  2D 37 32 32 33 02 05 10 E4 04 00 00 0F 00 31 30  -7223.........10
000000E0  39 33 32 20 42 69 67 67 65 20 52 64 2E 02 06 10  932 Bigge Rd....
000000F0  E4 04 00 00 0A 00 4D 65 6E 6C 6F 20 50 61 72 6B  ......Menlo Park
00000100  02 07 0D E4 04 00 00 02 00 43 41 02 08 0D E4 04  .........CA.....

正如您所看到的,其中一些是清晰的(字段名称内容),其中一些不是.有没有人认识到这种格式,并且知道如何将其清理成我在SS Management Studio中执行相同查询所获得的纯文本,即如何从结果集中成功提取XML?

顺便说一句,我使用MS OLE DB Provider for sql Server和sql Server Native Client 11提供程序,并使用Delphi Seattle代替D7,得到相同的结果(包括Blob.Txt文件内容).

鉴于代码访问外部数据库,此代码是我可以访问MCVE的最接近的代码.

更新#2如果我将SQL查询更改为,解码问题就会消失

select Convert(Text,(select * from authors where au_lname = 'White' for xml AUTO
))

它给出了结果(在SS中)

<authors au_id="172-32-1176" au_lname="White" au_fname="Johnson" phone="408 496-7223" address="10932 Bigge Rd." city="Menlo Park" state="CA" zip="94025" contract="1"/>

但我仍然有兴趣知道如何在不需要Convert()的情况下使其工作.我注意到如果我从sql删除Where子句,返回的内容不是格式良好的XML – 它包含一系列节点,每个数据行一个节点,但没有封闭的根节点.

顺便说一下,我意识到我可以通过不使用“For XML Auto”来避免这个问题,我只是对如何正确地做到这一点感兴趣.此外,一旦我设法提取XML,我就不需要任何帮助来解析XML.

解决方法

添加 TYPE Directive以指定您希望返回XML.
select * 
from Authors 
where au_lname = 'White' 
for xml auto,type
原文链接:https://www.f2er.com/mssql/78667.html

猜你在找的MsSQL相关文章