📄 xmlparse.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 + -