延迟方法-如何用itunes备份
![quotedstr](/uploads/image/0817.jpg)
2023年4月3日发(作者:typecho)
燃气公司呼叫中心系统概要设计
functionStringReplace(constS,OldPattern,NewPattern:string;
Flags:TReplaceFlags):string;
var
SearchStr,Patt,NewStr:string;
Offset:Integer;
begin
ifrfIgnoreCaseinFlagsthen
begin
SearchStr:=UpperCase(S);
Patt:=UpperCase(OldPattern);
endelse
begin
SearchStr:=S;
Patt:=OldPattern;
end;
NewStr:=S;
Result:='';
whileSearchStr<>''do
begin
Offset:=Pos(Patt,SearchStr);
ifOffset=0then
begin
Result:=Result+NewStr;
Break;
end;
Result:=Result+Copy(NewStr,1,Offset-1)+NewPattern;
NewStr:=Copy(NewStr,Offset+Length(OldPattern),MaxInt);
ifnot(rfReplaceAllinFlags)then
begin
Result:=Result+NewStr;
Break;
end;
SearchStr:=Copy(SearchStr,Offset+Length(Patt),MaxInt);
end;
end;
functionStrToInt64Def(constAValue:string;ADefault:int64):int64;
begin
Result:=StrToIntDef(AValue,ADefault);
end;
functionStrToInt64(constAValue:string):int64;
begin
Result:=StrToInt(AValue);
end;
{$ENDIF}
//Delphi4stubs
{$IFNDEFD5UP}
functionAnsiPos(constSubstr,S:string):Integer;
begin
Result:=Pos(Substr,S);
end;
functionAnsiQuotedStr(constS:string;Quote:Char):string;
var
P,Src,Dest:PChar;
AddCount:Integer;
begin
AddCount:=0;
P:=StrScan(PChar(S),Quote);
whileP<>nildo
begin
Inc(P);
Inc(AddCount);
P:=StrScan(P,Quote);
end;
ifAddCount=0then
begin
Result:=Quote+S+Quote;
Exit;
end;
SetLength(Result,Length(S)+AddCount+2);
Dest:=Pointer(Result);
Dest^:=Quote;
Inc(Dest);
Src:=Pointer(S);
P:=StrScan(Src,Quote);
repeat
Inc(P);
Move(Src^,Dest^,P-Src);
Inc(Dest,P-Src);
Dest^:=Quote;
Inc(Dest);
Src:=P;
P:=StrScan(Src,Quote);
untilP=nil;
P:=StrEnd(Src);
Move(Src^,Dest^,P-Src);
Inc(Dest,P-Src);
Dest^:=Quote;
end;
functionAnsiExtractQuotedStr(varSrc:PChar;Quote:Char):string;
var
P,Dest:PChar;
DropCount:Integer;
begin
Result:='';
if(Src=nil)or(Src^<>Quote)then
Exit;
Inc(Src);
DropCount:=1;
P:=Src;
Src:=StrScan(Src,Quote);
whileSrc<>nildo
begin
Inc(Src);
ifSrc^<>Quotethen
Break;
Inc(Src);
Inc(DropCount);
Src:=StrScan(Src,Quote);
end;
ifSrc=nilthen
Src:=StrEnd(P);
if((Src-P)<=1)then
Exit;
ifDropCount=1then
SetString(Result,P,Src-P-1)
else
begin
SetLength(Result,Src-P-DropCount);
Dest:=PChar(Result);
Src:=StrScan(P,Quote);
whileSrc<>nildo
begin
Inc(Src);
ifSrc^<>Quotethen
Break;
Move(P^,Dest^,Src-P);
Inc(Dest,Src-P);
Inc(Src);
P:=Src;
Src:=StrScan(Src,Quote);
end;
ifSrc=nilthen
Src:=StrEnd(P);
Move(P^,Dest^,Src-P-1);
end;
end;
procedureFreeAndNil(varObj);
var
P:TObject;
begin
P:=TObject(Obj);
TObject(Obj):=nil;
;
end;
{$ENDIF}
//.
functionStreamWrite(Stream:TStream;constBuffer{$IFDEFCLR}:TBytes{$ENDIF};Offset,Count:
Longint):Longint;
begin
{$IFDEFCLR}
Result:=(Buffer,Offset,Count);
{$ELSE}
Result:=(TBytes(Buffer)[Offset],Count);
{$ENDIF}
end;
{$IFNDEFCLR}
//Delphi'simplementationofTStringStreamisseverelyflawed,itdoesaSetLength
//oneachwrite,plementationover-
//comesthisissue.
type
TsdStringStream=class(TMemoryStream)
public
constructorCreate(constS:string);
functionDataString:string;
end;
深圳市博域信源通讯有限公司一体化呼叫中心平台产品BYICC2.0典型成功案例汇总
住房公积金管理中心行业
内蒙古自治区乌兰察布市住房公积金管理中心12329住房公积金热线呼叫中心系统
自来水/供水行业
广东省佛山市水业集团有限公司客户服务中心(CallCenter/呼叫中心)系统
贵州省安顺市供水总公司呼叫中心系统
佛山水业三水供水有限公司呼叫中心(CallCenter)系统
深圳市布吉供水有限公司呼叫中心(CallCenter)系统
湖北省恩施市自来水有限责任公司96510供水服务热线呼叫中心系统
公安机关
山东省招远市公安局指挥中心110/119/122三台合一接处警系统
湖南省永州市新田县公安局指挥中心110/119/122三台合一接处警系统
西藏昌都地区江达县公安局指挥中心110/119/122三台合一接处警系统
湖南省岳阳市公安局交通警察支队122接警处警系统
山东省菏泽市公安局110自动语音回访系统
黑龙江省牡丹江市柴河林业局综合指挥中心110/119/122三台合一接处警系统
电力行业
江西省吉安市遂川县95598电力客户服务中心系统
内蒙古兴安盟乌兰浩特市电业局95598电力客户服务中心系统
内蒙托克托县电业局95598电力客户服务中心系统
江西省赣州市安远县/崇义县/大余县/定南县/赣县/会昌县/信丰县电业局95598电力客
户服务中心系统
广西壮族自治区河池市环江县电业总公司95598电力客户服务中心系统
包头市达茂(旗)电力有限责任公司95598电力客户服务中心系统
黑龙江省尚志市电力公司95598电力客户服务中心系统
燃气/热电/供暖行业
南宁市海方燃气有限责任公司客户服务中心(CallCenter)系统
威海第二热电集团有限公司客户服务热线呼叫中心&CRM一体化系统
南宁市金焰燃气有限责任公司客户服务中心(CallCenter/呼叫中心)系统
佛山市顺德兴顺燃气有限公司客户服务热线呼叫中心系统
南宁华侨投资区侨联燃气有限责任公司客户服务热线呼叫中心&CRM一体化系统
紧急救援/居家养老服务/智慧养老服务行业
重庆市九龙坡区民政局居家养老服务呼叫中心系统平台
福建省莆田市老龄工作委员会居家养老服务呼叫中心系统平台
泉州市民政局(泉州市老龄办)的泉州市居家养老服务信息呼叫中心平台
广州志朗电脑技术有限公司平安钟服务平台呼叫中心系统
北京万家安全系统有限公司居家养老信息服务系统
东莞市永华智能系统有限公司汽车GPS防盗防劫监控中心(110CAS报警中心)客户服务
热线系统
北京家健产业有限公司居家养老服务系统
顺德华峰实业有限公司110网络监控中心呼叫中心系统
劳动和社会保障行业
湖北省钟祥市劳动和社会保障局12333劳动和社会保障电话服务中心系统
广东省茂名市劳动和社会保障局12333劳动和社会保障电话咨询服务热线系统
广东省阳江市劳动和社会保障局12333劳动和社会保障电话咨询服务热线系统
广东省清远市劳动和社会保障局12333劳动和社会保障电话服务中心系统
交通运输/物流/汽车制造/地铁/城市轨道交通行业
东莞文一.红叶集团呼叫中心系统
香港昌机集团有限公司物流呼叫中心与车辆调度系统
宁夏北方飞扬贸易有限公司物流信息呼叫中心(CallCenter)系统
港铁轨道交通(深圳)有限公司/深圳地铁四号线客户服务热线呼叫中心系统
港铁轨道交通(深圳)有限公司/深圳地铁四号线客户服务热线呼叫中心系统的应急备
用系统
港铁轨道交通(深圳)有限公司/深圳地铁四号线客户服务热线呼叫中心系统UAT测试
机
重庆长安铃木汽车有限公司客户服务中心系统
重庆长安铃木汽车有限公司客户服务热线呼叫中心容灾系统
广电网络/数字电视/传媒行业
大连广播电视台新闻热线呼叫中心系统
云南广电网络集团有限公司大理分公司客户服务中心(呼叫中心)系统
云南省丽江市有线电视网络有限公司客户服务中心(呼叫中心)系统
云南广电网络集团有限公司昭通分公司客户服务中心(呼叫中心)系统
云南广电网络集团有限公司文山分公司客户服务中心(呼叫中心)系统
云南广电网络集团有限公司保山分公司客户服务中心(呼叫中心)系统
云南广电网络集团有限公司西双版纳分公司客户服务中心(呼叫中心)系统
旅游/旅行社/酒店行业
深圳枫叶酒店呼叫中心(电话订房)系统
深圳市世纪风行旅行社有限公司呼叫中心(CallCenter)系统
中青旅山水酒店投资管理有限公司呼叫中心(电话订房)系统
广州白天鹅宾馆(中国第一家中外合作的五星级宾馆)呼叫中心系统
广州市心友汇文化传播有限公司呼叫中心(CallCenter)系统
房地产行业
重庆港源房地产开发有限公司呼叫中心系统
深圳房地产信息网(/)呼叫中心系统
电话营销/电子商务/外包服务(BPO)行业
贵州四方鼎立咨询服务有限公司为贵州移动提供配套增值业务服务的外包呼叫中心系
统(含电话营销外呼系统)
广州剑奇贸易公司医疗保健电视购物呼叫中心系统
深圳市炫捷网络科技有限公司保险电话营销外包呼叫中心系统
无锡市美洋洋生活在线电话营销呼叫中心系统
深圳华强集团有限公司华强电子世界网客户服务中心系统
金融/保险行业
天安保险股份有限公司浙江分公司客户服务热线系统
深圳市信乐保险代理有限公司客户服务中心(CallCenter)系统
中国银行股份有限公司惠州分行(包括总部以及各个营业网点)电话录音系统
电信通信/运营商行业
新疆特力电信实业有限责任公司客户服务中心系统
中国网通(集团)有限公司天津市分公司"信息家园"内容认购综合认证平台
广州珠江电信设备制造有限公司客户服务中心(CallCenter)系统
城市管理/数字化城市行业
山东省淄博市淄川区城市管理行政执法局数字化城市监督指挥中心12319城管服务热
线呼叫中心系统
环境保护/环保局行业
贵州省毕节市环境监察支队(贵州省毕节市环境保护局)12369环保举报热线呼叫中心系
统
河南省新乡市12369环保投诉热线系统
宁夏回族自治区银川市环保局12369投诉热线系统
深圳市宝安区环保局客户服务中心(CallCenter)系统
江苏省无锡市环保局12369环保热线服务系统
上海市宝山区环保监测监控系统/12369环保热线服务系统
医院/医疗器械/医疗卫生行业
昆明市寻甸回族彝族自治县第一人民医院电话预约挂号呼叫中心系统
长沙三诺生物传感技术股份有限公司客户服务中心(CallCenter)系统
上海市杨浦区中心医院客户服务中心系统
大理市第二人民医院电话预约挂号呼叫中心系统
商务局
内蒙古自治区巴彦淖尔市商务局12312商务举报投诉服务热线系统(呼叫中心系统)
出入境检验检疫局/质量技术监督局
广西出入境检验检疫局12365举报处置指挥系统平台(呼叫中心系统)
海关
广东省江门海关统一服务热线系统
司法局
深圳市司法局电话语音声纹识别呼叫中心系统
福建省泉州市司法局12348法律服务热线系统
(constS:string);
begin
inheritedCreate;
SetSize(length(S));
ifSize>0then
begin
Write(S[1],Size);
Position:=0;
end;
end;
ring:string;
begin
SetLength(Result,Size);
ifSize>0then
begin
Position:=0;
Read(Result[1],length(Result));
end;
end;
{$ELSE}
//sethestandardTStringStream
type
TsdStringStream=TStringStream;
{$ENDIF}
//Utilityfunctions
functionMin(A,B:integer):integer;
begin
ifA
Result:=A
else
Result:=B;
end;
functionMax(A,B:integer):integer;
begin
ifA>Bthen
Result:=A
else
Result:=B;
end;
functionEscapeString(constAValue:string):string;
var
i:integer;
begin
Result:=AValue;
fori:=0tocEscapeCount-1do
Result:=StringReplace(Result,cEscapes[i],cReplaces[i],[rfReplaceAll]);
end;
functionUnEscapeStringUTF8(constAValue:string):string;
var
SearchStr,Reference,Replace:string;
i,Offset,Code:Integer;
W:word;
begin
SearchStr:=AValue;
Result:='';
whileSearchStr<>''do
begin
//find'&'
Offset:=AnsiPos('&',SearchStr);
ifOffset=0then
begin
//Nothingfound
Result:=Result+SearchStr;
Break;
end;
Result:=Result+Copy(SearchStr,1,Offset-1);
SearchStr:=Copy(SearchStr,Offset,MaxInt);
//findnext';'
Offset:=AnsiPos(';',SearchStr);
ifOffset=0then
begin
//Error:encountereda'&'butnota';'..wewillignore,justreturn
//theunmodifiedvalue
Result:=Result+SearchStr;
Break;
end;
//Reference
Reference:=copy(SearchStr,1,Offset);
SearchStr:=Copy(SearchStr,Offset+1,MaxInt);
Replace:=Reference;
//Seeifitisacharacterreference
ifcopy(Reference,1,2)=''then
begin
Reference:=copy(Reference,3,length(Reference)-3);
iflength(Reference)>0then
begin
iflowercase(Reference[1])='x'then
//Hexnotation
Reference[1]:='$';
Code:=StrToIntDef(Reference,-1);
if(Code>=0)and(Code<$FFFF)then
begin
W:=Code;
{$IFDEFD5UP}
Replace:=sdUnicodeToUtf8(WideChar(W));
{$ELSE}
Replace:=char(Wand$FF);
{$ENDIF}
end;
end;
endelse
begin
//Lookupdefaultescapes
fori:=0tocEscapeCount-1do
ifReference=cReplaces[i]then
begin
//Replace
Replace:=cEscapes[i];
Break;
end;
end;
//Newresult
Result:=Result+Replace;
end;
end;
functionUnEscapeStringANSI(constAValue:string):string;
var
SearchStr,Reference,Replace:string;
i,Offset,Code:Integer;
B:byte;
begin
SearchStr:=AValue;
Result:='';
whileSearchStr<>''do
begin
//find'&'
Offset:=AnsiPos('&',SearchStr);
ifOffset=0then
begin
//Nothingfound
Result:=Result+SearchStr;
Break;
end;
Result:=Result+Copy(SearchStr,1,Offset-1);
SearchStr:=Copy(SearchStr,Offset,MaxInt);
//findnext';'
Offset:=AnsiPos(';',SearchStr);
ifOffset=0then
begin
//Error:encountereda'&'butnota';'..wewillignore,justreturn
//theunmodifiedvalue
Result:=Result+SearchStr;
Break;
end;
//Reference
Reference:=copy(SearchStr,1,Offset);
SearchStr:=Copy(SearchStr,Offset+1,MaxInt);
Replace:=Reference;
//Seeifitisacharacterreference
ifcopy(Reference,1,2)=''then
begin
Reference:=copy(Reference,3,length(Reference)-3);
iflength(Reference)>0then
begin
iflowercase(Reference[1])='x'then
//Hexnotation
Reference[1]:='$';
Code:=StrToIntDef(Reference,-1);
if(Code>=0)and(Code<$FF)then
begin
B:=Code;
Replace:=char(B);
end;
end;
endelse
begin
//Lookupdefaultescapes
fori:=0tocEscapeCount-1do
ifReference=cReplaces[i]then
begin
//Replace
Replace:=cEscapes[i];
Break;
end;
end;
//Newresult
Result:=Result+Replace;
end;
end;
functionQuoteString(constAValue:string):string;
var
AQuoteChar:char;
begin
AQuoteChar:='"';
ifPos('"',AValue)>0then
AQuoteChar:='''';
{$IFDEFCLR}
Result:=QuotedStr(AValue,AQuoteChar);
{$ELSE}
Result:=AnsiQuotedStr(AValue,AQuoteChar);
{$ENDIF}
end;
functionUnQuoteString(constAValue:string):string;
{$IFNDEFCLR}
var
P:PChar;
{$ENDIF}
begin
ifLength(AValue)<2then
begin
Result:=AValue;
exit;
end;
ifAValue[1]incQuoteCharsthen
begin
{$IFDEFCLR}
Result:=DequotedStr(AValue,AValue[1]);
{$ELSE}
P:=PChar(AValue);
Result:=AnsiExtractQuotedStr(P,AValue[1]);
{$ENDIF}
endelse
Result:=AValue;
end;
functionAddControlChars(constAValue:string;constChars:string;Interval:integer):string;
//InsertCharsinAValueateachIntervalchars
var
i,j,ALength:integer;
//local
procedureInsertControlChars;
var
k:integer;
begin
fork:=1toLength(Chars)do
begin
Result[j]:=Chars[k];
inc(j);
end;
end;
//main
begin
if(Length(Chars)=0)or(Interval<=0)then
begin
Result:=AValue;
exit;
end;
//Calculatelengthbasedonoriginallengthandtotalextralengthforcontrolchars
ALength:=Length(AValue)+((Length(AValue)-1)divInterval+3)*Length(Chars);
SetLength(Result,ALength);
//Copyandinsert
j:=1;
fori:=1toLength(AValue)do
begin
if(imodInterval)=1then
//Insertcontrolchars
InsertControlChars;
Result[j]:=AValue[i];
inc(j);
end;
InsertControlChars;
//Adjustlength
dec(j);
ifALength>jthen
SetLength(Result,j);
end;
functionRemoveControlChars(constAValue:string):string;
//RemovecontrolcharactersfromstringinAValue
var
i,j:integer;
begin
Setlength(Result,Length(AValue));
i:=1;
j:=1;
whilei<=Length(AValue)do
ifAValue[i]incControlCharsthen
inc(i)
else
begin
Result[j]:=AValue[i];
inc(i);
inc(j);
end;
//Adjustlength
ifi<>jthen
SetLength(Result,j-1);
end;
functionFindString(constSubString:string;constS:string;Start,Close:integer;varAPos:integer):
boolean;
//CheckiftheSubstringmatchesthestringSinanypositioninintervalStarttoClose-1
//=Trueifanythingisfound.
//Note:thisfuntioniscase-insensitive
var
CharIndex:integer;
begin
Result:=False;
APos:=0;
forCharIndex:=StarttoClose-Length(SubString)do
ifMatchString(SubString,S,CharIndex)then
begin
APos:=CharIndex;
Result:=True;
exit;
end;
end;
functionMatchString(constSubString:string;constS:string;Start:integer):boolean;
//CheckiftheSubstringmatchesthestringSatpositionStart.
//Note:thisfuntioniscase-insensitive
var
CharIndex:integer;
begin
Result:=False;
//Checkrangejustincase
if(Length(S)-Start+1)
exit;
CharIndex:=0;
whileCharIndex
ifUpcase(SubString[CharIndex+1])=Upcase(S[Start+CharIndex])then
inc(CharIndex)
else
exit;
//Allcharswerethesame,sowesucceeded
Result:=True;
end;
随着经济的发展和社会信息化程度的提高,人们的生活质量和工作效率也越来越高,消费者
对企业的服务质量也提出了越来越高的要求。企业为了争夺客户资源
,必须能够准确把握住消费者的需求,并以最快的速度做出响应。
燃气公司面向市民经营燃气等特殊商品,有其固有的特点。由于面向庞大的用户群,燃气又
是关系千家万户生活的必需品,每一位用户的电话我们都必须作出快
速的响应,满足用户的需求。
同时,由于经营的商品危险性比较高,对安全供气和用户的安全用气的要求是及其严格的。
目前,燃气公司通常已经开通的热线有主要有业务热线、抢修热线和
送气预约热线,但这些热线往往不能覆盖并统筹管理整个服务层面,因此,无论是用户向燃
气公司索取服务,或燃气公司向用户提供服务,仍然存在许多不便,
服务响应速度和服务质量也无法得到有效的控制,不仅增加了服务成本,还制约了燃气供应
业务在本地区取得最大规模的发展。
此外,由于传统热线没有将客户数据、业务数据和业务流程整合起来,许多有价值的记录,
许多重复出现的问题,都淹没在日常工作中,对燃气公司进一步提升
运营管理水平,挖掘业务潜力,提高企业效益都极为不利。这将带来以下问题难以解决:
(1)电话是最原始的沟通手段,而且电话有它不可弥补的缺陷。电话只是1对1的服务,
如果有第2个人打电话进来只能听见占线的声音。如果访问量很大的话,
没有多少人能真正得到专业的指导。呼叫中心能够从根本上解决上述问题,而且系统运行正
常。
(2)客户欠款的催缴完全要通过人工拨号来实现,工作量很大。
(3)公司在下班时间后,难以为客户提供服务,难以做到全天候24小时的优质服务。
(4)难以事先了解客户信息、服务历史记录等相关信息,以便为其提供更有针对性的个性
化服务。
(5)难以针对客户的具体情况安排有特殊技能的话务员以满足客户的要求,对话务员的专
业水平要求较高。
(6)难以使客户得到"直通车"式的服务,客户可能拨打了多个电话,问题也得不到解决。
也就是难以实现"只要您一个电话,剩下的事情由我来做"。
(7)难以实现完善的客户信息管理、客户分析、业务分析等功能,为公司领导决策提供事
实依据。
随着公众电话的普及,越来越多的业务通过电话、传真的方式达成。有大量的燃气公司方面
基本法规等业务咨询电话、燃气公司费催缴电话、燃气抢修电话、投
诉电话、用户基本价查询/计费查询电话等,用户通过电话达成的业务已经占到燃气公司业
务的相当比例。由于各种业务电话分散,给客户带来诸多不便,同时,
燃气公司内部各部门也难以及时有效沟通,无法对外提供统一口径的服务。
同时随着外来燃气企业的不断涌现,燃气市场的竞争在不断加剧。同时,市场竞争的加剧和
生活条件的改善使得客户对服务质量的要求不断提高,以往的服务质
量已远远不能满足广大客户的需求。在这种情况下,只有以更完善、更高效、更优质的服务
来提高客户的满意度,增强自身的竞争能力。另一方面,对于企业的
内部管理来说,一成不变的管理模式不但不能满足日益扩展的业务需要,而且会在一定程度
上阻碍企业的发展。如何为客户提供"一个电话对外"和"一站式"的服
务便成了燃气公司最急待解决的课题。
随着近年来CTI技术和呼叫中心技术的蓬勃发展,使这一问题迎刃而解。我们能够方便地建
设一套技术先进、稳定高效、价格合理、适合于燃气公司的呼叫中心。
呼叫中心(CallCenter)是指以电话接入为主的呼叫响应中心,它为用户提供各种电话响应服
务。以CTI(计算机电话语音集成技术ComputerTelephony
Integration)技术为核心的呼叫中心是一个集语音技术、呼叫处理、计算机网络和数据库技
术于一体的系统。新一代的呼叫中心将计算机网络和通信网紧密结合
起来,这有利于把呼叫中心的技术平台与燃气公司现有的业务平台及业务数据库有机的结合
起来。
呼叫中心已经成为公认的改善服务的措施,对于燃气公司也不例外。
二、博域通讯燃气公司多媒体呼叫中心系统概述
燃气公司多媒体呼叫中心系统的基本需求如下:
人工座席数量不少于16个;
支持的通讯方式包括:电话,传真,手机;
支持不少于16路电话同时呼入;
支持不少于4路传真;
支持不少于16路IVR;
具有录音留言功能;
具有语音自动应答功能(IVR)/交互式传真应答功能(IFR),支持自动文本转语音(语音合成);
完成IVR导航(语音菜单提供普通话、广东话;文本合成为语音支持普通话)和播报;
完成座席电话转接和其他基本的话务功能;
座席具有软电话方式的主动呼出(电脑拨号打外线)功能;
实现ACD(自动坐席分配):系统将服务进行排队,然后把每一个服务都能传递给最合适的
话务员。服务的路由方法可以基于一些条件,例如,座席专业技能、空
闲率、最近解答这个客户的话务员等的信息分析,选出最合适的一个座席来为用户提供相应
的服务;
完成来电和客户资料自动显示(屏幕弹出),呼叫转移,基本系统维护管理功能,客户资料
管理功能,话务员技能分组。
主要业务功能:燃气公司方面基本法规等业务咨询用户基本价查询/气费查询,燃气抢修
申告投诉建议燃气公司费欠费催缴基本话务量和业务统计分析功能
燃气供应行业也是与百姓生活息息相关的一个公共服务事业,其用户数量庞大,服务内容丰
富、流程复杂,需要调动的业务部门多,用户对服务响应时间的要求
比较高,而且还涉及到报险抢修等紧急事故处理这样的特殊"服务"。
博域通讯燃气公司多媒体呼叫中心系统实现以统一的形象面向客户,充分利用了企业现有的
技术和资源,构筑了一个支持多种接入手段的统一接入路由、高质量
、高效率、互动的新一代客户综合服务系统,还能够在不改动系统结构的基础上以模块化方
式增加新业务。
博域通讯燃气公司多媒体呼叫中心系统采用一个特别易记的特别服务号码,向社会公布,客
户打入此电话号码进行信息查询、客户投诉建议等。客户打入电话后
,当系统的自动语音应答子系统无法解决客户问题时,客户可选择人工服务,由企业客户服
务代表直接接听客户电话,处理并解决客户问题。此时客户同座席话
务人员直接沟通,并同时记录下该客户的联系方式,将相关数据添加入系统数据库;也可以
在数据库的支持下回答信息查询等。客户也可以选择自动语音服务方
式,根据系统的语音提示输入按键,选择类别,进行修改查询密码,修改交接密码,修改交
接密文,查询客户资料。
本系统能够将数据库中每天收到的各种类型的信息进行整理后供查询,或将信息的统计报表
和其他的各种信息汇总输出,上报给相关部门或领导。各相关部门调
查处理结果和答复意见出来后,再由座席话务人员通知到本人。
也可由系统自动拨通联系电话,由系统通过传真或电脑语音自动播报调查处理结果和答复意
见来完成回馈。
功能丰富而强大的座席业务软件系统,减少了座席服务技能的差异,大大提高了业务处理效
率和服务水平。强大的统计分析工具有助于燃气公司了解客户需求,
为产品和服务调整,发展目标的制定提供强有力的数据支持。本系统建议采用基于计算机
语音板卡的语音接入方式,支持1号线路的接入,保障系统的可靠性和
稳定性,可以减少燃气公司一期工程投资,同时具有良好的系统性能。
博域通讯燃气公司多媒体呼叫中心系统在为企业提供各种各样的业务服务的同时,也向企业
提供详尽的维护管理功能。
三、博域通讯燃气公司多媒体呼叫中心系统的特色
博域通讯在国内率先采用最先进的第四代呼叫中心技术和自主研制的核心平台构建完整的
计算机电信集成(CTI)系统体系,以博域通讯一体化交换机呼叫中心平台
产品BYUNICC4.0/一体化呼叫中心平台产品BYICC2.0为技术平台,采用了具体业务和硬件分
离的设计原则,企业可根据自己的需要在基本硬件平台资源的基础上开
展多种多样的业务功能。
高智能的呼叫中心平台是建立高效的业务平台的基础,高稳定的呼叫中心平台是业务稳定运
行的基石,呼叫中心平台产品的功能和性能对客户服务中心的运营和管
理起着至关重要的作用,一体化交换机呼叫中心平台产品BYUNICC4.0/一体化呼叫中心平台
产品BYICC2.0作为业界领先的高度整合、无缝链接、性能卓越、运行稳
定、安装实施快速便捷、内置CRM功能(将呼叫中心收集到的顾客档案信息/业务咨询/业务
投诉/业务受理/主动回访/市场调查等信息进行录入/统计分析,实现统
一的客户信息管理,并及时反馈到企业产品开发以及管理决策上;实现与业务操作及企业/
政府部门的信息资源无缝集成,具有良好的企业数据融合能力和良好
的企业业务整合能力,已有的CRM系统能直接嵌入到一体化呼叫中心平台的人工座席软件
的操作界面;通过呼叫中心与客户关系管理系统相结合,实现对客户的个
性化和差异化服务,从而最终提高客户的满意度和忠诚度)、高性价比的一体化呼叫中心(CTI)
通讯平台,集成并固化了PBX/ACD/IVR/CTI/数字录音/语音信
箱/VOIP/TTS/传真/人工座席软件/短信/统计报表软件/维护管理工具软件/易学易用的二次开
发环境等核心的呼叫中心功能模块,实现了简单、高性能价格比的系
统构架,所有对平台和系统功能的修改、扩展等都不会影响到系统的正常使用,具有高度集
成的一体化技术解决方案、电信级的稳定性和迅速的灾难恢复能力、充
足的系统容量和平滑的扩展能力,以及超强的系统可维护行和高性价比等优异特性;广泛适
用于各类企业建设客户服务中心(呼叫中心,CALLCENTER)系统,政
府部门建设语音服务系统。一体化交换机呼叫中心平台产品BYUNICC4.0/一体化呼叫中心平
台产品BYICC2.0经过众多企业客户服务中心(呼叫中心,CALLCENTER
)系统以及政府部门语音服务系统的成功案例验证。
本系统具有以下几个方面的显著特点:
三层客户机/服务器软件体系结构
采用了国际领先的呼叫智能分配和路由技术,合理分配每个座席的呼叫话务量
引入自动文本转语音(TTS)技术
先进灵活的系统结构
易于和燃气公司内部MIS系统、抢修系统、营业系统高度集成,从而在信息化管理上
实现了对企业内部资源和外部资源的有效整合
话路、客户数据、操作界面的同步转移
完善的系统管理功能
严格的系统安全性设计我们主要从以下几个方面来考虑系统的安全性和可靠性设计:
双机集群,访问控制,信息传输安全,数据库安全,应用的安全
性,防病毒措施,安全备份,安全管理制度等。
支持分布式呼叫中心
电信级的应用水平
系统模块化的、领先的软硬件设计和一流性价比的的硬件设备,使得本燃气公司多媒体呼叫
中心系统达到了电信级的可靠性及可用性,性能稳定,能够保证在大
呼叫量下平稳运行。
四、博域通讯燃气公司多媒体呼叫中心系统的业务功能
客户利用电话、手机等拨打某一特服号码(如9xxxx)进入燃气公司多媒体呼叫中心系统,本
系统依托燃气公司各类业务技术支持系统和网络系统,通过人工受理或
自动语音服务等方式全天24小时不间断地为客户提供各种服务。
系统的业务功能结构如下图所示:
博域通讯燃气公司多媒体呼叫中心系统所实现的主要业务功能如下(可以根据燃气公司的要
求进行修改完善):
4.1业务咨询服务
在人工座席服务时或自动语音服务时,受理用户的业务咨询请求。主要包括:
燃气方面基本法规;
业务申办流程;
用气疑难解答等。
真正实现7*24小时业务申请服务:即使在无人值守的情况下,客户亦能通过拨打呼叫中心
热线电话号码,得到系统以语音方式进行的业务咨询服务;系统在人工
服务状态下,当业务代表输入客户名称时,系统即时将客户与企业相关的信息显示在座席终
端上,使业务及时了解客户,有针对性回答客户问题,使客户倍感亲
切。系统的自动话务分配(ACD)功能能根据客户需求,选择最合适的业务代表接听。企业
所有业务代表均是根据终端上显示回答客户,规范了语言,统一了回答
。客户有什么问题想要咨询,可以给系统工作人员留言,工作人员通过语音信箱回答客户
的问题,方便简捷。语音信箱将提供实时录音记录,避免信息遗漏。它
要求客户留下回电号码、相关问题内容及是否希望回复等信息,待座席代表有空闲时进行回
复,并将处理意见及时反馈给客户。
4.2业务查询服务
燃气公司将用户基本价,用户气费以语音,文档等方式存入系统,这样,客户通过拨打呼叫
中心热线电话,即能:☆以语音方式听取所需要的客户资料、公司
背景信息等;☆由业务代表根据终端显示,向客户进行回答问题;业务查询支持用户通
过电话、手机、传真等手段进行各种业务查询服务。
查询类业务主要提供两类服务,一类服务主要是面向客户提供对业务、服务等信息的查询;
另一类主要是面向燃气公司内部的工作人员提供有关业务资料、客户
档案等信息的查询。该类业务一方面解决了客户对业务、服务状态查询的需要,加强相互
的信任,提高服务水平;一方面又帮助了企业内部的工作人员,使他们
工作当中可以得到来自本系统的帮助。
4.3业务受理类服务
受理类业务是燃气公司多媒体呼叫中心系统的重要业务之一,也是建立优秀企业形象的主要
手段。该类业务主要包括以下几个主要内容:A通过受理功能,客户
可获得燃气抢修申告的及时受理服务。B客户信息管理客户信息包括客户编号、客户名称、
联系电话、地址、所属地区、地区编号、用户人口数、楼层等多项
,接听客户呼入电话,由座席代表记录信息形成档案,也可采用更为主动的呼出方式来确认、
核实、补充档案。
4.4用户投诉/意见建议受理
本呼叫中心系统可通过电话,手机,传真等各种接入手段接受用户的投诉,并及时处理或通
过特定的通信渠道转交给企业的处理部门处理,同时可根据处理的情
况及时回复用户,做到服务的闭环。
A当客户对燃气公司质量或输送管道,或对相关服务人员有意见时,可通过人工,留言信
箱,电话,手机,传真等方式,将自己的投诉存入系统。
B企业相关人员通过专用密码及时提取,统计,分析,及时处理,并将处理结果存入系统,
供客户查询。
主要内容包括如下:
投诉单的记录和录音功能;
投诉单的送发功能;
投诉单的处理功能;
投诉单的答复功能。对已受理的投诉举报或批评建议,系统自动生成唯一标识的受理流水
号。客户凭此流水号,可随时打电话进入系统了解处理情况。对已受
理的投诉举报或批评建议,由职能部门整理后,根据职责分工转对口部门处理。对本级部门
无法处理的举报,可采用自动或手工方式移交上级部门处理。本系统
可通过电话语音、传真等方式将处理结果及时反馈给客户。
4.5主动呼出服务
呼叫中心最具生命力的功能是呼出(OUTBOUND),通过呼出主动地为客户提供服务,才是
它的用武之地。通过这种主动的呼出,最终将为企业获取无可估量的利
润,将呼叫中心变成"利润中心"。呼出是广义的"呼出",即呼叫中心主动与客户联系的方
式,包括自动呼出、人工呼出、传真呼出,甚至上门拜访等。
利用呼叫中心自身具备的呼出功能,燃气公司可以根据自身的客户数据库主动联系客户,为
用户提供包括用户满意度调查、客户气费欠款的自动催缴等服务。A
、用户回访。了解用户对服务的满意度和具体意见。系统能在规定的时间内,按预先设置,
逐一拨号,通过主动地与固有客户,特别是大客户的联络,帮助客户
的实际问题,一方面可以加深客户感情,另一方面可以更好地把握客户需求的变化以不断改
进工作;燃气公司根据调查结果,进行统计分析,为再发展和决策提
供依据。B、客户气费欠款的自动催缴:大大减轻了工作人员的工作量,同时有助于资金的
回收,提高企业的经济效益。
4.6其他增值服务(可选)
可以根据燃气公司的要求进行定制。如:CRM-客户关系管理。
CRM系统功能描述:用户完整资料的建立与管理;用户使用中海物流服务的管理;客户营
销管理;客户综合分析。建议放在二期工程进行实施。
4.7因特网服务功能(可选)
结合Internet技术,提供客户网上自动响应,拓展服务功能;如可以在互联网上进行业务咨
询,业务查询,客户满意度调查,客户投诉建议等。采用Internet技
术,将因特网融入到本呼叫中心,实现与客户之间的Email服务、CallBack(呼叫回复)、交
互式文本交谈、浏览导航,提供网页连接/传送功能。建议放在二期
工程进行实施。
五、系统物理结构
博域通讯燃气公司呼叫中心系统由一体化交换机BYIPPBX4.0[集成并固化了PBX、CTI服务
器、ACD、IVR(交互式语音应答)服务、传真服务、VoIP、TTS服务、录
音留言服务、语音信箱服务、人工座席CTI接口、系统维护管理、数据库/录音服务器等]、
人工座席PC机(逻辑上分为:普通业务代表座席、专家/班长座席)、话
务员声导管耳机+耳机话务盒(可以采用普通电话机)、通信线路、网络系统等和呼叫中心支
撑平台(一体化交换机呼叫中心平台软件BYUNICC4.0)、经过定制的
交互式语音应答(IVR)应用软件、经过定制(或标准)的人工座席应用软件(包括录音管
理功能)、经过定制(或标准)的统计报表应用软件构成。
数据库服务器可以根据需要配置在局域网内的任何一台服务器上。
系统网络结构图如下:
博域通讯燃气公司呼叫中心系统人工座席软件示意图
博域通讯燃气公司呼叫中心系统统计报表软件示意图
博域通讯燃气公司呼叫中心系统统计报表软件示意图
硬件组成:
一体化交换机(集成并固化了PBX/ACD/IVR/CTI/数字录音/语音信箱/VOIP/TTS/传真/人工
座席软件/短信/统计报表软件/维护管理工具软件/易学易用的二
次开发环境等核心的呼叫中心功能模块);
人工座席使用的普通PC机若干台;
话务员耳机以及话务盒(或标准电话机)若干只;
局域网和配件以及通信线路(中继线路以及分机线路);
数据库服务器(对于中小型系统,可以使用一体化交换机兼作为数据库服务器);
WEB/EMAIL服务器(可选);
短信息网关服务器以及GPRS短信猫(可选)
软件组成:
底层支撑平台软件BYUNICCSS2.0;
自动语音流程(IVR/IFR)应用软件BYUNICCIVR2.0,可定制[可以利用产品内置的可视化
的IVR流程图形编辑环境进行编辑定制];
人工座席软件BYUNICCAgent2.0,可定制;
统计报表软件BYUNICCReport2.0,可定制;
业务应用网关软件BYUNICCGateWay2.0(可选),可定制;
同步录音管理软件BYUNICCRecMan2.0(可选);
系统维护管理软件BYUNICCManager2.0;
TTS语音合成引擎软件BYUNICCTTS2.0(可选);
自动传真收发软件BYUNICCFAX2.0(可选);
系统通信实时监控软件BYUNICCMONITOR2.0;
短信平台软件BYUNICCSMS2.0(可选)
五、深圳博域通讯一体化交换机呼叫中心平台产品BYUNICC4.0/一体化呼叫中心平台产品
BYICC2.0的部分燃气客户服务中心系统成功案例
南宁市安拓软件有限公司采用博域通讯一体化呼叫中心平台产品BYICC2.0开发建设南宁市
海方燃气有限责任公司客户服务中心(CallCenter)系统。(2009-6-19
)
procedureParseAttributes(constAValue:string;Start,Close:integer;Attributes:TStrings);
//ConverttheattributesstringAValuein[Start,Close-1]totheattributesstringlist
var
i:integer;
InQuotes:boolean;
AQuoteChar:char;
begin
InQuotes:=False;
AQuoteChar:='"';
ifnotassigned(Attributes)then
exit;
ifnotTrimPos(AValue,Start,Close)then
exit;
//Clearfirst
;
//Loopthroughcharacters
fori:=StarttoClose-1do
begin
//Inquotes?
ifInQuotesthen
begin
ifAValue[i]=AQuoteCharthen
InQuotes:=False;
endelse
begin
ifAValue[i]incQuoteCharsthen
begin
InQuotes:=True;
AQuoteChar:=AValue[i];
end;
end;
//Addattributestringsoneachcontrolcharbreak
ifnotInQuotesthen
ifAValue[i]incControlCharsthen
begin
ifi>Startthen
(copy(AValue,Start,i-Start));
Start:=i+1;
end;
end;
//Addlastattributestring
ifStart
(copy(AValue,Start,Close-Start));
//First-char"="signsshouldappendtoprevious
fori:=-1downto1do
ifAttributes[i][1]='='then
begin
Attributes[i-1]:=Attributes[i-1]+Attributes[i];
(i);
end;
//First-charquotesshouldappendtoprevious
fori:=-1downto1do
if(Attributes[i][1]incQuoteChars)and(Pos('=',Attributes[i-1])>0)then
begin
Attributes[i-1]:=Attributes[i-1]+Attributes[i];
(i);
end;
end;
functionTrimPos(constAValue:string;varStart,Close:integer):boolean;
//TrimthestringinAValuein[Start,Close-1]byadjustingStartandClosevariables
begin
//Checks
Start:=Max(1,Start);
Close:=Min(Length(AValue)+1,Close);
ifClose<=Startthen
begin
Result:=False;
exit;
end;
//Trimleft
while
(Start
(AValue[Start]incControlChars)do
inc(Start);
//Trimright
while
(Start
(AValue[Close-1]incControlChars)do
dec(Close);
//Dowehaveastringleft?
Result:=Close>Start;
end;
procedureWriteStringToStream(S:TStream;constAString:string);
begin
ifLength(AString)>0then
begin
{$IFDEFCLR}
(BytesOf(AString),Length(AString));
{$ELSE}
(AString[1],Length(AString));
{$ENDIF}
end;
end;
functionReadOpenTag(AReader:TsdSurplusReader):integer;
//TrytoreadthetypeofopentagfromS
var
AIndex,i:integer;
Found:boolean;
Ch:char;
Candidates:array[0..cTagCount-1]ofboolean;
Surplus:string;
begin
Surplus:='';
Result:=cTagCount-1;
fori:=0tocTagCount-1doCandidates[i]:=True;
AIndex:=1;
repeat
Found:=False;
inc(AIndex);
ar(Ch)=0then
exit;
Surplus:=Surplus+Ch;
fori:=cTagCount-1downto0do
ifCandidates[i]and(length(cTags[i].FStart)>=AIndex)then
begin
ifcTags[i].FStart[AIndex]=Chthen
begin
Found:=True;
iflength(cTags[i].FStart)=AIndexthen
Result:=i;
endelse
Candidates[i]:=False;
end;
untilFound=False;
//Thesurplusstringthatwealreadyread(everythingafterthetag)
s:=copy(Surplus,length(cTags[Result].FStart),length(Surplus));
end;
functionReadStringFromStreamUntil(AReader:TsdSurplusReader;constASearch:string;
varAValue:string;SkipQuotes:boolean):boolean;
var
AIndex,ValueIndex,SearchIndex:integer;
LastSearchChar,Ch:char;
InQuotes:boolean;
QuoteChar:Char;
SB:TsdStringBuilder;
begin
Result:=False;
InQuotes:=False;
//Getlastsearchstringcharacter
AIndex:=length(ASearch);
ifAIndex=0thenexit;
LastSearchChar:=ASearch[AIndex];
SB:=;
try
QuoteChar:=#0;
repeat
//Addcharacterstothevaluetobereturned
ar(Ch)=0then
exit;
r(Ch);
//Doweskipquotes?
ifSkipQuotesthen
begin
ifInQuotesthen
begin
if(Ch=QuoteChar)then
InQuotes:=false;
endelse
begin
ifChincQuoteCharsthen
begin
InQuotes:=true;
QuoteChar:=Ch;
end;
end;
end;
//Inquotes?Ifso,wedon'tchecktheendcondition
ifnotInQuotesthen
begin
//Isthelastcharthesameasthelastcharofthesearchstring?
ifCh=LastSearchCharthen
begin
//Checktoseeifthewholesearchstringispresent
ValueIndex:=-1;
SearchIndex:=length(ASearch)-1;
ifValueIndex
Result:=True;
while(SearchIndex>0)andResultdo
begin
Result:=SB[ValueIndex]=ASearch[SearchIndex];
dec(ValueIndex);
dec(SearchIndex);
end;
end;
end;
untilResult;
//Useonlythepartbeforethesearchstring
AValue:=Copy(1,-length(ASearch));
finally
;
end;
end;
functionReadStringFromStreamWithQuotes(S:TStream;constTerminator:string;
varAValue:string):boolean;
var
Ch,QuoteChar:char;
InQuotes:boolean;
SB:TsdStringBuilder;
begin
SB:=;
try
QuoteChar:=#0;
Result:=False;
InQuotes:=False;
repeat
(Ch,1)=0thenexit;
ifnotInQuotesthen
begin
if(Ch='"')or(Ch='''')then
begin
InQuotes:=True;
QuoteChar:=Ch;
end;
endelse
begin
ifCh=QuoteCharthen
InQuotes:=False;
end;
ifnotInQuotesand(Ch=Terminator)then
break;
r(Ch);
untilFalse;
AValue:=;
Result:=True;
finally
;
end;
end;
functionsdDateTimeFromString(constADate:string):TDateTime;
//ConvertthestringADatetoaTDateTimeaccordingtotheW3Cdate/timespecification
//asfoundhere:/TR/NOTE-datetime
var
AYear,AMonth,ADay,AHour,AMin,ASec,AMSec:word;
begin
AYear:=StrToInt(copy(ADate,1,4));
AMonth:=StrToInt(copy(ADate,6,2));
ADay:=StrToInt(copy(ADate,9,2));
ifLength(ADate)>16then
begin
AHour:=StrToInt(copy(ADate,12,2));
AMin:=StrToInt(copy(ADate,15,2));
ASec:=StrToIntDef(copy(ADate,18,2),0);//Theymightbeomitted,sodefaultto0
AMSec:=StrToIntDef(copy(ADate,21,3),0);//Theymightbeomitted,sodefaultto0
endelse
begin
AHour:=0;
AMin:=0;
ASec:=0;
AMSec:=0;
end;
Result:=
EncodeDate(AYear,AMonth,ADay)+
EncodeTime(AHour,AMin,ASec,AMSec);
end;
functionsdDateTimeFromStringDefault(constADate:string;ADefault:TDateTime):TDateTime;
//ConvertthestringADatetoaTDateTimeaccordingtotheW3Cdate/timespecification
//asfoundhere:/TR/NOTE-datetime
//Ifthereisaconversionerror,thedefaultvalueADefaultisreturned.
begin
try
Result:=sdDateTimeFromString(ADate);
except
Result:=ADefault;
end;
end;
functionsdDateTimeToString(ADate:TDateTime):string;
//ConverttheTDateTimeADatetoastringaccordingtotheW3Cdate/timespecification
//asfoundhere:/TR/NOTE-datetime
var
AYear,AMonth,ADay,AHour,AMin,ASec,AMSec:word;
begin
DecodeDate(ADate,AYear,AMonth,ADay);
DecodeTime(ADate,AHour,AMin,ASec,AMSec);
iffrac(ADate)=0then
Result:=Format('%.4d-%.2d-%.2d',[AYear,AMonth,ADay])
else
Result:=Format('%.4d-%.2d-%.2dT%.2d:%.2d:%.2d.%.3dZ',
[AYear,AMonth,ADay,AHour,AMin,ASec,AMSec]);
end;
functionsdWriteNumber(Value:double;SignificantDigits:integer;AllowScientific:boolean):
string;
const
Limits:array[1..9]ofinteger=
(10,100,1000,10000,100000,1000000,10000000,100000000,1000000000);
var
Limit,Limitd,PointPos,IntVal,ScPower:integer;
Body:string;
begin
if(SignificantDigits<1)or(SignificantDigits>9)then
(sxeSignificantDigitsOutOfRange);
//Zero
ifValue=0then
begin
Result:='0';
exit;
end;
//Sign
ifValue<0then
begin
Result:='-';
Value:=-Value;
endelse
Result:='';
//Determinepointposition
Limit:=Limits[SignificantDigits];
Limitd:=Limitdiv10;
PointPos:=SignificantDigits;
whileValue
begin
Value:=Value*10;
dec(PointPos);
end;
whileValue>=Limitdo
begin
Value:=Value*0.1;
inc(PointPos);
end;
//Round
IntVal:=round(Value);
//Exceptionalcasewhichhappenswhenthevalueroundsuptothelimit
ifIntval=Limitthen
begin
IntVal:=IntValdiv10;
inc(PointPos);
end;
//Stripoffanyzeros,thesereducesignificancecount
while(IntValmod10=0)and(PointPos
begin
dec(SignificantDigits);
IntVal:=IntValdiv10;
end;
//Checkforscientificnotation
ScPower:=0;
ifAllowScientificand((PointPos<-1)or(PointPos>SignificantDigits+2))then
begin
ScPower:=PointPos-1;
dec(PointPos,ScPower);
end;
//Body
Body:=IntToStr(IntVal);
whilePointPos>SignificantDigitsdo
begin
Body:=Body+'0';
inc(SignificantDigits);
end;
whilePointPos<0do
begin
Body:='0'+Body;
inc(PointPos);
end;
ifPointPos=0then
Body:='.'+Body
else
ifPointPos
Body:=copy(Body,1,PointPos)+'.'+copy(Body,PointPos+1,SignificantDigits);
//Finalresult
ifScPower=0then
Result:=Result+Body
else
Result:=Result+Body+'E'+IntToStr(ScPower);
end;
{$IFDEFCLR}
functionsdUnicodeToUtf8(constW:widestring):string;
begin
Result:=es(W);
end;
functionsdUtf8ToUnicode(constS:string):widestring;
begin
Result:=ing(BytesOf(S));
end;
functionEncodeBase64Buf(constBuffer:TBytes;Count:Integer):string;
begin
Result:=64String(Buffer,0,Count);
end;
functionEncodeBase64(constSource:string):string;
begin
Result:=64String(BytesOf(Source));
end;
procedureDecodeBase64Buf(constSource:string;varBuffer:TBytes;Count:Integer);
var
ADecoded:TBytes;
begin
ADecoded:=se64String(Source);
ifCount>Length(ADecoded)then
(sxeMissingDataInBinaryStream);
SetLength(ADecoded,Count);
Buffer:=ADecoded;
end;
functionDecodeBase64(constSource:string):string;
begin
Result:=AnsiString(se64String(Source));
end;
{$ELSE}
functionPtrUnicodeToUtf8(Dest:PChar;MaxDestBytes:Cardinal;Source:PWideChar;
SourceChars:Cardinal):Cardinal;
var
i,count:Cardinal;
c:Cardinal;
begin
Result:=0;
ifnotassigned(Source)ornotassigned(Dest)then
exit;
count:=0;
i:=0;
while(i
begin
c:=Cardinal(Source[i]);
Inc(i);
ifc<=$7Fthen
begin
Dest[count]:=Char(c);
Inc(count);
endelse
ifc>$7FFthen
begin
ifcount+3>MaxDestBytesthen
break;
Dest[count]:=Char($E0or(cshr12));
Dest[count+1]:=Char($80or((cshr6)and$3F));
Dest[count+2]:=Char($80or(cand$3F));
Inc(count,3);
endelse
begin//$7F
ifcount+2>MaxDestBytesthen
break;
Dest[count]:=Char($C0or(cshr6));
Dest[count+1]:=Char($80or(cand$3F));
Inc(count,2);
end;
end;
ifcount>=MaxDestBytesthen
count:=MaxDestBytes-1;
Dest[count]:=#0;
Result:=count+1;//convertzerobasedindextobytecount
end;
functionPtrUtf8ToUnicode(Dest:PWideChar;MaxDestChars:Cardinal;Source:PChar;
SourceBytes:Cardinal):Cardinal;
var
i,count:Cardinal;
c:Byte;
wc:Cardinal;
begin
ifnotassigned(Dest)ornotassigned(Source)then
begin
Result:=0;
Exit;
end;
Result:=Cardinal(-1);
count:=0;
i:=0;
while(i
begin
wc:=Cardinal(Source[i]);
Inc(i);
if(wcand$80)<>0then
begin
ifi>=SourceBytesthen
//incompletemultibytechar
Exit;
wc:=wcand$3F;
if(wcand$20)<>0then
begin
c:=Byte(Source[i]);
Inc(i);
if(cand$C0)<>$80then
//malformedtrailbyteoroutofrangechar
Exit;
ifi>=SourceBytesthen
//incompletemultibytechar
Exit;
wc:=(wcshl6)or(cand$3F);
end;
c:=Byte(Source[i]);
Inc(i);
if(cand$C0)<>$80then
//malformedtrailbyte
Exit;
Dest[count]:=WideChar((wcshl6)or(cand$3F));
endelse
Dest[count]:=WideChar(wc);
Inc(count);
end;
ifcount>=MaxDestCharsthen
count:=MaxDestChars-1;
Dest[count]:=#0;
Result:=count+1;
end;
functionsdUnicodeToUtf8(constW:widestring):string;
var
L:integer;
Temp:string;
begin
Result:='';
ifW=''thenExit;
SetLength(Temp,Length(W)*3);//SetLengthincludesspacefornullterminator
L:=PtrUnicodeToUtf8(PChar(Temp),Length(Temp)+1,PWideChar(W),Length(W));
ifL>0then
SetLength(Temp,L-1)
else
Temp:='';
Result:=Temp;
end;
functionsdUtf8ToUnicode(constS:string):widestring;
var
L:Integer;
Temp:WideString;
begin
Result:='';
ifS=''thenExit;
SetLength(Temp,Length(S));
L:=PtrUtf8ToUnicode(PWideChar(Temp),Length(Temp)+1,PChar(S),Length(S));
ifL>0then
SetLength(Temp,L-1)
else
Temp:='';
Result:=Temp;
end;
functionEncodeBase64Buf(constBuffer;Count:Integer):string;
var
i,j:integer;
ACore:integer;
ALong:cardinal;
S:PByte;
begin
//MakesureASizeisalwaysamultipleof3,andthismultiple
//getssavedas4characters
ACore:=(Count+2)div3;
//Setthelengthofthestringthatstoresencodedcharacters
SetLength(Result,ACore*4);
S:=@Buffer;
//DotheloopACoretimes
fori:=0toACore-1do
begin
ALong:=0;
forj:=0to2do
begin
ALong:=ALongshl8+S^;
inc(S);
end;
forj:=0to3do
begin
Result[i*4+4-j]:=cBase64Char[ALongand$3F];
ALong:=ALongshr6;
end;
end;
//ForcomformitytoBase64,wemustpadthedatainsteadofzeroout
//ifthesizeisnotanexactmultipleof3
caseACore*3-Countof
0:;//nothingtodo
1://padonebyte
Result[ACore*4]:=cBase64PadChar;
2://padtwobytes
begin
Result[ACore*4]:=cBase64PadChar;
Result[ACore*4-1]:=cBase64PadChar;
end;
end;//case
end;
functionEncodeBase64(constSource:string):string;
//ctionreturnstheBASE64encoded
//dataasstring,withoutanylinebreaks.
begin
iflength(Source)>0then
Result:=EncodeBase64Buf(Source[1],length(Source))
else
Result:='';
end;
procedureDecodeBase64Buf(varSource:string;varBuffer;Count:Integer);
var
i,j:integer;
BufPos,Core:integer;
LongVal:cardinal;
D:PByte;
Map:array[Char]ofbyte;
begin
//Core*4isthenumberofcharstoread-checklength
Core:=Length(Source)div4;
ifCount>Core*3then
(sxeMissingDataInBinaryStream);
//Preparemap
fori:=0to63do
Map[cBase64Char[i]]:=i;
D:=@Buffer;
//Checkforfinalpadding,andreplacewith"zeros".Therecanbe
//atmaxtwopadchars('=')
BufPos:=length(Source);
if(BufPos>0)and(Source[BufPos]=cBase64PadChar)then
begin
Source[BufPos]:=cBase64Char[0];
dec(BufPos);
if(BufPos>0)and(Source[BufPos]=cBase64PadChar)then
Source[BufPos]:=cBase64Char[0];
end;
//DothisCoretimes
fori:=0toCore-1do
begin
LongVal:=0;
//Unrollthecharacters
forj:=0to3do
LongVal:=LongValshl6+Map[Source[i*4+j+1]];
//andunrollthebytes
forj:=2downto0do
begin
//Checkovershoot
ifinteger(D)-integer(@Buffer)>=Countthen
exit;
D^:=LongValshr(j*8)and$FF;
inc(D);
end;
end;
end;
functionDecodeBase64(constSource:string):string;
//ctionreturnsthebinary
//tringStreamtoconvertthisdatatoastream.
var
BufData:string;
BufSize,BufPos:integer;
begin
BufData:=RemoveControlChars(Source);
//Determinelengthofdata
BufSize:=length(BufData)div4;
ifBufSize*4<>length(BufData)then
(sxeErrorCalcStreamLength);
BufSize:=BufSize*3;
//Checkpaddingchars
BufPos:=length(BufData);
if(BufPos>0)and(BufData[BufPos]=cBase64PadChar)then
begin
dec(BufPos);
dec(BufSize);
if(BufPos>0)and(BufData[BufPos]=cBase64PadChar)then
dec(BufSize);
end;
Setlength(Result,BufSize);
//Decode
ifBufSize>0then
DecodeBase64Buf(BufData,Result[1],BufSize);
end;
{$ENDIF}
functionsdAnsiToUtf8(constS:string):string;
begin
Result:=sdUnicodeToUtf8(S);
end;
functionsdUtf8ToAnsi(constS:string):string;
begin
Result:=sdUtf8ToUnicode(S);
end;
functionEncodeBinHexBuf(constSource;Count:Integer):string;
//ctionreturnstheBINHEXencoded
//dataasstring,withoutanylinebreaks.
var
{$IFDEFCLR}
Text:TBytes;
{$ELSE}
Text:string;
{$ENDIF}
begin
SetLength(Text,Count*2);
{$IFDEFCLR}
BinToHex(TBytes(Source),0,Text,0,Count);
{$ELSE}
{$IFDEFD4UP}
BinToHex(PChar(@Source),PChar(Text),Count);
{$ELSE}
(sxeUnsupportedEncoding);
{$ENDIF}
{$ENDIF}
Result:=Text;
end;
functionEncodeBinHex(constSource:string):string;
//ctionreturnstheBINHEXencoded
//dataasstring,withoutanylinebreaks.
var
{$IFDEFCLR}
Text:TBytes;
{$ELSE}
Text:string;
{$ENDIF}
begin
SetLength(Text,Length(Source)*2);
{$IFDEFCLR}
BinToHex(BytesOf(Source),0,Text,0,Length(Source));
{$ELSE}
{$IFDEFD4UP}
BinToHex(PChar(Source),PChar(Text),Length(Source));
{$ELSE}
(sxeUnsupportedEncoding);
{$ENDIF}
{$ENDIF}
Result:=Text;
end;
procedureDecodeBinHexBuf(constSource:string;varBuffer{$IFDEFCLR}:TBytes{$ENDIF};Count:
Integer);
//DecodeBINHEXdatainSourceintobinarydata.
begin
ifLength(Source)div2
(sxeMissingDataInBinaryStream);
{$IFDEFCLR}
HexToBin(BytesOf(Source),0,Buffer,0,Count);
{$ELSE}
{$IFDEFD4UP}
HexToBin(PChar(Source),PChar(@Buffer),Count);
{$ELSE}
(sxeUnsupportedEncoding);
{$ENDIF}
{$ENDIF}
end;
functionDecodeBinHex(constSource:string):string;
//ctionreturnsthebinary
//tringStreamtoconvertthisdatatoastream.
var
AData:string;
ASize:integer;
{$IFDEFCLR}
Buffer:TBytes;
{$ELSE}
Buffer:string;
{$ENDIF}
begin
AData:=RemoveControlChars(Source);
//Determinelengthofdata
ASize:=length(AData)div2;
ifASize*2<>length(AData)then
(sxeErrorCalcStreamLength);
SetLength(Buffer,ASize);
{$IFDEFCLR}
HexToBin(BytesOf(AData),0,Buffer,0,ASize);
{$ELSE}
{$IFDEFD4UP}
HexToBin(PChar(AData),PChar(Buffer),ASize);
{$ELSE}
(sxeUnsupportedEncoding);
{$ENDIF}
{$ENDIF}
Result:=Buffer;
end;
functionsdStringToBool(constAValue:string):boolean;
var
Ch:Char;
begin
ifLength(AValue)>0then
begin
Ch:=UpCase(AValue[1]);
ifChin['T','Y']then
begin
Result:=True;
exit;
end;
ifChin['F','N']then
begin
Result:=False;
exit;
end;
end;
(sxeCannotConverToBool);
end;
functionsdStringFromBool(ABool:boolean):string;
const
cBoolValues:array[boolean]ofstring=('False','True');
begin
Result:=cBoolValues[ABool];
end;
{TXmlNode}
arsing:boolean;
begin
Result:=assigned(Document)arsing;
end;
(Source:TPersistent);
var
i:integer;
Node:TXmlNode;
begin
ifSourceisTXmlNodethen
begin
//Clearfirst
Clear;
//Properties
FElementType:=TXmlNode(Source).FElementType;
FName:=TXmlNode(Source).FName;
FTag:=TXmlNode(Source).FTag;
FValue:=TXmlNode(Source).FValue;
//Attributes
ifassigned(TXmlNode(Source).FAttributes)then
begin
CheckCreateAttributesList;
(TXmlNode(Source).FAttributes);
end;
//Nodes
fori:=0toTXmlNode(Source).NodeCount-1do
begin
Node:=NodeNew('');
(TXmlNode(Source).Nodes[i]);
end;
endelse
ifSourceisTNativeXmlthen
begin
Assign(TNativeXml(Source).FRootNodes);
endelse
inherited;
end;
uteAdd(constAName,AValue:string);
var
Attr:string;
begin
Attr:=Format('%s=%s',[AName,QuoteString(EscapeString(AValue))]);
CheckCreateAttributesList;
(Attr);
end;
{$IFDEFD4UP}
uteAdd(constAName:string;AValue:integer);
begin
AttributeAdd(AName,IntToStr(AValue));
end;
{$ENDIF}
uteDelete(Index:integer);
begin
if(Index>=0)and(Index
(Index);
end;
uteExchange(Index1,Index2:integer);
var
Temp:string;
begin
if(Index1<>Index2)and
(Index1>=0)and(Index1<)and
(Index2>=0)and(Index2<)then
begin
Temp:=FAttributes[Index1];
FAttributes[Index1]:=FAttributes[Index2];
FAttributes[Index2]:=Temp;
end;
end;
uteIndexByname(constAName:string):integer;
//ReturntheindexoftheattributewithnameAName,or-1ifnotfound
var
i:integer;
begin
Result:=-1;
fori:=0toAttributeCount-1do
ifAnsiCompareText(AttributeName[i],AName)=0then
begin
Result:=i;
exit;
end;
end;
utesClear;
begin
FreeAndNil(FAttributes);
end;
Length:integer;
var
BufData:string;
BufPos:integer;
begin
BufData:=RemoveControlChars(FValue);
caseBinaryEncodingof
xbeBinHex:
begin
Result:=length(BufData)div2;
ifResult*2<>length(BufData)then
(sxeErrorCalcStreamLength);
end;
xbeBase64:
begin
Result:=length(BufData)div4;
ifResult*4<>length(BufData)then
(sxeErrorCalcStreamLength);
Result:=Result*3;
//Checkpaddingchars
BufPos:=length(BufData);
if(BufPos>0)and(BufData[BufPos]=cBase64PadChar)then
begin
dec(BufPos);
dec(Result);
if(BufPos>0)and(BufData[BufPos]=cBase64PadChar)then
dec(Result);
end;
end;
else
Result:=0;//avoidcompilerwarning
end;
end;
Read(varBuffer{$IFDEFCLR}:TBytes{$ENDIF};Count:Integer);
//ReaddatafromXMLbinhextothebuffer
var
BufData:string;
begin
BufData:=RemoveControlChars(FValue);
caseBinaryEncodingof
xbeBinHex:
DecodeBinHexBuf(BufData,Buffer,Count);
xbeBase64:
DecodeBase64Buf(BufData,Buffer,Count);
end;
end;
Write(constBuffer{$IFDEFCLR}:TBytes{$ENDIF};Count:Integer);
//WritedatafromthebuffertoXMLinbinhexformat
var
BufData:string;
begin
ifCount>0then
caseBinaryEncodingof
xbeBinHex:
BufData:=EncodeBinHexBuf(Buffer,Count);
xbeBase64:
BufData:=EncodeBase64Buf(Buffer,Count);
end;
//ForcomformitywithBase64,wemustaddlinebreakseach76characters
FValue:=AddControlChars(BufData,GetLineFeed+GetIndent,76);
end;
Document(ADocument:TNativeXml);
var
i:integer;
begin
FDocument:=ADocument;
fori:=0toNodeCount-1do
Nodes[i].ChangeDocument(ADocument);
end;
reateAttributesList;
begin
ifnotassigned(FAttributes)then
begin
FAttributes:=;
ifassigned(FDocument)then
:=tributes;
end;
end;
;
begin
//Name+value
FName:='';
FValue:='';
//Clearattributesandnodes
AttributesClear;
NodesClear;
end;
eNodeName(constNodeName:string):integer;
begin
//ComparewithFullPathorlocalnamebasedonNodeName'sfirstcharacter
iflength(NodeName)>0then
ifNodeName[1]='/'then
begin
//FullPath
Result:=AnsiCompareText(FullPath,NodeName);
exit;
end;
//localname
Result:=AnsiCompareText(Name,NodeName);
end;
(ADocument:TNativeXml);
begin
inheritedCreate;
FDocument:=ADocument;
end;
Name(ADocument:TNativeXml;
constAName:string);
begin
Create(ADocument);
Name:=AName;
end;
NameValue(ADocument:TNativeXml;constAName,
AValue:string);
begin
Create(ADocument);
Name:=AName;
ValueAsString:=AValue;
end;
Type(ADocument:TNativeXml;
AType:TXmlElementType);
begin
Create(ADocument);
FElementType:=AType;
end;
;
begin
ifassigned(Parent)then
move(Self);
end;
EmptyAttributes;
var
i:integer;
V:string;
begin
fori:=AttributeCount-1downto0do
begin
V:=AttributeValue[i];
iflength(V)=0then
(i);
end;
end;
EmptyNodes;
var
i:integer;
Node:TXmlNode;
begin
fori:=NodeCount-1downto0do
begin
Node:=Nodes[i];
//Recursivecall
EmptyNodes;
//Checkifweshoulddeletechildnode
ythen
NodeDelete(i);
end;
end;
y;
begin
NodesClear;
AttributesClear;
inherited;
end;
de(constNodeName:string):TXmlNode;
//rytotheNodeByName
//function,thisfunctionwillsearchthewholesubnodetree,usingthe
//DepthFirstmethod.
var
i:integer;
begin
Result:=nil;
//Loopthroughallsubnodes
fori:=0toNodeCount-1do
begin
Result:=Nodes[i];
//IfthesubnodehasnameNodeNamethenwehavearesult,exit
eNodeName(NodeName)=0then
exit;
//Ifnot,wewillsearchthesubtreeofthisnode
Result:=de(NodeName);
ifassigned(Result)then
exit;
end;
end;
des(constNodeName:string;constAList:TList);
//local
procedureFindNodesRecursive(ANode:TXmlNode;AList:TList);
var
i:integer;
begin
withANodedo
fori:=0toNodeCount-1do
begin
ifNodes[i].CompareNodeName(NodeName)=0then
(Nodes[i]);
FindNodesRecursive(Nodes[i],AList);
end;
end;
//main
begin
;
FindNodesRecursive(Self,AList);
end;
llowScientific:boolean;
begin
ifassigned(Document)then
Result:=llowScientific
else
Result:=cDefaultFloatAllowScientific;
end;
ignificantDigits:integer;
begin
ifassigned(Document)then
Result:=ignificantDigits
else
Result:=cDefaultFloatSignificantDigits;
end;
siString(consts:string):string;
begin
ifUtf8Encodedthen
Result:=sdAnsiToUtf8(s)
else
Result:=s;
end;
destring(constW:widestring):string;
begin
ifUtf8Encodedthen
Result:=sdUnicodeToUtf8(W)
else
Result:=W;
end;
ributeByName(constAName:string):string;
begin
ifassigned(FAttributes)then
Result:=UnEscapeString(UnQuoteString([AName]))
else
Result:='';
end;
ributeByNameWide(constAName:string):widestring;
begin
Result:=ToWidestring(GetAttributeByName(AName));
end;
ributeCount:integer;
begin
ifassigned(FAttributes)then
Result:=
else
Result:=0;
end;
ributeName(Index:integer):string;
begin
if(Index>=0)and(Index
Result:=[Index];
end;
ributePair(Index:integer):string;
begin
if(Index>=0)and(Index
Result:=FAttributes[Index];
end;
ributeValue(Index:integer):string;
var
P:integer;
S:string;
begin
Result:='';
if(Index>=0)and(Index
begin
S:=FAttributes[Index];
P:=AnsiPos('=',S);
ifP>0then
Result:=UnEscapeString(UnQuoteString(Copy(S,P+1,MaxInt)));
end;
end;
ributeValueAsInteger(Index:integer):integer;
begin
Result:=StrToIntDef(GetAttributeValue(Index),0);
end;
ributeValueAsWidestring(Index:integer):widestring;
begin
Result:=ToWidestring(GetAttributeValue(Index));
end;
ributeValueDirect(Index:integer):string;
var
P:integer;
S:string;
begin
Result:='';
if(Index>=0)and(Index
begin
S:=FAttributes[Index];
P:=AnsiPos('=',S);
ifP>0then
Result:=UnQuoteString(Copy(S,P+1,MaxInt));
end;
end;
aryEncoding:TBinaryEncodingType;
begin
Result:=xbeBinHex;
ifassigned(Document)then
Result:=Encoding;
end;
aryString:string;
//GetthebinarycontentsofthisnodeasBase64andreturnitasastring
var
OldEncoding:TBinaryEncodingType;
{$IFDEFCLR}
Buffer:TBytes;
{$ENDIF}
begin
//Settobase64
OldEncoding:=BinaryEncoding;
try
BinaryEncoding:=xbeBase64;
{$IFDEFCLR}
SetLength(Buffer,BufferLength);
iflength(Buffer)>0then
BufferRead(Buffer,length(Buffer));
Result:=Buffer;
{$ELSE}
SetLength(Result,BufferLength);
iflength(Result)>0then
BufferRead(Result[1],length(Result));
{$ENDIF}
finally
BinaryEncoding:=OldEncoding;
end;
end;
cadedName:string;
//Returnthename+indexandallpredecessorswithunderscorestoseparate,in
//ordertogetauniquereferencethatcanbeusedinfilenames
var
LName:string;
begin
LName:=Format('%s%.4d',[Name,StrToIntDef(AttributeByName['Index'],0)]);
ifassigned(Parent)then
Result:=Format('%s_%s',[edName,LName])
else
Result:=LName;
end;
lPath:string;
//GetFullpathwillreturnthecompletepathofthenodefromtheroot,e.g.
///Root/SubNode1/SubNode2/ThisNode
begin
Result:='/'+Name;
ifTreedepth>0then
//Recursivecall
Result:=lPath+Result;
end;
ent:string;
var
i:integer;
begin
ifassigned(Document)then
begin
matof
xfCompact:Result:='';
xfReadable:
fori:=0toTreeDepth-1do
Result:=Result+String;
end;//case
endelse
Result:=''
end;
eFeed:string;
begin
ifassigned(Document)then
begin
matof
xfCompact:Result:='';
xfReadable:Result:=#13#10;
else
Result:=#10;
end;//case
endelse
Result:='';
end;
eCount:integer;
begin
ifAssigned(FNodes)then
Result:=
else
Result:=0;
end;
es(Index:integer):TXmlNode;
begin
if(Index>=0)and(Index
Result:=TXmlNode(FNodes[Index])
else
Result:=nil;
end;
alNodeCount:integer;
var
i:integer;
begin
Result:=NodeCount;
fori:=0toNodeCount-1do
inc(Result,Nodes[i].TotalNodeCount);
end;
eDepth:integer;
begin
Result:=-1;
ifassigned(Parent)then
Result:=pth+1;
end;
ueAsBool:boolean;
begin
Result:=sdStringToBool(FValue);
end;
ueAsDateTime:TDateTime;
begin
Result:=sdDateTimeFromString(ValueAsString);
end;
ueAsFloat:double;
var
Code:integer;
begin
val(StringReplace(FValue,',','.',[]),Result,Code);
ifCode>0then
(sxeCannotConvertToFloat);
end;
ueAsInt64:int64;
begin
Result:=StrToInt64(FValue);
end;
ueAsInteger:integer;
begin
Result:=StrToInt(FValue);
end;
ueAsString:string;
begin
Result:=UnEscapeString(FValue);
end;
ueAsWidestring:widestring;
begin
Result:=ToWidestring(ValueAsString);
end;
teOnDefault:boolean;
begin
Result:=True;
ifassigned(Document)then
Result:=nDefault;
end;
ribute(constAName:string):boolean;
var
i:integer;
begin
Result:=False;
fori:=0toAttributeCount-1do
ifAnsiCompareText(AName,AttributeName[i])=0then
begin
Result:=True;
exit;
end;
end;
nParent:integer;
//Retrieveourindexintheparent'snodelist
var
i:integer;
begin
Result:=-1;
ifassigned(Parent)then
fori:=unt-1do
ifSelf=[i]then
begin
Result:=i;
exit;
end;
end;
r:boolean;
begin
Result:=(Length(FName)=0)andIsEmpty;
end;
y:boolean;
begin
Result:=(Length(FValue)=0)and(NodeCount=0)and(AttributeCount=0);
end;
lTo(ANode:TXmlNode;Options:TXmlCompareOptions;
MismatchNodes:TList):boolean;
var
i,Index:integer;
NodeResult,ChildResult:boolean;
begin
//Startwithanegativeresult
Result:=False;
NodeResult:=False;
ifnotassigned(ANode)then
exit;
//Assumechildsequalsothernode'schilds
ChildResult:=True;
//childnodenamesandvalues-thiscomesfirsttoassurethelistsarefilled
if(xcChildNamesinOptions)or(xcChildValuesinOptions)or(xcRecursiveinOptions)then
fori:=0toNodeCount-1do
begin
//Dochildnamecheck
Index:=dexByName(Nodes[i].Name);
//Dowehavethechildnodeintheother?
ifIndex<0then
begin
//Nowedonthaveit
ifxcChildNamesinOptionsthen
begin
ifassigned(MismatchNodes)(Nodes[i]);
ChildResult:=False;
end;
endelse
begin
//Dochildvaluecheck
ifxcChildValuesinOptionsthen
ifAnsiCompareText(Nodes[i].ValueAsString,[Index].ValueAsString)<>0
then
begin
ifassigned(MismatchNodes)then
(Nodes[i]);
ChildResult:=False;
end;
//Dorecursivecheck
ifxcRecursiveinOptionsthen
ifnotNodes[i].IsEqualTo([Index],Options,MismatchNodes)then
ChildResult:=False;
end;
end;
try
//Weassumetherearedifferences
NodeResult:=False;
//Nodename,typeandvalue
ifxcNodeNameinOptionsthen
ifAnsiCompareText(Name,)<>0then
exit;
ifxcNodeTypeinOptionsthen
ifElementType<>tTypethen
exit;
ifxcNodeValueinOptionsthen
ifAnsiCompareText(ValueAsString,sString)<>0then
exit;
//attributecount
ifxcAttribCountinOptionsthen
ifAttributeCount<>uteCountthen
exit;
//attributenamesandvalues
if(xcAttribNamesinOptions)or(xcAttribValuesinOptions)then
fori:=0toAttributeCount-1do
begin
Index:=uteIndexByName(AttributeName[i]);
ifIndex<0then
ifxcAttribNamesinOptionsthen
exit
else
continue;
ifxcAttribValuesinOptionsthen
ifAnsiCompareText(AttributeValue[i],uteValue[Index])<>0then
exit;
end;
//childnodecount
ifxcChildCountinOptionsthen
ifNodeCount<>untthen
exit;
//Ifwearrivehere,itmeansnodifferenceswerefound,returnTrue
NodeResult:=True;
finally
Result:=ChildResultandNodeResult;
if(notNodeResult)andassigned(MismatchNodes)then
(0,Self);
end;
end;
d(ANode:TXmlNode):integer;
begin
ifassigned(ANode)then
begin
:=Self;
Document(Document);
ifnotassigned(FNodes)then
FNodes:=;
Result:=(ANode);
endelse
Result:=-1;
end;
AttributeValue(constNodeName,AttribName,AttribValue:string;
ShouldRecurse:boolean):TXmlNode;
//Thisfunctionreturnsapointertothefirstsubnodethathasanattributewith
//nameAttribNameandvalueAttribValue.
var
i:integer;
Node:TXmlNode;
begin
Result:=nil;
//Findallnodesthatarepotentialresults
fori:=0toNodeCount-1do
begin
Node:=Nodes[i];
if(AnsiCompareText(,NodeName)=0)and
ribute(AttribName)and
(AnsiCompareText(uteByName[AttribName],AttribValue)=0)then
begin
Result:=Node;
exit;
end;
//Recursivecall
ifShouldRecursethen
Result:=AttributeValue(NodeName,AttribName,AttribValue,True);
ifassigned(Result)then
exit;
end;
end;
ElementType(ElementType:TXmlElementType):TXmlNode;
var
i:integer;
begin
Result:=nil;
fori:=0toNodeCount-1do
ifNodes[i].ElementType=ElementTypethen
begin
Result:=Nodes[i];
exit;
end;
end;
Name(constAName:string):TXmlNode;
var
i:integer;
begin
Result:=nil;
fori:=0toNodeCount-1do
ifAnsiCompareText(Nodes[i].Name,AName)=0then
begin
Result:=Nodes[i];
exit;
end;
end;
lete(Index:integer);
begin
if(Index>=0)and(Index
begin
TXmlNode(FNodes[Index]).Free;
(Index);
end;
end;
change(Index1,Index2:integer);
begin
if(Index1>=0)and(Index1
(Index2>=0)and(Index2
ge(Index1,Index2);
end;
tract(ANode:TXmlNode):TXmlNode;
var
Index:integer;
begin
//CompatibilitywithDelphi4
Result:=nil;
ifassigned(FNodes)then
begin
Index:=f(ANode);
ifIndex>=0thenbegin
Result:=ANode;
(Index);
end;
end;
end;
ndOrCreate(constAName:string):TXmlNode;
//FindthenodewithAName,andifnotfound,addnewone
begin
Result:=NodeByName(AName);
ifnotassigned(Result)then
Result:=NodeNew(AName);
end;
dexByName(constAName:string):integer;
begin
Result:=0;
whileResult
begin
ifAnsiCompareText(Nodes[Result].Name,AName)=0then
exit;
inc(Result);
end;
ifResult=NodeCountthen
Result:=-1;
end;
dexByNameFrom(constAName:string;AFrom:integer):integer;
begin
Result:=AFrom;
whileResult
begin
ifAnsiCompareText(Nodes[Result].Name,AName)=0then
exit;
inc(Result);
end;
ifResult=NodeCountthen
Result:=-1;
end;
dexOf(ANode:TXmlNode):integer;
begin
ifassigned(ANode)andassigned(FNodes)then
Result:=f(ANode)
else
Result:=-1;
end;
sert(Index:integer;ANode:TXmlNode);
//InsertthenodeANodeatlocationIndexinthelist.
begin
ifnotassigned(ANode)then
exit;
if(Index>=0)and(Index<=NodeCount)then
begin
ifnotassigned(FNodes)then
FNodes:=;
:=Self;
(Index,ANode);
end;
end;
w(constAName:string):TXmlNode;
//Addanewchildnodeandreturnitspointer
begin
Result:=Nodes[NodeAdd(Name(Document,AName))];
end;
wAtIndex(Index:integer;constAName:string):TXmlNode;
//CreateanewnodewithAName,andinsertitintothesubnodelistatlocation
//Index,andreturnapointertoit.
begin
if(Index>=0)and(Index<=NodeCount)then
begin
Result:=Name(Document,AName);
NodeInsert(Index,Result);
endelse
Result:=nil;
end;
move(ANode:TxmlNode):integer;
begin
Result:=NodeIndexOf(ANode);
ifResult>=0then
NodeDelete(Result);
end;
yName(constAName:string;constAList:TList);
//FillAListwithnodesthathavenameAName
var
i:integer;
begin
ifnotassigned(AList)then
exit;
;
fori:=0toNodeCount-1do
ifAnsiCompareText(Nodes[i].Name,AName)=0then
(Nodes[i]);
end;
lear;
var
i:integer;
begin
fori:=0toNodeCount-1do
TXmlNode(FNodes[i]).Free;
FreeAndNil(FNodes);
end;
ag(constAValue:string;TagStart,TagClose:integer);
var
LItems:TStringList;
begin
//Createalisttoholdstringitems
LItems:=;
try
ParseAttributes(AValue,TagStart,TagClose,LItems);
//Determinename,attributesorvalueforeachelementtype
caseElementTypeof
xeDeclaration:
FName:='xml';
xeStyleSheet:
begin
FName:='xml-stylesheet';
//Wealsosetthisasthevalueforusein"StyleSheetString"
ValueDirect:=trim(copy(AValue,TagStart,TagClose-TagStart));
end;
else
//Firstitemisthename-isitthere?
=0then
(sxeMissingElementName);
//Setthename-usingtheelementinsteadofpropertyforspeed
FName:=LItems[0];
(0);
end;//case
//Anyattributes?
>0then
begin
CheckCreateAttributesList;
(LItems);
end;
finally
;
end;
end;
yAsDirectNode:boolean;
//Ifthisnodequalifiesasadirectnodewhenwriting,wereturnTrue.
//Adirectnodemayhaveattributes,rmore,
//therootnodewillneverbedisplayedasadirectnode.
begin
Result:=
(Length(FValue)=0)and
(NodeCount=0)and
(ElementType=xeNormal)and
notUseFullNodesand
(TreeDepth>0);
end;
tributeBool(constAName:string;ADefault:boolean):boolean;
var
V:string;
begin
V:=AttributeByName[AName];
try
Result:=sdStringToBool(V);
except
Result:=ADefault;
end;
end;
tributeDateTime(constAName:string;
ADefault:TDateTime):TDateTime;
var
V:string;
begin
V:=AttributeByName[AName];
try
Result:=sdDateTimeFromStringDefault(V,ADefault);
except
Result:=ADefault;
end;
end;
tributeFloat(constAName:string;ADefault:double):double;
var
V:string;
Code:integer;
begin
V:=AttributeByName[AName];
val(StringReplace(V,',','.',[]),Result,Code);
ifCode>0then
Result:=ADefault;
end;
tributeInteger(constAName:string;ADefault:integer):integer;
begin
Result:=StrToIntDef(AttributeByName[AName],ADefault);
end;
tributeInt64(constAName:string;ADefault:int64):int64;
begin
Result:=StrToInt64Def(AttributeByName[AName],ADefault);
end;
tributeString(constAName:string;constADefault:string):string;
begin
Result:=AttributeByName[AName];
iflength(Result)=0then
Result:=ADefault;
end;
ol(constAName:string;ADefault:boolean):boolean;
var
Index:integer;
begin
Result:=ADefault;
Index:=NodeIndexByName(AName);
ifIndex>=0then
Result:=Nodes[Index].ValueAsBoolDef(ADefault);
end;
{$IFDEFUSEGRAPHICS}
ush(constAName:string;ABrush:TBrush);
var
Child:TXmlNode;
begin
Child:=NodeByName(AName);
ifassigned(Child)thenwithChilddo
begin
//Readvalues
:=ReadColor('Color',clWhite);
:=TBrushStyle(ReadInteger('Style',integer(bsSolid)));
endelse
begin
//Defaults
:=nil;
:=clWhite;
:=bsSolid;
end;
end;
lor(constAName:string;ADefault:TColor):TColor;
var
Index:integer;
begin
Result:=ADefault;
Index:=NodeIndexByName(AName);
ifIndex>=0then
Result:=StrToInt(Nodes[Index].ValueAsString);
end;
{$ENDIF}
teTime(constAName:string;ADefault:TDateTime):TDateTime;
//DateMUSTalwaysbewritteninthisformat:
//YYYY-MM-DD(ifjustdate)or
//YYYY-MM-DDThh:mm:(andsforuniversaltime
//elphi'sTDateTimedoesnotgiveusaclueaboutthetimezone,
//thisistheeasiestsolution)
//ThisformatSHOULDNOTbechanged,toavoidallkindsof
//conversionerrorsinfuture.
//ThisformatiscompatiblewiththeW3Cdate/timespecificationasfoundhere:
///TR/NOTE-datetime
begin
Result:=sdDateTimeFromStringDefault(ReadString(AName,''),ADefault);
end;
更多推荐
quotedstr
发布评论