Search code examples
xmldelphidelphi-2007

Remove empty <ul> nodes from IXMLDOMDOCUMENT in Delphi


I have many xml nodes in an xmldocument. I want to remove all the empty <ul> nodes. How can I accomplish this?

Here is a snippet:

  <li>
    <a href="javascript:void(0);">Level 1</a>
    <ul id="subject19">
      <li>
        <a href="javascript:void(0);">Level 2</a>
        <ul id="subject20">
          <li>
            <a href="javascript:void(0);">Level 3</a>
            <ul id="subject21"/>
          </li>
        </ul>
      </li>
    </ul>
  </li>

I need to remove <ul id="subject21"/>


Solution

  • You can use a simple recursion. Here is an example how:

    procedure ScanAndRemove(aNode: IXMLNode);
    var
      i: Integer;
      childNode: IXMLNode;
    begin
      i := 0;
      while i < aNode.ChildNodes.Count do
      begin
        childNode := aNode.ChildNodes[i];
        if (childNode.NodeName = 'ul') and (childNode.ChildNodes.Count = 0) then
          aNode.ChildNodes.Remove(childNode) else
          begin
            ScanAndRemove(childNode);
            Inc(i);
          end;
      end;
    end;
    

    And just pass the document root element:

    procedure Cleanup;
    var
      xmlDoc: IXMLDocument;
    begin
      xmlDoc := TXMLDocument.Create(nil);
      try
        xmlDoc.LoadFromXML('...');
        ScanAndRemove(xmlDoc.DocumentElement);
        // now xmlDoc contains the desired result
      finally
        xmlDoc := nil;
      end;
    end;
    

    EDIT The recursive function will remove a node without children, but containing a value. Eg:

    <ul>
      blabla
    </ul>
    

    If you want the opposite, you should add one more check - ie:

    if (childNode.NodeName = 'ul') and 
      (childNode.ChildNodes.Count = 0) and 
      (VarToStrDef(childNode.NodeValue, '') = '') then
      ... 
    

    Or this way - https://stackoverflow.com/a/9673869/3962893