xmlutils.pp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. {
  2. This file is part of the Free Component Library
  3. XML utility routines.
  4. Copyright (c) 2006 by Sergei Gorelkin, [email protected]
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. unit xmlutils;
  12. {$mode objfpc}
  13. {$H+}
  14. interface
  15. uses
  16. SysUtils;
  17. function IsXmlName(const Value: WideString; Xml11: Boolean = False): Boolean; overload;
  18. function IsXmlName(Value: PWideChar; Len: Integer; Xml11: Boolean = False): Boolean; overload;
  19. function IsXmlNames(const Value: WideString; Xml11: Boolean = False): Boolean;
  20. function IsXmlNmToken(const Value: WideString; Xml11: Boolean = False): Boolean;
  21. function IsXmlNmTokens(const Value: WideString; Xml11: Boolean = False): Boolean;
  22. function IsValidXmlEncoding(const Value: WideString): Boolean;
  23. function Xml11NamePages: PByteArray;
  24. procedure NormalizeSpaces(var Value: WideString);
  25. {$i names.inc}
  26. implementation
  27. var
  28. Xml11Pg: PByteArray = nil;
  29. function Xml11NamePages: PByteArray;
  30. var
  31. I: Integer;
  32. p: PByteArray;
  33. begin
  34. if Xml11Pg = nil then
  35. begin
  36. GetMem(p, 512);
  37. for I := 0 to 255 do
  38. p^[I] := ord(Byte(I) in Xml11HighPages);
  39. p^[0] := 2;
  40. p^[3] := $2c;
  41. p^[$20] := $2a;
  42. p^[$21] := $2b;
  43. p^[$2f] := $29;
  44. p^[$30] := $2d;
  45. p^[$fd] := $28;
  46. p^[$ff] := $30;
  47. Move(p^, p^[256], 256);
  48. p^[$100] := $19;
  49. p^[$103] := $2E;
  50. p^[$120] := $2F;
  51. Xml11Pg := p;
  52. end;
  53. Result := Xml11Pg;
  54. end;
  55. function IsXml11Char(Value: PWideChar; var Index: Integer): Boolean; overload;
  56. begin
  57. if (Value[Index] >= #$D800) and (Value[Index] <= #$DB7F) then
  58. begin
  59. Inc(Index);
  60. Result := (Value[Index] >= #$DC00) and (Value[Index] <= #$DFFF);
  61. end
  62. else
  63. Result := False;
  64. end;
  65. function IsXml11Char(const Value: WideString; var Index: Integer): Boolean; overload;
  66. begin
  67. if (Value[Index] >= #$D800) and (Value[Index] <= #$DB7F) then
  68. begin
  69. Inc(Index);
  70. Result := (Value[Index] >= #$DC00) and (Value[Index] <= #$DFFF);
  71. end
  72. else
  73. Result := False;
  74. end;
  75. function IsXmlName(const Value: WideString; Xml11: Boolean): Boolean;
  76. begin
  77. Result := IsXmlName(PWideChar(Value), Length(Value), Xml11);
  78. end;
  79. function IsXmlName(Value: PWideChar; Len: Integer; Xml11: Boolean = False): Boolean; overload;
  80. var
  81. Pages: PByteArray;
  82. I: Integer;
  83. begin
  84. Result := False;
  85. if Xml11 then
  86. Pages := Xml11NamePages
  87. else
  88. Pages := @NamePages;
  89. I := 0;
  90. if (Len = 0) or not ((Byte(Value[I]) in NamingBitmap[Pages^[hi(Word(Value[I]))]]) or
  91. (Value[I] = ':') or
  92. (Xml11 and IsXml11Char(Value, I))) then
  93. Exit;
  94. Inc(I);
  95. while I < Len do
  96. begin
  97. if not ((Byte(Value[I]) in NamingBitmap[Pages^[$100+hi(Word(Value[I]))]]) or
  98. (Value[I] = ':') or
  99. (Xml11 and IsXml11Char(Value, I))) then
  100. Exit;
  101. Inc(I);
  102. end;
  103. Result := True;
  104. end;
  105. function IsXmlNames(const Value: WideString; Xml11: Boolean): Boolean;
  106. var
  107. Pages: PByteArray;
  108. I: Integer;
  109. Offset: Integer;
  110. begin
  111. if Xml11 then
  112. Pages := Xml11NamePages
  113. else
  114. Pages := @NamePages;
  115. Result := False;
  116. if Value = '' then
  117. Exit;
  118. I := 1;
  119. Offset := 0;
  120. while I <= Length(Value) do
  121. begin
  122. if not ((Byte(Value[I]) in NamingBitmap[Pages^[Offset+hi(Word(Value[I]))]]) or
  123. (Value[I] = ':') or
  124. (Xml11 and IsXml11Char(Value, I))) then
  125. begin
  126. if (I = Length(Value)) or (Value[I] <> #32) then
  127. Exit;
  128. Offset := 0;
  129. Inc(I);
  130. Continue;
  131. end;
  132. Offset := $100;
  133. Inc(I);
  134. end;
  135. Result := True;
  136. end;
  137. function IsXmlNmToken(const Value: WideString; Xml11: Boolean): Boolean;
  138. var
  139. I: Integer;
  140. Pages: PByteArray;
  141. begin
  142. if Xml11 then
  143. Pages := Xml11NamePages
  144. else
  145. Pages := @NamePages;
  146. Result := False;
  147. if Value = '' then
  148. Exit;
  149. I := 1;
  150. while I <= Length(Value) do
  151. begin
  152. if not ((Byte(Value[I]) in NamingBitmap[Pages^[$100+hi(Word(Value[I]))]]) or
  153. (Value[I] = ':') or
  154. (Xml11 and IsXml11Char(Value, I))) then
  155. Exit;
  156. Inc(I);
  157. end;
  158. Result := True;
  159. end;
  160. function IsXmlNmTokens(const Value: WideString; Xml11: Boolean): Boolean;
  161. var
  162. I: Integer;
  163. Pages: PByteArray;
  164. begin
  165. if Xml11 then
  166. Pages := Xml11NamePages
  167. else
  168. Pages := @NamePages;
  169. I := 1;
  170. Result := False;
  171. if Value = '' then
  172. Exit;
  173. while I <= Length(Value) do
  174. begin
  175. if not ((Byte(Value[I]) in NamingBitmap[Pages^[$100+hi(Word(Value[I]))]]) or
  176. (Value[I] = ':') or
  177. (Xml11 and IsXml11Char(Value, I))) then
  178. begin
  179. if (I = Length(Value)) or (Value[I] <> #32) then
  180. Exit;
  181. end;
  182. Inc(I);
  183. end;
  184. Result := True;
  185. end;
  186. function IsValidXmlEncoding(const Value: WideString): Boolean;
  187. var
  188. I: Integer;
  189. begin
  190. Result := False;
  191. if (Value = '') or (Value[1] > #255) or not (char(ord(Value[1])) in ['A'..'Z', 'a'..'z']) then
  192. Exit;
  193. for I := 2 to Length(Value) do
  194. if (Value[I] > #255) or not (char(ord(Value[I])) in ['A'..'Z', 'a'..'z', '0'..'9', '.', '_', '-']) then
  195. Exit;
  196. Result := True;
  197. end;
  198. procedure NormalizeSpaces(var Value: WideString);
  199. var
  200. I, J: Integer;
  201. begin
  202. I := Length(Value);
  203. // speed: trim only whed needed
  204. if (I > 0) and ((Value[1] = #32) or (Value[I] = #32)) then
  205. Value := Trim(Value);
  206. I := 1;
  207. while I < Length(Value) do
  208. begin
  209. if Value[I] = #32 then
  210. begin
  211. J := I+1;
  212. while (J <= Length(Value)) and (Value[J] = #32) do Inc(J);
  213. if J-I > 1 then Delete(Value, I+1, J-I-1);
  214. end;
  215. Inc(I);
  216. end;
  217. end;
  218. initialization
  219. finalization
  220. if Assigned(Xml11Pg) then
  221. FreeMem(Xml11Pg);
  222. end.