Reputation: 489
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>
Upvotes: 2
Views: 2386
Reputation: 167571
As an alternative to the DOM programming, here is an XSLT 1.0 stylesheet that should do the job:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:se="http://schemas.xmlsoap.org/soap/encoding/" exclude-result-prefixes="se">
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="se:*">
<xsl:element name="{local-name()}">
<xsl:apply-templates select="@* | node()"/>
</xsl:element>
</xsl:template>
</xsl:transform>
It transforms
<?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>
into
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">
<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>
as shown in http://xsltransform.net/94rmq6V/1.
As for using it with MSXML, you can use transformNodeToObject
, https://msdn.microsoft.com/en-us/library/ms766561%28v=vs.85%29.aspx, together with your input document, a second document into which you load above stylesheet and a result document, as in
var
xmldoc : IXMLDOMDocument;
sheet : IXMLDOMDocument;
result : IXMLDOMDocument;
and create them:
xmldoc := CoDOMDocument.Create;
sheet := CoDOMDocument.Create;
result := CoDOMDocument.Create;
load the xmldoc as you do, load the above XSLT code (either from a file using the load
method or from a string with loadXML
, as you do for the xmldoc), and then call
xmldoc.transformNodeToObject(sheet, result);
Upvotes: 2
Reputation: 30715
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;
Upvotes: 1