1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
|
unit PList2JSon;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Laz2_DOM, fpjson;
function PListXml2Json(AnXml: TXMLDocument): TJSONData;
implementation
function Xml2Json(AnNode: TDOMNode): TJSONData; forward;
function XmlDict2Json(AnNode: TDOMNode): TJSONData;
var
c, i: integer;
key: DOMString;
val: TJSONData;
keyNd: TDOMNode;
begin
c := AnNode.GetChildCount;
i := 0;
Result := CreateJSONObject([]);
try
while i < c do begin
keyNd := AnNode.ChildNodes[i];
if LowerCase(keyNd.NodeName) <> 'key' then
raise Exception.Create('Expected <key>, but got ' + keyNd.NodeName);
key := Trim(keyNd.TextContent);
inc(i);
if i = c then
raise Exception.Create('Expected value for key '+key);
val := Xml2Json(AnNode.ChildNodes[i]);
inc(i);
TJSONObject(Result).Add(key, val)
end;
except
Result.Free;
raise;
end;
end;
function XmlArray2Json(AnNode: TDOMNode): TJSONData;
var
CN: TDOMNode;
begin
Result := CreateJSONArray([]);
try
CN := AnNode.FirstChild;
while CN <> nil do begin
TJSONArray(Result).Add(Xml2Json(CN));
CN := CN.NextSibling;
end;
except
Result.Free;
raise;
end;
end;
function Xml2Json(AnNode: TDOMNode): TJSONData;
var
n: DOMString;
i64: int64;
f: Double;
b: Boolean;
d: TDateTime;
begin
n := LowerCase(AnNode.NodeName);
if (n = 'dict') or (n = 'dictionary') then begin
Result := XmlDict2Json(AnNode);
end
else
if n = 'array' then begin
Result := XmlArray2Json(AnNode);
end
else
if n = 'string' then begin
Result := CreateJSON(AnNode.TextContent);
end
else
if n = 'number' then begin
if TryStrToInt64(trim(AnNode.TextContent), i64) then begin
if (i64 >= low(integer)) and (i64 <= high(integer)) then
Result := CreateJSON(integer(i64))
else
Result := CreateJSON(i64);
end
else begin
if TryStrToFloat(trim(AnNode.TextContent), f) then
Result := CreateJSON(f)
else
raise Exception.Create('Unknown number '+AnNode.TextContent);
end;
end
else
if n = 'boolean' then begin
if TryStrToBool(trim(AnNode.TextContent), b) then
Result := CreateJSON(b)
else
raise Exception.Create('Unknown bool '+AnNode.TextContent);
end
else
if n = 'date' then begin
if TryStrToDate(trim(AnNode.TextContent), d) then
Result := CreateJSON(d)
else
raise Exception.Create('Unknown date'+AnNode.TextContent);
end
else
if n = 'data' then begin
raise Exception.Create('DATA not supported');
end
else
raise Exception.Create('Unknown key '+n);
end;
function PListXml2Json(AnXml: TXMLDocument): TJSONData;
var
CN: TDOMNode;
begin
Result := nil;
if AnXml = nil then
raise Exception.Create('Missing XML');
CN := AnXml.FirstChild;
if CN = nil then
raise Exception.Create('Missing XML content');
if CN is TDOMDocumentType then
CN := CN.NextSibling;
if LowerCase(CN.NodeName) <> 'plist' then
raise Exception.Create('Expected <plist> ');
if CN.NextSibling <> nil then
raise Exception.Create('Trailing extra data');
if CN.GetChildCount <> 1 then
raise Exception.Create('Expected <dict> or <array> ');
CN := CN.ChildNodes[0];
if (LowerCase(CN.NodeName) = 'dict') or (LowerCase(CN.NodeName) = 'dictionary') then
Result := XmlDict2Json(CN)
else
if LowerCase(CN.NodeName) = 'CN' then
Result := XmlArray2Json(AnXml)
else
raise Exception.Create('Expected <dict> or <array> ');
end;
end.
|