tvplanit: Fix ParentNode property of TVpXMLDatastore.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@4942 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2016-07-13 19:48:35 +00:00
parent d616eba746
commit ccc2190dcc
2 changed files with 45 additions and 81 deletions

View File

@ -319,7 +319,6 @@ object Form1: TForm1
AutoConnect = True AutoConnect = True
Connected = False Connected = False
FileName = 'data.xml' FileName = 'data.xml'
ParentNode = 'test'
left = 136 left = 136
top = 202 top = 202
end end

View File

@ -234,6 +234,7 @@ var
i, j: Integer; i, j: Integer;
node, prevnode: TDOMNode; node, prevnode: TDOMNode;
rootnode: TDOMNode; rootnode: TDOMNode;
appending: Boolean;
{%H-}nodename: String; {%H-}nodename: String;
begin begin
L := TStringList.Create; L := TStringList.Create;
@ -241,85 +242,53 @@ begin
if FParentNode <> '' then begin if FParentNode <> '' then begin
L.Delimiter := '/'; L.Delimiter := '/';
L.StrictDelimiter := true; L.StrictDelimiter := true;
L.DelimitedText := FParentNode; L.DelimitedText := StringReplace(FParentNode, '\', '/', [rfReplaceAll]);
if L.Count = 0 then begin
L.Delimiter := '\';
L.DelimitedText := FParentNode;
end;
end; end;
// Get current root node
rootnode := ADoc.FirstChild;
nodeName := rootnode.NodeName;
if (L.Count = 0) then begin if (L.Count = 0) then begin
// no parent node specified --> is it a child of root? // no parent node specified --> is the root node the node of the data store?
Result := rootnode.FindNode(STORE_NODE_NAME); Result := ADoc.FindNode(STORE_NODE_NAME);
// no: attach as child to root // no: attach as child of root
if Result = nil then begin if Result = nil then begin
rootnode := ADoc.FirstChild;
Result := ADoc.CreateElement(STORE_NODE_NAME); Result := ADoc.CreateElement(STORE_NODE_NAME);
rootnode.AppendChild(Result); rootnode.AppendChild(Result);
end; end;
exit; exit;
end; end;
// Parent node path is absolute // Remove empty path elements due to consecutive slashes
if (L[0] = '') then begin for i := L.Count-1 downto 0 do
if (L.Count > 1) and (rootnode.NodeName <> L[1]) then begin if L[i] = '' then L.Delete(i);
// ... but root is different from current root --> Error // Add the name of the datastore node to the path list of node names
Result := nil; L.Add(STORE_NODE_NAME);
XmlError('Root nodes of xml file and datastore do not match.');
end;
end;
node := rootnode; // Now iterate through all elements of the path. Begin a new subtree at the
// element where the ParehtNode path differs from the path in the document.
node := ADoc;
appending := false;
for i:=0 to L.Count-1 do begin for i:=0 to L.Count-1 do begin
if (L[i] = '') then if not appending then begin
Continue; Result := node.FindNode(L[i]);
if node = rootnode then // Result is nil if the path element L[i] is not found. In this case
prevnode := rootnode // set the Flag appending to true to indicate that a new sub-tree begins here.
else if (Result = nil) then
prevnode := node.ParentNode; appending := true;
// Look for the path segment among the nodes of the current level end;
Result := node.FindNode(L[i]); if appending then begin
if Result = nil then begin Result := ADoc.CreateElement(L[i]);
// Not found -> Build sub-tree starting at prev level node.AppendChild(Result);
for j:= i to L.Count-1 do begin end;
if L[j] = '' then node := Result;
Continue;
prevnode := node;
node := ADoc.CreateElement(L[i]);
prevnode.AppendChild(node);
end;
end else
// Found -> Proceed to next level
if i < L.Count-1 then
node := prevnode.FirstChild;
end; end;
Result := ADoc.CreateElement(STORE_NODE_NAME);
node.AppendChild(Result);
finally finally
L.Free; L.Free;
end; end;
end; end;
{ Finds the node with the caption STORE_NODE_NAME, or returns nil if not found.
Follows the path given by ParentNode }
function TVpXmlDatastore.FindStoreNode(ADoc: TDOMDocument): TDOMNode; function TVpXmlDatastore.FindStoreNode(ADoc: TDOMDocument): TDOMNode;
function NodeFound(ANode: TDOMNode; ANodeName: String): Boolean;
var
nodename: String;
begin
if ANode = nil then begin
Result := false;
exit;
end;
nodename := ANode.NodeName;
Result := nodename = ANodeName;
if not Result then
Result := NodeFound(ANode.NextSibling, ANodeName);
end;
var var
L: TStringList; L: TStringList;
nodename: String; nodename: String;
@ -330,15 +299,11 @@ begin
if FParentNode <> '' then begin if FParentNode <> '' then begin
L.Delimiter := '/'; L.Delimiter := '/';
L.StrictDelimiter := true; L.StrictDelimiter := true;
L.DelimitedText := FParentNode; L.DelimitedText := StringReplace(FParentNode, '\', '/', [rfReplaceAll]);
if L.Count = 0 then begin
L.Delimiter := '\';
L.DelimitedText := FParentNode;
end;
end; end;
// DataStore node is root node // ParentNode is empty --> DataStore node is root node
if L.Count = 0 then begin if (L.Count = 0) then begin
Result := ADoc.FirstChild; Result := ADoc.FirstChild;
if Result <> nil then begin if Result <> nil then begin
nodeName := Result.NodeName; nodeName := Result.NodeName;
@ -346,18 +311,18 @@ begin
Result := nil; Result := nil;
end; end;
end else begin end else begin
Result := ADoc.FirstChild; // Remove empty path elements due to consecutive slashes
i := 0; for i := L.Count-1 downto 0 do
while (i < L.Count) do begin if L[i] = '' then L.Delete(i);
if L[i] = '' then // Add the name of the datastore node to the path list of node names
Continue; L.Add(STORE_NODE_NAME);
if NodeFound(Result, L[i]) then begin // Beginning with root dig deeper along the path specified until the
Result := Result.FirstChild; // node of the datastore is found (or not).
inc(i); Result := ADoc;
end else begin for i:=0 to L.Count-1 do begin
Result := nil; Result := Result.FindNode(L[i]);
if Result = nil then
exit; exit;
end;
end; end;
end; end;
finally finally
@ -533,6 +498,7 @@ begin
if storeNode = nil then if storeNode = nil then
exit; exit;
nodeName := storeNode.NodeName;
Resources.ClearResources; Resources.ClearResources;
node := storeNode.FirstChild; node := storeNode.FirstChild;
while node <> nil do begin while node <> nil do begin
@ -1545,8 +1511,7 @@ begin
end else begin end else begin
// If file does not exist then create a new xml document // If file does not exist then create a new xml document
doc := TXMLDocument.Create; doc := TXMLDocument.Create;
storeNode := doc.CreateElement(STORE_NODE_NAME); storeNode := CreateStoreNode(doc); //doc.CreateElement(STORE_NODE_NAME);
doc.AppendChild(storeNode);
end; end;
WriteResources(doc, storeNode); WriteResources(doc, storeNode);