Delphi之通過代碼示例學習XML解析、StringReplace的用法


  這個程序可以用於解析任何合法的XML字符串。

首先是看一下程序的運行效果:            

  以解析這樣一個XML的字符串為例:

<?xml version="1.0" encoding="UTF-8"?><BookInfo><Owner><OwnerName>張三</OwnerName><OwnerAge>1234</OwnerAge></Owner><BookMes><BookName>時間簡史</BookName><ISDN>234343453534</ISDN><Writer>霍金</Writer></BookMes></BookInfo>

  首先是打開應用程序

  然后將上面所示的字符串復制到文本編輯框中,然后點擊解析按鈕,會出現下面的效果

  如上圖所示,可以 “XML中的字段標簽:XML中對應標簽的值” 的格式顯示解析的效果。

 

  因為進行了異常處理(使用try..except..end,並且在異常處理中使用ShowMessage彈出異常信息),所以如果輸入的字符串不是合法的XML格式的話,程序會正常報錯,而不會異常終止。

  比如沒有輸入直接點擊解析按鈕,效果如下:

  有比如輸入一個非法的字符串,效果如下

 

然后看一下代碼                   

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, XMLIntf, XMLDoc;

type
  TForm1 = class(TForm)
    edt1: TEdit;
    btn1: TButton;
    procedure btn1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure ReadXml(Node: IXMLNode; var showmess: string);
var
  NodeList: IXMLNodeList;
  strName: string;
  i: Integer;
begin
  if not Node.HasChildNodes then Exit;
  nodeList := node.ChildNodes;
  for i := 0 to nodeList.Count - 1 do
  begin
    strName := nodeList[i].NodeName;
    if nodeList[i].IsTextElement then //如果是元素
    begin
      showmess:= showmess + strName + ':' + NodeList[i].NodeValue + #13#10;
    end
    else if nodeList[i].HasChildNodes then //如果有子節點
    begin
      ReadXml(NodeList[i], showmess);
    end;
  end;
end;

procedure TForm1.btn1Click(Sender: TObject);
var
  sXML, showmess: string;
  ComInstrXML: IXMLDocument;
  mainNode: IXMLNode;
begin
   showmess:= '';
   sXML:= edt1.Text;
   sXML:= StringReplace(sXML, 'UTF-8', 'gbk', []);   //只替換<?xml version="1.0" encoding="UTF-8"?>里面的字符編碼方式,因為往往這個是在最前面出現的,所以StringReplace的第四個參數是[]
   try  //一定不要忘記異常處理,保證程序的穩定性,能夠正常處理異常而不至於在發生異常的時候導致程序崩潰
     ComInstrXML:= LoadXMLData(sXML);
     mainNode:= ComInstrXML.DocumentElement;
     readXML(mainNode, showmess);

     ShowMessage(showmess);
   except
     on E: Exception do
     begin
       ShowMessage(E.Message);
     end;
   end;
end;

end.

  

講解一下代碼                    

 0.建議這樣使用XML解包

  本例中的程序,在解包之后是將標簽以及對應的值顯示在彈出框上,這樣只是為了演示解析XML的效果。

  建議在開發中將解析好的XML節點,以節點的標簽作為Key,以節點的內容作為value,插入到一個可以搜索的鏈表或者其他什么可以根據Key進行搜索的容器類中,然后在之后使用的時候就可以很方便的搜索到解析后的值。

1.注意解析XML使用到相關的類、方法所屬的單元

  要使用IXMLDocument、IXMLNodeList和iXMLNode,需要引入 XMLIntf 單元。

  要使用 LoadXMLData方法,需要引入XMLDoc 單元。 

2.遞歸解包XML

  因為XML本身就是一個遞歸的結構,所以解包XML,也就是其中的ReadXML 方法使用的就是遞歸的方法,遞歸結束標志是:正在解析的XML標簽是一個元素,沒有子節點。

3.字符編碼的問題 

  在 TForm1.btn1Click(Sender: TObject) 方法中,我們可以看到首先將XML字符串中的 'UTF-8' 替換為 'gbk',因為如果編碼方式是UTF-8:<?xml version="1.0" encoding="UTF-8"?>,那么如果XML中存在中文,那么解析的時候會報錯(如果全部為英文,那么就不會報錯),如下圖

  如果將UTF-8替換為gbk,,那么在解析XML的時候就不會報這樣的錯誤。

  另外如果以不包含編碼格式的XML字符串,如:<BookInfo><Owner><OwnerName>張三</OwnerName><OwnerAge>1234</OwnerAge></Owner><BookMes><BookName>時間簡史</BookName><ISDN>234343453534</ISDN><Writer>霍金</Writer></BookMes></BookInfo>,沒有 <?xml version="1.0" encoding="UTF-8"?>的話,此時就算有   sXML:= StringReplace(sXML, 'UTF-8', 'gbk', [rfReplaceAll]);   這樣的替換字符編碼的代碼也是沒有用的,也沒有辦法改成gbk的編碼,所以仍然會報上面的異常。

  所以請注意字符編碼的問題,尤其是既有中文又有英文的時候。

  另外還有一個需要注意的點,我們只需要替換“<?xml version="1.0" encoding="UTF-8"?>”這個里面的UTF-8為gbk就行了,因為可能XML本身的其他字段就存儲着什么關於字符編碼的信息,但是與本條XML報文無關,純粹只是一條需要傳輸的信息。下面的一條XML的報文就是例子:

<?xml version="1.0" encoding="UTF-8"?><BookInfo><Charset>UTF-8</Charset><Owner><OwnerName>張三</OwnerName><OwnerAge>1234</OwnerAge></Owner><BookMes><BookName>時間簡史</BookName><ISDN>234343453534</ISDN><Writer>霍金</Writer></BookMes></BookInfo>

  這時候在替換的時候,要注意只要替換XML本身的字符編碼就好了,其他的XML需要傳輸的可能有關於字符編碼的信息不能替換,否則可能導致傳輸的XML信息違背了其傳輸時候的初衷了!!

  所以上面的代碼中使用:sXML:= StringReplace(sXML, 'UTF-8', 'gbk', []);   其中StringReplace的第四個參數是[] 表示只替換第一個即可。

4.stringReplace函數的使用

  function StringReplace (const S, OldPattern, NewPattern: string; Flags: TReplaceFlags): string; 

rfReplaceAll:全部替換 
rfIgnoreCase:忽略大小寫

例子

var 
    aStr: String; 
begin 
    aStr := 'This is a book, not a pen!'; 
    ShowMessage(StringReplace (aStr, 'a', 'two', []));//This is two book, not a pen!只替換了第一個符合的字符串 
    ShowMessage(StringReplace (aStr, 'a', 'two', [rfReplaceAll]));//This is two book, not two pen!替換了所有符合的字符串 
    aStr := 'This is a book, not A pen!'; 
    ShowMessage(StringReplace (aStr, 'a', 'two', [rfReplaceAll]));//This is two book, not A pen!只替換了符合的字符串(小寫a) 
    ShowMessage(StringReplace (aStr, 'a', 'two', [rfReplaceAll, rfIgnoreCase]));//This is two book, not two pen!不管大小寫替換了所有符合的字符串
end;

5.換行

  注意代碼中有這樣一行代碼:

showmess:= showmess + strName + ':' + NodeList[i].NodeValue + #13#10;

  其中的 #13#10 表示換行

 




 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM