1

これには用語があると確信しているため、適切な用語が不足していることをご容赦ください。生の文字列を使用して XML テキストを作成しています (使いやすいように、任意のタイプの XML ビルダー/パーサーではありません)。ただし、提供しているデータの一部の文字が標準化されていないという問題に直面しています。たとえば、&シンボル。文字列にこれが含まれていると、最後のパーサーがスローされます。これに適切に対応し、文字列を XML 標準に変換するにはどうすればよいですか?

文字列リストにプレーン文字列を書き込み、Text以下のようにそのプロパティを読み取ります。A(const S: String);XML ファイルに行を追加し、必要なインデントを追加する短縮された方法であるサブルーチンに注意してください。サブルーチンを参照してくださいStandardize。これは私が記入する必要があるものです。

uses Windows, Classes, SysUtils, DB, ADODB, ActiveX;

function TSomething.FetchXML(const SQL: String): String;
var
  L: TStringList;
  Q: TADOQuery;
  X, Y: Integer;
  function Standardize(const S: String): String;
  begin
    Result:= S; //<<<--- Need to convert string to XML standards
  end;
  procedure A(const Text: String; const Indent: Integer = 0);
  var
    I: Integer;
    S: String;
  begin
    if Indent > 0 then
      for I := 0 to Indent do
        S:= S + '  ';
    L.Append(S + Text);
  end;
begin
  Result:= '';
  L:= TStringList.Create;
  try
    Q:= TADOQuery.Create(nil);
    try
      Q.ConnectionString:= FCredentials.ConnectionString;
      Q.SQL.Text:= SQL;
      Q.Open;
      A('<?xml version="1.0" encoding="UTF-8"?>');
      A('<dataset Source="ECatAPI">');
      A('<table>');
      A('<fields>', 1);
      for X := 0 to Q.FieldCount - 1 do begin
        A('<field Name="'+Q.Fields[X].FieldName+'" '+
          'Type="'+IntToStr(Integer(Q.Fields[X].DataType))+'" '+
          'Width="'+IntToStr(Q.Fields[X].DisplayWidth)+'" />', 2);
      end;
      A('</fields>', 1);
      A('<rows>', 1);
      if not Q.IsEmpty then begin
        Q.First;
        while not Q.Eof do begin
          A('<row>', 2);
          for Y:= 0 to Q.FieldCount - 1 do begin
            A('<value Field="'+Q.Fields[Y].FieldName+'">'+
              Standardize(Q.Fields[Y].AsString)+'</value>', 3);
          end;
          A('</row>', 2);
          Q.Next;
        end;
      end;
      A('</rows>', 1);
      A('</table>');
      A('</dataset>');
      Result:= L.Text;
      Q.Close;
    finally
      Q.Free;
    end;
  finally
    L.Free;
  end;
end;

ノート

上記は疑似コードであり、コピペして改変したもので、関係ないものは改変・除外してあります...

より詳しい情報

このアプリケーションは、データへの読み取り専用アクセスを提供するスタンドアロンの Web サーバーです。XML データを書き込むだけで済み、読み取る必要はありません。仮にそうしたとしても、その部分をカバーする XML パーサー ライブラリが既にあります。不要なオブジェクトでメモリをいっぱいにすることなく、この軽量化を可能な限り維持しようとしています。

4

5 に答える 5

4

手作業でXMLを生成しないでください。

複雑なデータ(たとえば、XML、HTML、またはXML内の他のSGML、エスケープされたCDATA)をエスケープするための正しいコードを作成することは価値がありません。

あなたがする脱出はただの始まりです。誰かが互換性のない何かをあなたのデータに入れるまで待ちます。

多くのデータベースは、とにかくクエリから整形式のXMLを作成することをサポートしています(他の回答を参照)。これは、検討すべき方向です。

于 2012-08-31T09:50:11.187 に答える
3

もう 1 つのヒント: お使いのデータベースが XML としての結果の生成をサポートしている可能性があります。

于 2012-08-31T09:00:30.723 に答える
1

ジェリーの解決策は良いものです。

これを行う既存の VCL 手順があることに注意してください。

unit IdStrings には StrXHtmlEncode() があります。これはジェリーのソリューションと同じです。

ユニット HttpApp には HTMLEncode() があります。この関数は、Jerry のソリューションよりも効率的ですが、注意してください。この手順は、実際には Unicode 文字列に対して壊れています。ユニコード以前のコンパイラでは正しく動作しましたが、ユニコード用に正しくアップグレードされておらず、エラーは修正されていません。

apos 置換が追加された HttpApp.HTMLEncode() の Unicode セーフ バージョンは次のとおりです。StringReplace() スタイルよりも冗長ですが、実行時のパフォーマンスに関してははるかに効率的です。(apos は、XML および XHTHML では定義済みのエンティティですが、HTML 4 では定義されていません)。

function XHTMLEncode( const sRawValue: string): string;
var
  Sp, Rp: PChar;
begin
  SetLength( result, Length( sRawValue) * 10);
  Sp := PChar( sRawValue);
  Rp := PChar( result);
  while Sp^ <> #0 do
  begin
    case Sp^ of
      '&': begin
             FormatBuf( Rp^, 10, '&amp;', 10, []);
             Inc(Rp,4);
           end;
      '<',
      '>': begin
             if Sp^ = '<' then
               FormatBuf(Rp^, 8, '&lt;', 8, [])
             else
               FormatBuf(Rp^, 8, '&gt;', 8, []);
             Inc(Rp,3);
           end;
      '"': begin
             FormatBuf(Rp^, 12, '&quot;', 12, []);
             Inc(Rp,5);
           end;
      '''': begin
             FormatBuf(Rp^, 12, '&apos;', 12, []);
             Inc(Rp,5);
           end;
    else
      Rp^ := Sp^
    end;
    Inc(Rp);
    Inc(Sp);
  end;
  SetLength( result, Rp - PChar( result))
end;
于 2012-08-31T06:43:37.793 に答える
1

上記の質問のコメントのおかげで、定義済みのエンティティを適切な名前に置き換える機能を実装しました。これは新しいサブルーチンです:

function EncodeXmlStr(const S: String): String;
begin
  Result:= StringReplace(S,      '&',  '&amp;',  [rfReplaceAll]);
  Result:= StringReplace(Result, '''', '&apos;', [rfReplaceAll]);
  Result:= StringReplace(Result, '"',  '&quot;', [rfReplaceAll]);
  Result:= StringReplace(Result, '<',  '&lt;',   [rfReplaceAll]);
  Result:= StringReplace(Result, '>',  '&gt;',   [rfReplaceAll]);
end;
于 2012-08-31T03:30:35.673 に答える