anchor.diff:    end;
   end;
   
  +function TXmlNode.NodeByAttributeValue(const NodeName, AttribName, AttribValue: array of Utf8String;
  +  ShouldRecurse: boolean = True): TXmlNode;
  +var
  +  i,j: integer;
  +  Node: TXmlNode;
  +begin
  +  Result := nil;
  +  // Find all nodes that are potential results
  +  for i := 0 to NodeCount - 1 do
  +  begin
  +    Node := Nodes[i];
  +    for j:= Low(NodeName) to High(NodeName) do
  +    if (UTF8CompareText(Node.Name, NodeName[j]) = 0) and
  +        Node.HasAttribute(AttribName[j]) and
  +       (UTF8CompareText(Node.AttributeValueByName[AttribName[j]], AttribValue[j]) = 0) then
  +    begin
  +      Result := Node;
  +      exit;
  +    end;
  +    // Recursive call
  +    if ShouldRecurse then
  +      Result := Node.NodeByAttributeValue(NodeName, AttribName, AttribValue, True);
  +    if assigned(Result) then
  +      exit;
  +  end;
  +end;
  +
   function TXmlNode.HasAttribute(const AName: Utf8String): boolean;
   var
     i: integer;
  
positive.code:         SubNode.WriteStream(S);
  
        if HasSubElements and (SubNode is TsdCharData) then
          sdStreamWriteString(S, GetEndOfLine);
      end;
  
      // endtag
  
negative.code:       SubNode := ANode.Nodes[i];
        if SubNode.CompareNodeName(NodeName) = 0 then
          AList.Add(SubNode);
        FindNodesRecursive(SubNode, AList);
      end;
    end;
  // main
  begin
    AList.Clear;
    FindNodesRecursive(Self, AList);
  end;
  
  procedure TXmlNode.FindNodes(const NodeName: array of Utf8String; const AList: TList);
    // local
    procedure FindNodesRecursive(ANode: TXmlNode; AList: TList);
    var
      i,j: integer;
      SubNode: TXmlNode;
    begin
      for i := 0 to ANode.NodeCount - 1 do
      begin
        SubNode := ANode.Nodes[i];
        for j:=Low(NodeName) to High(NodeName) do
          if SubNode.CompareNodeName(NodeName[j]) = 0 then
            AList.Add(SubNode);
        FindNodesRecursive(SubNode, AList);
      end;
    end;
  