Browse Source

* Modified TDOMNodeList. It now has a fixed BuildList procedure which iterates descendant nodes,
calling NodeFilter for each node. The NodeFilter return value determines whether the node will
be added to the list, and whether node's children should be recursively iterated.
This considerably simplifies creating TDOMNodeList descendants, as they no longer need to mess
with the class internals (FRevision, FList, etc).

git-svn-id: trunk@13227 -

sergei 16 years ago
parent
commit
c5114c7423
1 changed files with 41 additions and 32 deletions
  1. 41 32
      packages/fcl-xml/src/dom.pp

+ 41 - 32
packages/fcl-xml/src/dom.pp

@@ -290,6 +290,8 @@ type
 //   NodeList
 //   NodeList
 // -------------------------------------------------------
 // -------------------------------------------------------
 
 
+  TFilterResult = (frFalse, frNorecurseFalse, frTrue, frNorecurseTrue);
+
   TDOMNodeList = class(TObject)
   TDOMNodeList = class(TObject)
   protected
   protected
     FNode: TDOMNode;
     FNode: TDOMNode;
@@ -297,6 +299,8 @@ type
     FList: TFPList;
     FList: TFPList;
     function GetCount: LongWord;
     function GetCount: LongWord;
     function GetItem(index: LongWord): TDOMNode;
     function GetItem(index: LongWord): TDOMNode;
+    function NodeFilter(aNode: TDOMNode): TFilterResult; virtual;
+    // now deprecated in favor of NodeFilter
     procedure BuildList; virtual;
     procedure BuildList; virtual;
   public
   public
     constructor Create(ANode: TDOMNode);
     constructor Create(ANode: TDOMNode);
@@ -313,7 +317,7 @@ type
     filter: DOMString;
     filter: DOMString;
     FNamespaceFilter: DOMString;
     FNamespaceFilter: DOMString;
     UseFilter: Boolean;
     UseFilter: Boolean;
-    procedure BuildList; override;
+    function NodeFilter(aNode: TDOMNode): TFilterResult; override;
   public
   public
     constructor Create(ANode: TDOMNode; const AFilter: DOMString); overload;
     constructor Create(ANode: TDOMNode; const AFilter: DOMString); overload;
     constructor Create(ANode: TDOMNode; const nsURI, localName: DOMString); overload;
     constructor Create(ANode: TDOMNode; const nsURI, localName: DOMString); overload;
@@ -1412,18 +1416,43 @@ begin
   inherited Destroy;
   inherited Destroy;
 end;
 end;
 
 
+function TDOMNodeList.NodeFilter(aNode: TDOMNode): TFilterResult;
+begin
+// accept all nodes but don't allow recursion
+  Result := frNorecurseTrue;
+end;
+
 procedure TDOMNodeList.BuildList;
 procedure TDOMNodeList.BuildList;
 var
 var
-  Child: TDOMNode;
+  current, next: TDOMNode;
+  res: TFilterResult;
 begin
 begin
   FList.Clear;
   FList.Clear;
   FRevision := FNode.GetRevision; // refresh
   FRevision := FNode.GetRevision; // refresh
 
 
-  Child := FNode.FirstChild;
-  while Assigned(Child) do
+  current := FNode.FirstChild;
+
+  while Assigned(current) do
   begin
   begin
-    FList.Add(Child);
-    Child := Child.NextSibling;
+    res := NodeFilter(current);
+    if res in [frTrue, frNorecurseTrue] then
+      FList.Add(current);
+
+    next := nil;
+    if res in [frTrue, frFalse] then
+      next := current.FirstChild;
+
+    if next = nil then
+    begin
+      while current <> FNode do
+      begin
+        next := current.NextSibling;
+        if Assigned(next) then
+          Break;
+        current := current.ParentNode;
+      end;
+    end;
+    current := next;
   end;
   end;
 end;
 end;
 
 
@@ -1464,33 +1493,13 @@ begin
 end;
 end;
 
 
 // TODO: namespace support here
 // TODO: namespace support here
-procedure TDOMElementList.BuildList;
-var
-  Child: TDOMNode;
+function TDOMElementList.NodeFilter(aNode: TDOMNode): TFilterResult;
 begin
 begin
-  FList.Clear;
-  FRevision := FNode.GetRevision; // refresh
-
-  Child := FNode.FirstChild;
-  while Assigned(Child) and (Child <> FNode) do
-  begin
-    if (Child.NodeType = ELEMENT_NODE) and (not UseFilter or (TDOMElement(Child).TagName = filter)) then
-          FList.Add(Child);
-    // recursive track node hierarchy  
-    if Assigned(Child.FirstChild) then
-      Child := Child.FirstChild
-    else
-      if Assigned(Child.NextSibling) then
-        Child := Child.NextSibling
-      else
-      begin
-         Child := Child.ParentNode;
-         while Assigned(Child) and (Child <> FNode) and not Assigned(Child.NextSibling) do
-           Child := Child.ParentNode;
-         if Assigned(Child) and (Child <> FNode) then
-            Child := Child.NextSibling;
-      end;
-  end;
+  if (aNode.NodeType = ELEMENT_NODE) and
+    (not UseFilter or (TDOMElement(aNode).TagName = Filter)) then
+    Result := frTrue
+  else
+    Result := frFalse;
 end;
 end;