Search code examples
xmldelphinamespacesdelphi-7

How to remove name space from XML using Delphi 7


i am using below code to remove name space attribute from xml but i didn;t succeeded. i want to remove Namespace only from nodes Action__CompIntfc__CIName

<Action__CompIntfc__CIName xmlns="http://schemas.xmlsoap.org/soap/encoding/">

Below is my code

procedure TForm1.Button1Click(Sender: TObject);
var
  xmldoc : IXMLDOMDocument;
  xmlString : WideString;
  RecNodelist: IXMLDOMNodeList;
  DataNode: IXMLDOMElement;
  attr :  IXMLDOMAttribute;
begin
  xmlString := '<?xml version="1.0"?>'
  +'<SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"   xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">'
    +'<SOAP-ENV:Body>'
      +'<Action__CompIntfc__CIName xmlns="http://schemas.xmlsoap.org/soap/encoding/">'
        +'<test>1</test>'
      +'</Action__CompIntfc__CIName>'
      +'<Action__CompIntfc__CIName xmlns="http://schemas.xmlsoap.org/soap/encoding/">'
        +'<test>15</test>'
      +'</Action__CompIntfc__CIName>'
    +'</SOAP-ENV:Body>'
  +'</SOAP-ENV:Envelope>';
  try
    XMLdoc := CoDOMDocument.Create;
    xmldoc.loadXML(xmlString);
    RecNodelist := XMLdoc.selectNodes('//SOAP-ENV:Envelope/SOAP-ENV:Body/Action__CompIntfc__CIName');
    DataNode := RecNodelist.NextNode as IXMLDOMElement;
    while DataNode <> nil do
    begin
      showmessage(DataNode.xml);
      attr := DataNode.getAttributeNode('xmlns');
      DataNode.removeAttributeNode(attr);
      showmessage(DataNode.xml);
      DataNode := RecNodelist.NextNode as IXMLDOMElement;
    end;
  except
   on e: Exception do
   begin
     ShowMessage(e.Message);
   end;
  end;
end;

After deleting namespace "xmlns="http://schemas.xmlsoap.org/soap/encoding/" from XML from below node

<Action__CompIntfc__CIName xmlns="http://schemas.xmlsoap.org/soap/encoding/">

i am expecting my xml to be

<?xml version="1.0"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"   xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
  <SOAP-ENV:Body>

    <Action__CompIntfc__CIName>
      <test>1</test>
    </Action__CompIntfc__CIName>

    <Action__CompIntfc__CIName>
      <test>15</test>
    </Action__CompIntfc__CIName>

  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Solution

  • The following works for me.

    As you'll see, it works by iterating your RecNodeList looking for nodes with the right name. When it finds one, it creates a new node with the same tagName and text properties, copies its attributes except the 'xmlns' one and then replaces the existing node with the new one.

    It also copies the node's first level child nodes and their attributes. If you wanted to copy those child nodes' children (if any) too, it would probably be easiest to write a recursive function to do it, but that doesn't arise with the Xml in your q.

    Of course, the method shown is sensitive to the structure of the Xml document and so is rather fragile. I haven't attempted to find out, but I imagine that the XSLT solution suggested in a comment might be equally fragile.

    procedure TForm1.RemoveNS;
    var
      xmldoc : IXMLDOMDocument;
      xmlString : WideString;
      Target : String;
      RecNodelist: IXMLDOMNodeList;
      DataNode: IXMLDOMElement;
      NextNode : IXMLDOMNode;
      NewNode: IXMLDOMElement;
      AttrNode : IXMLDOmNode;
      ChildNode : IXMLDomElement;
      Map : IXMLDOMNamedNodeMap;
      i,
      j : Integer;
    begin
    
      // remove Namespace only from nodes
      //  <Action__CompIntfc__CIName xmlns="http://schemas.xmlsoap.org/soap/encoding/">
    
      xmlString := '<?xml version="1.0"?>'#13#10
      +'<SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"   xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">'#13#10
        +'<SOAP-ENV:Body>'#13#10
          +'<Action__CompIntfc__CIName xmlns="http://schemas.xmlsoap.org/soap/encoding/" anattr="hello">'#13#10
            +'<test attr="123">1</test>'#13#10
          +'</Action__CompIntfc__CIName>'#13#10
          +'<Action__CompIntfc__CIName xmlns="http://schemas.xmlsoap.org/soap/encoding/">'#13#10
            +'<test>15</test>'#13#10
          +'</Action__CompIntfc__CIName>'#13#10
        +'</SOAP-ENV:Body>'#13#10
      +'</SOAP-ENV:Envelope>'#13#10;
    
      Memo1.Lines.Text := xmlString;
      Target := 'Action__CompIntfc__CIName';
      xmldoc := CoDOMDocument.Create;
    
      try
        xmldoc.loadXML(xmlString);
        RecNodelist := xmldoc.selectNodes('//SOAP-ENV:Envelope/SOAP-ENV:Body/Action__CompIntfc__CIName');
    
        DataNode := RecNodelist.NextNode as IXMLDOMElement;
        while DataNode <> nil do
        begin
          NextNode := DataNode.nextSibling;
          if CompareText(DataNode.nodeName, Target) = 0 then begin
            NewNode := XMLDoc.createElement(DataNode.tagName);
            NewNode.text := DataNode.Text;
    
            //  copy the existing node's Attributes
            Map := DataNode.attributes;
            for i := 0 to Map.length - 1 do begin
              AttrNode := Map.item[i];
              if CompareText(AttrNode.NodeName, 'xmlns') <> 0 then
                NewNode.SetAttribute(AttrNode.NodeName, AttrNode.NodeValue);
            end;
    
            //  Create (first level) child nodes matching the existing node's
            //  children and any attributes they have
            for i := 0 to DataNode.childNodes.length - 1 do begin
              ChildNode := XMLDoc.createElement(DataNode.childNodes.item[i].nodeName);
              ChildNode.text := DataNode.childNodes.item[i].Text;
    
              Map := DataNode.childNodes.item[i].attributes;
              for j:= 0 to Map.length - 1 do begin
                AttrNode := Map.item[j];
                ChildNode.SetAttribute(AttrNode.NodeName, AttrNode.NodeValue);
              end;
    
              NewNode.appendChild(ChildNode);
            end;
            DataNode.parentNode.replaceChild(NewNode, DataNode);
          end;
          DataNode := NextNode as IXmlDOMElement;
        end;
    
        Memo2.Lines.Text := XmlDoc.documentElement.xml;
      except
       on e: Exception do
       begin
         ShowMessage(e.Message);
       end;
      end;
       xmldoc := Nil;  // not strictly necessary because it will get finalized when this procedure exits, but anyway
    end;