⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xmlparse.pas

📁 XML 精要 范例 解析封装类库
💻 PAS
字号:
//------------------------------------------
//    名称:XMLParse
//    功能:XML解析类库
//    引入:xmldom, XMLIntf, msxmldom, XMLDoc, Classes, IdCoder, IdCoder3to4, IdCoderMIME, IdBaseComponent
//	  引出:无 
//    版本:1.0
//    作者:罗庚
//    时间:2004-01-05
//    说明: 改类用于简化XML的解析工作, 但其有个限定, 只能解析不带域的XML.而且不能直接解析如下格式的片断
//  <XMLPackage>
//    <data id="1">
//       <row id="1" name="子蓝" sex="男" age="24" duty="软件工程师"/>
//       <row id="2" name="天使蓝" sex="女" age="25" duty="商务经理"/>
//    </data>
//    <data id="2">
//       <row id="1" name="子蓝" sex="男" age="24" duty="软件工程师"/>
//       <row id="2" name="天使蓝" sex="女" age="25" duty="商务经理"/>
//    </data>
//  </XMLPackage>
//  这是应为存在两个<data>元素的实例, intRowIndex 只能用于区分strNodePath指定的最尾部的同名节点(如row元素), 而不能区分出树枝(如<data id="2">这个节点)
//  但也不是说没有办法解析, 可以用 GetNode<data id="2"> 把 data 节点读出, 然后再再手工解析. 或者可以考虑让 GetNode 支持数组格式 ,如可以让 strNodePath='Package.data[1].row[0]'这样的格式.
//------------------------------------------

unit XMLParse;

interface
uses  XMLIntf,  XMLDoc, Classes,  IdCoderMIME ; // msxmldom,,xmldom,IdCoder, IdCoder3to4,IdBaseComponent
Type
   TXMLDOMEx = Class(TObject)
      private
        XMLDocument :IXMLDocument;
        strXMLFileName :String;
      public
        constructor Create( strFileName :String='' );
        destructor destory();
        function LoadXMLFile( strFileName :String ):Boolean;
        function GetNodeAttribute( strNodePath, strAttribute: String; var strValue: String; intRowIndex: Integer=0; const dep: Char='.'):Boolean;
        function GetNodeText( strNodePath :String; var strValue :String; intRowIndex :Integer=0 ; const dep: Char='.'):Boolean;
        function GetNodeStream( strNodePath :StrIng; var stmValue :TStream; intRowIndex :Integer=0 ; const strEncode :String='Base64';const dep: Char='.'):Boolean;
        function GetChridNodeCount( strParentNodePath, strChildNodeName: String; const dep: Char='.'): Integer;
        function GetNode( strNodePath: String; intRowIndex: Integer=0; const dep: Char='.'): IXMLNode;

   end;
implementation


{ TXMLDOMEx }
//---------------------------------------------------------------------------
// 名称: Create
// 功能: 创建对象,建立IXMLDocument接口
// 输入:strFileName :String=''  XML文件名
// 输出:无
// 版本:1.0
// 作者:罗庚
// 时间:2004-01-03
//---------------------------------------------------------------------------
constructor TXMLDOMEx.Create(strFileName: String);
begin
  XMLDocument := TXMLDocument.Create( strFileName );

  XMLDocument.Active := True;
  strXMLFileName := strFileName;
end;

//---------------------------------------------------------------------------
// 名称: GetChridNodeCount
// 功能: 获取XML中节点strParentNodePath 的子节点 strChildNodeName 的个数
// 输入:strParentNodePath 父节点名,默认使用.分割,如 XMLPackage.data.row;
//       strChildNodeName  要确定其个数的子节点, 默认为空, 表示确定所有父节点下的子节点个数
//       dep 路径 strNodePath 分割符号, 默认为 . ,如 strNodePath='XMLPackage>data>row',则改属性置为 >
// 输出:Integer 找到的子节点个数
// 版本:1.0
// 作者:罗庚
// 时间:2004-01-03
//---------------------------------------------------------------------------
function TXMLDOMEx.GetChridNodeCount(strParentNodePath,
  strChildNodeName: String; const dep: Char='.'): Integer;
var XMLParentNode: IXMLNode;  //'XMLPackage.memo'
    iCount, i :Integer;
    
begin
  iCount := 0;
  XMLParentNode := GetNode( strParentNodePath, 0, dep );
  if not assigned( XMLParentNode ) then
  begin
    Result := -1; // 无效的父节点
    exit;
  end;

  if strChildNodeName = '' then
    Result := XMLParentNode.ChildNodes.Count
  else
  begin
    for i := 0 to XMLParentNode.ChildNodes.Count -1 do
    begin
      if XMLParentNode.ChildNodes.Nodes[i].NodeName = strChildNodeName then
        inc( iCount );
    end;
    Result := iCount;
  end;

end;

//---------------------------------------------------------------------------
// 名称: GetNode
// 功能: 获取XML中编号第intRowIndex个路径为strNodePath的节点.
// 注意: 本类库的主要限制也就在这, 就是intRowIndex只能对strNodePath尾部的节点有控制作用
// 输入:strNodePath 节点名,默认使用.分割,如 XMLPackage.data.row;
//       intRowIndex 尾部节点的索引, 如在data节点中包含多个 row节点时, 这个参数说明获取第几个row节点(row[i]),默认为0
//       dep 路径 strNodePath 分割符号, 默认为 . ,如 strNodePath='XMLPackage>data>row',则改属性置为 >
// 输出:IXMLNode 找到的节点, 没有找到返回nil
// 版本:1.0
// 作者:罗庚
// 时间:2004-01-03
//---------------------------------------------------------------------------
function TXMLDOMEx.GetNode(strNodePath: String;  intRowIndex: Integer;
  const dep: Char): IXMLNode;
var XMLNode: IXMLNode;
    sltNodePath :TStrings;
    iNodePathCount, iNodePathIndex :Integer;
    bIsFoundChild :Boolean;

    i:Integer;
    strBeFoundNodeName :String;
begin
  sltNodePath:=TStringList.Create;
  sltNodePath.Delimiter:= dep;
  sltNodePath.DelimitedText:= strNodePath;

  // 获取根节点
  iNodePathCount := sltNodePath.Count;
  iNodePathIndex := 0;
  XMLNode := XMLDocument.DocumentElement;
  // End .

  bIsFoundChild := XMLNode.NodeName = sltNodePath.Strings[ iNodePathIndex ];
  inc( iNodePathIndex );

  while bIsFoundChild and ( iNodePathIndex < iNodePathCount  )  do
  begin
    strBeFoundNodeName := sltNodePath.Strings[ iNodePathIndex ];
    // 遍历所有的子节点, 从中查找下名为 strBeFoundNodeName 的节点.
    bIsFoundChild := False;
    for i:= 0 to XMLNode.ChildNodes.Count - 1 do
    begin
      // 当寻找到当前节点的子节点是本次要寻找的节点时候, 选择往下层寻找还是本层寻找第intRowIndex个同名的节点
       if XMLNode.ChildNodes.Nodes[i].NodeName = strBeFoundNodeName then
       begin
         // 当还没有到达strNodePath中指定的最后的节点时,继续往下层遍历
          if iNodePathIndex <> (iNodePathCount - 1) then
          begin
            bIsFoundChild := True;
            XMLNode := XMLNode.ChildNodes.Nodes[i];
            break;
          end
         // End .
          else
         // 当已经寻找到strNodePath中指定的最后的节点的时候,控制往下寻找第 intRowIndex 个名为 strBeFoundNodeName 节点
          begin
            Dec( intRowIndex );
            if intRowIndex < 0 then
            begin
              bIsFoundChild := True;
              XMLNode := XMLNode.ChildNodes.Nodes[i];
              break;
            end;
          end;
          // End .
       end;
      // End . 
    end;
    // End . 结束寻找子节点.
    inc( iNodePathIndex );
  end;
  // end of while

  if bIsFoundChild then
    Result := XMLNode
  else
    Result := nil;
end;

//---------------------------------------------------------------------------
// 名称: GetNodeAttribute
// 功能: 获取XML中编号第intRowIndex个路径为strNodePath的节点的属性 strAttribute.
// 输入:strNodePath 节点名,默认使用.分割,如 XMLPackage.data.row;
//       strAttribute 要获取的属性名称, 区分大小写
//       strValue     输出的属性值
//       intRowIndex 尾部节点的索引, 如在data节点中包含多个 row节点时, 这个参数说明获取第几个row节点(row[i]),默认为0
//       dep 路径 strNodePath 分割符号, 默认为 . ,如 strNodePath='XMLPackage>data>row',则改属性置为 >
// 输出:boolean 成功返回true, false 表示无效的节点或者属性
// 版本:1.0
// 作者:罗庚
// 时间:2004-01-03
//---------------------------------------------------------------------------
function TXMLDOMEx.GetNodeAttribute(strNodePath, strAttribute: String;
  var strValue: String; intRowIndex: Integer=0; const dep: Char='.'): Boolean;
var XMLNode: IXMLNode;  
begin
  XMLNode := GetNode( strNodePath, intRowIndex, dep );
  Result := True;
  if ( not assigned( XMLNode )) or ( not XMLNode.HasAttribute( strAttribute )) then
  begin
    Result := False;      // 无效的节点或者属性
    strValue := '';
  end
  else
  begin
    strValue := XMLNode.Attributes[ strAttribute ];
  end;
end;

//---------------------------------------------------------------------------
// 名称: GetNodeText
// 输入:strNodePath 节点名,默认使用.分割,如 XMLPackage.data.row;
//       strValue    改节点包含的Text
//       intRowIndex 尾部节点的索引, 如在data节点中包含多个 row节点时, 这个参数说明获取第几个row节点(row[i]),默认为0
//       dep 路径 strNodePath 分割符号, 默认为 . ,如 strNodePath='XMLPackage>data>row',则改属性置为 >
// 输出:1. true      成功返回
//       2. false     无效的节点或者该节点不能包括单独的Text
// 版本:1.0
// 作者:罗庚
// 时间:2004-01-03
//---------------------------------------------------------------------------
function TXMLDOMEx.GetNodeText(strNodePath :String; var strValue :String;
     intRowIndex :Integer=0 ; const dep: Char='.'): Boolean;
var XMLNode: IXMLNode;
begin
  XMLNode := GetNode( strNodePath, intRowIndex, dep );
  Result := True;
  if ( not assigned( XMLNode )) or (not XMLNode.IsTextElement )  then
  begin
    Result := False;      // 无效的节点或者该节点不能包括单独的Text
    strValue := '';
  end
  else
  begin
    strValue := XMLNode.Text;
  end;
end;

//---------------------------------------------------------------------------
// 名称: GetNodeStream
// 输入:strNodePath 节点名,默认使用.分割,如 XMLPackage.data.row;
//       strStrem     输出的DecodeBase64流
//       intRowIndex 尾部节点的索引, 如在data节点中包含多个 row节点时, 这个参数说明获取第几个row节点(row[i]),默认为0
//       strEncode   Decode的代码格式, 这个类库只支持 Base64, 但可以扩充.
//       dep 路径 strNodePath 分割符号, 默认为 . ,如 strNodePath='XMLPackage>data>row',则改属性置为 >
// 输出:1. true      成功返回
//       2. false     无效的节点或者该节点不能包括单独的Text
// 版本:1.0
// 作者:罗庚
// 时间:2004-01-03
//---------------------------------------------------------------------------
function TXMLDOMEx.GetNodeStream(strNodePath: StrIng;
  var stmValue: TStream; intRowIndex: Integer;
  const strEncode: String; const dep: Char): Boolean;
var strText :String;
    DecodeBase64: TIdDecoderMIME;
begin
   stmValue.Size := 0;
   stmValue.Position := 0;
  if not GetNodeText( strNodePath, strText, intRowIndex, dep ) then
  begin
    Result := False;     // 无效的节点或者该节点不能包括单独的Text
    exit;
  end;

  DecodeBase64 := TIdDecoderMIME.Create(nil);
  DecodeBase64.DecodeToStream( strText, stmValue );
  DecodeBase64.Free;
end;

//---------------------------------------------------------------------------
// 名称: LoadXMLFile
// 功能: 载入一个XML文件
// 输入:strFileName XML的文件名
// 输出:1. true      成功返回
//       2. false     读取失败或者解析失败
// 版本:1.0
// 作者:罗庚
// 时间:2004-01-03
//---------------------------------------------------------------------------
function TXMLDOMEx.LoadXMLFile(strFileName: String): Boolean;
begin
  XMLDocument.Active := False;
  XMLDocument.LoadFromFile( strFileName );
  XMLDocument.Active := True;
end;

//---------------------------------------------------------------------------
// 名称: destory
// 功能: 类销毁时, 撤销所有对象
// 输入:无
// 输出:无
// 版本:1.0
// 作者:罗庚
// 时间:2004-01-03
//---------------------------------------------------------------------------
destructor TXMLDOMEx.destory;
begin
  if assigned( XMLDocument ) then
  begin
    // XMLDocument._Release;         这句语句倒不一定需要, 这里只是为了保险.
    XMLDocument := nil;
  end
end;

end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -