我正在尝试用Delphi编写一个xML。
如果我为节点添加了一个xmlns属性,那么该节点的子节点也会显示该属性,但后来为空。如何确保子节点显示属性?
我使用以下代码进行了测试
procedure TForm2.Button1Click(Sender: TObject);
var
RootNode, CurNode, PmtNode, PmtDetNode : IXMLNODE;
I:Integer;
begin
SepaDoc := Newxmldocument;
SepaDoc.Encoding := 'utf-8';
SepaDoc.Options := [doNodeAutoIndent];
RootNode := SepaDoc.AddChild('Document');
CurNode := RootNode.AddChild('Child1');
CurNode.Attributes['xmlns'] := 'apenootje';
CurNode := CurNode.AddChild('Child2');
CurNode := CurNode.AddChild('Child3');
SepaDoc.SaveToFile('D:\indir\testsepa.xml');
end;
这导致以下XML
<?xml version="1.0" encoding="UTF-8"?>
-<Document> -<Child1 xmlns="apenootje">
-<Child2 xmlns="">
<Child3/>
</Child2>
</Child1>
</Document>
由于 Rob Nowee
答案 0 :(得分:5)
由于Child1的子元素没有相同的命名空间,因此必须是未声明的,这就是Child2持有空(默认)命名空间的原因。
当一个元素带有属性xmlns =“”时,该元素及其后代的默认命名空间将恢复为“无命名空间”:也就是说,未加前缀的名称被认为不在任何命名空间中。
XML Namespaces 1.1还引入了取消声明其他名称空间前缀的选项。例如,如果属性xmlns:p =“”出现在元素上,则名称空间前缀p不再在该元素或其后代的范围内(因此不能使用),除非由另一个名称空间声明重新引入
话虽如此,修复很简单;在所有后续子节点上包含命名空间:
program SO20424534;
{$APPTYPE CONSOLE}
uses
ActiveX,
XMLdom,
XMLDoc,
XMLIntf,
SysUtils;
function TestXML : String;
var
RootNode,
CurNode : IXMLNODE;
Doc : IXmlDocument;
ns : String;
begin
Doc := Newxmldocument;
ns := 'apenootje';
Doc.Encoding := 'utf-8';
Doc.Options := [doNodeAutoIndent];
RootNode := Doc.AddChild('Document');
CurNode := RootNode.AddChild('Child1');
CurNode.DeclareNamespace('', ns);
CurNode := CurNode.AddChild('Child2', ns);
CurNode := CurNode.AddChild('Child3', ns);
Result := Doc.XML.Text;
end;
begin
try
CoInitialize(nil);
try
Writeln(TestXML);
finally
CoUninitialize;
end;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
Readln;
end;
输出:
<?xml version="1.0"?>
<Document>
<Child1 xmlns="apenootje">
<Child2>
<Child3/>
</Child2>
</Child1>
</Document>
答案 1 :(得分:2)
您必须先声明命名空间,然后才能使用它。仅手动添加xmlns
属性是不够的,这不是让DOM知道命名空间存在的正确方法。请改用IXMLNode.DeclareNamespace()
,例如:
CurNode := RootNode.AddChild('Child1');
CurNode.DeclareNamespace('', 'apenootje');