如何使用 Delphi 从 XML 中删除名称 space 7
How to remove name space from XML using Delphi 7
我正在使用下面的代码从 xml 中删除名称 space 属性,但我没有成功。我只想从节点 Action__CompIntfc__CIName
中删除 Namespace
<Action__CompIntfc__CIName xmlns="http://schemas.xmlsoap.org/soap/encoding/">
下面是我的代码
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;
删除名称space "xmlns="http://schemas.xmlsoap.org/soap/encoding/" from XML from below node
<Action__CompIntfc__CIName xmlns="http://schemas.xmlsoap.org/soap/encoding/">
我希望我的 xml 成为
<?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>
以下适合我。
如您所见,它通过迭代 RecNodeList
寻找具有正确名称的节点来工作。当它找到一个时,它会创建一个具有相同 tagName
和 text
属性的新节点,复制其除 'xmlns' 属性之外的属性,然后用新节点替换现有节点。
它还会复制节点的第一级子节点及其属性。如果你也想复制那些子节点的子节点(如果有的话),编写一个递归函数可能是最简单的,但是你的 q.Xml 中的 Xml 不会出现这种情况。
当然,显示的方法对 Xml 文档的结构敏感,因此相当脆弱。我没有尝试找出答案,但我想评论中建议的 XSLT 解决方案可能同样脆弱。
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;
作为 DOM 编程的替代方案,这里有一个 XSLT 1.0 样式表可以完成这项工作:
<?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>
它改变了
<?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>
进入
<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>
如图http://xsltransform.net/94rmq6V/1.
至于将它与 MSXML 一起使用,您可以将 transformNodeToObject
、https://msdn.microsoft.com/en-us/library/ms766561%28v=vs.85%29.aspx 与您的输入文档、您在其中加载样式表和结果文档的第二个文档一起使用,如
var
xmldoc : IXMLDOMDocument;
sheet : IXMLDOMDocument;
result : IXMLDOMDocument;
并创建它们:
xmldoc := CoDOMDocument.Create;
sheet := CoDOMDocument.Create;
result := CoDOMDocument.Create;
像您一样加载 xmldoc,加载上面的 XSLT 代码(使用 load
方法从文件或使用 loadXML
的字符串加载,就像您对 xmldoc 所做的那样),以及然后打电话
xmldoc.transformNodeToObject(sheet, result);
我正在使用下面的代码从 xml 中删除名称 space 属性,但我没有成功。我只想从节点 Action__CompIntfc__CIName
中删除 Namespace<Action__CompIntfc__CIName xmlns="http://schemas.xmlsoap.org/soap/encoding/">
下面是我的代码
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;
删除名称space "xmlns="http://schemas.xmlsoap.org/soap/encoding/" from XML from below node
<Action__CompIntfc__CIName xmlns="http://schemas.xmlsoap.org/soap/encoding/">
我希望我的 xml 成为
<?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>
以下适合我。
如您所见,它通过迭代 RecNodeList
寻找具有正确名称的节点来工作。当它找到一个时,它会创建一个具有相同 tagName
和 text
属性的新节点,复制其除 'xmlns' 属性之外的属性,然后用新节点替换现有节点。
它还会复制节点的第一级子节点及其属性。如果你也想复制那些子节点的子节点(如果有的话),编写一个递归函数可能是最简单的,但是你的 q.Xml 中的 Xml 不会出现这种情况。
当然,显示的方法对 Xml 文档的结构敏感,因此相当脆弱。我没有尝试找出答案,但我想评论中建议的 XSLT 解决方案可能同样脆弱。
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;
作为 DOM 编程的替代方案,这里有一个 XSLT 1.0 样式表可以完成这项工作:
<?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>
它改变了
<?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>
进入
<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>
如图http://xsltransform.net/94rmq6V/1.
至于将它与 MSXML 一起使用,您可以将 transformNodeToObject
、https://msdn.microsoft.com/en-us/library/ms766561%28v=vs.85%29.aspx 与您的输入文档、您在其中加载样式表和结果文档的第二个文档一起使用,如
var
xmldoc : IXMLDOMDocument;
sheet : IXMLDOMDocument;
result : IXMLDOMDocument;
并创建它们:
xmldoc := CoDOMDocument.Create;
sheet := CoDOMDocument.Create;
result := CoDOMDocument.Create;
像您一样加载 xmldoc,加载上面的 XSLT 代码(使用 load
方法从文件或使用 loadXML
的字符串加载,就像您对 xmldoc 所做的那样),以及然后打电话
xmldoc.transformNodeToObject(sheet, result);