消除 xml 文件的声明
Eliminate declaration of xml file
我正在 Delphi 7 中创建一个 XML 文件。我想从代码中删除父节点的声明。
这是我的代码:
var
XML : IXMLDOCUMENT;
RootNode, CurNode : IXMLNODE;
begin
XML := NewXMLDocument;
XML.Encoding := 'utf-8';
XML.Options := [doNodeAutoIndent]; // looks better in Editor ;)
RootNode := XML.AddChild('p:test');
RootNode.Attributes['xmlns:ds'] := 'Attributes1';
RootNode.Attributes['xmlns:p'] := 'Attributes2';
RootNode.Attributes['versione'] := 'FPR12';
CurNode := RootNode.AddChild('HeadNode');
CurNode := CurNode.AddChild('SubNode');
CurNode.Text := 'Test';
CurNode := CurNode.ParentNode;
CurNode := CurNode.AddChild('Codice');
CurNode.Text := '01234567890';
CurNode := CurNode.ParentNode;
CurNode := CurNode.ParentNode;
s := 'C:\Users\web\Desktop\file.xml';
XMl.SaveToFile(s);
end;
这是我的结果:
<?xml version="1.0" encoding="utf-8"?>
<p:test xmlns:ds="Attributes1" xmlns:p="Attributes2" versione="FPR12">
<p:HeadNode>
<p:SubNode>Test</p:SubNode>
<p:Codice>01234567890</p:Codice>
</p:HeadNode>
</p:test>
这是我期望的(注意 HeadNode 及其嵌套节点上缺少的 "p:"):
<?xml version="1.0" encoding="utf-8"?>
<p:test xmlns:ds="Attributes1" xmlns:p="Attributes2" versione="FPR12">
<HeadNode>
<SubNode>Test</SubNode>
<Codice>01234567890</Codice>
</HeadNode>
</p:test>
我怎样才能得到这个?
这是正常行为,在父节点下创建的任何节点都将带有父节点的命名空间。由于您希望该节点 HeadNode
不带有名称空间,因此您必须在创建该节点时分配一个空名称空间。如果查看函数 TXMLNode.AddChild
,您会发现有一个重载函数接受第二个参数,该参数表示该节点的 NameSpaceUri
。
因此,要修复 XML,您只需将行 CurNode := RootNode.AddChild('HeadNode');
更改为 CurNode := RootNode.AddChild('HeadNode', '');
可编译示例:
program SO58008911;
{$APPTYPE CONSOLE}
{$R *.res}
uses
ActiveX,
XMLIntf,
XMLDoc,
System.SysUtils;
procedure TestXML;
var
XML : IXMLDOCUMENT;
RootNode, CurNode : IXMLNODE;
begin
XML := NewXMLDocument;
XML.Encoding := 'utf-8';
XML.Options := [doNodeAutoIndent]; // looks better in Editor ;)
RootNode := XML.AddChild('p:test');
RootNode.Attributes['xmlns:ds'] := 'Attributes1';
RootNode.Attributes['xmlns:p'] := 'Attributes2';
RootNode.Attributes['versione'] := 'FPR12';
CurNode := RootNode.AddChild('HeadNode', '');
CurNode := CurNode.AddChild('SubNode');
CurNode.Text := 'Test';
CurNode := CurNode.ParentNode;
CurNode := CurNode.AddChild('Codice');
CurNode.Text := '01234567890';
Writeln(XML.XML.Text);
end;
begin
try
CoInitialize(nil);
try
TestXML;
finally
CoUninitialize;
end;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
Readln;
end.
输出:
<?xml version="1.0"?>
<p:test xmlns:ds="Attributes1" xmlns:p="Attributes2" versione="FPR12">
<HeadNode>
<SubNode>Test</SubNode>
<Codice>01234567890</Codice>
</HeadNode>
</p:test>
仅仅使用 Attributes[]
属性 向 XML 节点添加 xmlns
属性是不够的,您需要实际 声明 DOM 树中的命名空间。 IXMLNode
有一个用于该目的的 DeclareNamespace()
方法。创建子节点时,它会继承其父节点的命名空间,但如果您没有正确声明命名空间,则不会。
此外,因为您的根 test
节点在其中声明了 2 个名称空间,您需要指定 HeadNode
子节点实际属于哪个名称空间。如果您不这样做,它会继承与其父节点相同的前缀,因此它可以指示它所在的名称空间,这就是您所看到的情况。
试试这个:
var
XML : IXMLDocument;
RootNode, CurNode : IXMLNode;
begin
XML := NewXMLDocument;
XML.Encoding := 'utf-8';
XML.Options := [doNodeAutoIndent]; // looks better in Editor ;)
RootNode := XML.AddChild('p:test');
RootNode.DeclareNamespace('ds', 'Attributes1');
RootNode.DeclareNamespace('p', 'Attributes2');
RootNode.Attributes['versione'] := 'FPR12';
CurNode := RootNode.AddChild('HeadNode', 'Attributes2');
CurNode := CurNode.AddChild('SubNode');
CurNode.Text := 'Test';
CurNode := CurNode.ParentNode;
CurNode := CurNode.AddChild('Codice');
CurNode.Text := '01234567890';
CurNode := CurNode.ParentNode;
CurNode := CurNode.ParentNode;
s := 'C:\Users\web\Desktop\file.xml';
XML.SaveToFile(s);
end;
<?xml version="1.0"?>
<p:test xmlns:ds="Attributes1" xmlns:p="Attributes2" versione="True">
<HeadNode xmlns="Attributes2">
<SubNode>Test</SubNode>
<Codice>01234567890</Codice>
</HeadNode>
</p:test>
我正在 Delphi 7 中创建一个 XML 文件。我想从代码中删除父节点的声明。
这是我的代码:
var
XML : IXMLDOCUMENT;
RootNode, CurNode : IXMLNODE;
begin
XML := NewXMLDocument;
XML.Encoding := 'utf-8';
XML.Options := [doNodeAutoIndent]; // looks better in Editor ;)
RootNode := XML.AddChild('p:test');
RootNode.Attributes['xmlns:ds'] := 'Attributes1';
RootNode.Attributes['xmlns:p'] := 'Attributes2';
RootNode.Attributes['versione'] := 'FPR12';
CurNode := RootNode.AddChild('HeadNode');
CurNode := CurNode.AddChild('SubNode');
CurNode.Text := 'Test';
CurNode := CurNode.ParentNode;
CurNode := CurNode.AddChild('Codice');
CurNode.Text := '01234567890';
CurNode := CurNode.ParentNode;
CurNode := CurNode.ParentNode;
s := 'C:\Users\web\Desktop\file.xml';
XMl.SaveToFile(s);
end;
这是我的结果:
<?xml version="1.0" encoding="utf-8"?>
<p:test xmlns:ds="Attributes1" xmlns:p="Attributes2" versione="FPR12">
<p:HeadNode>
<p:SubNode>Test</p:SubNode>
<p:Codice>01234567890</p:Codice>
</p:HeadNode>
</p:test>
这是我期望的(注意 HeadNode 及其嵌套节点上缺少的 "p:"):
<?xml version="1.0" encoding="utf-8"?>
<p:test xmlns:ds="Attributes1" xmlns:p="Attributes2" versione="FPR12">
<HeadNode>
<SubNode>Test</SubNode>
<Codice>01234567890</Codice>
</HeadNode>
</p:test>
我怎样才能得到这个?
这是正常行为,在父节点下创建的任何节点都将带有父节点的命名空间。由于您希望该节点 HeadNode
不带有名称空间,因此您必须在创建该节点时分配一个空名称空间。如果查看函数 TXMLNode.AddChild
,您会发现有一个重载函数接受第二个参数,该参数表示该节点的 NameSpaceUri
。
因此,要修复 XML,您只需将行 CurNode := RootNode.AddChild('HeadNode');
更改为 CurNode := RootNode.AddChild('HeadNode', '');
可编译示例:
program SO58008911;
{$APPTYPE CONSOLE}
{$R *.res}
uses
ActiveX,
XMLIntf,
XMLDoc,
System.SysUtils;
procedure TestXML;
var
XML : IXMLDOCUMENT;
RootNode, CurNode : IXMLNODE;
begin
XML := NewXMLDocument;
XML.Encoding := 'utf-8';
XML.Options := [doNodeAutoIndent]; // looks better in Editor ;)
RootNode := XML.AddChild('p:test');
RootNode.Attributes['xmlns:ds'] := 'Attributes1';
RootNode.Attributes['xmlns:p'] := 'Attributes2';
RootNode.Attributes['versione'] := 'FPR12';
CurNode := RootNode.AddChild('HeadNode', '');
CurNode := CurNode.AddChild('SubNode');
CurNode.Text := 'Test';
CurNode := CurNode.ParentNode;
CurNode := CurNode.AddChild('Codice');
CurNode.Text := '01234567890';
Writeln(XML.XML.Text);
end;
begin
try
CoInitialize(nil);
try
TestXML;
finally
CoUninitialize;
end;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
Readln;
end.
输出:
<?xml version="1.0"?>
<p:test xmlns:ds="Attributes1" xmlns:p="Attributes2" versione="FPR12">
<HeadNode>
<SubNode>Test</SubNode>
<Codice>01234567890</Codice>
</HeadNode>
</p:test>
仅仅使用 Attributes[]
属性 向 XML 节点添加 xmlns
属性是不够的,您需要实际 声明 DOM 树中的命名空间。 IXMLNode
有一个用于该目的的 DeclareNamespace()
方法。创建子节点时,它会继承其父节点的命名空间,但如果您没有正确声明命名空间,则不会。
此外,因为您的根 test
节点在其中声明了 2 个名称空间,您需要指定 HeadNode
子节点实际属于哪个名称空间。如果您不这样做,它会继承与其父节点相同的前缀,因此它可以指示它所在的名称空间,这就是您所看到的情况。
试试这个:
var
XML : IXMLDocument;
RootNode, CurNode : IXMLNode;
begin
XML := NewXMLDocument;
XML.Encoding := 'utf-8';
XML.Options := [doNodeAutoIndent]; // looks better in Editor ;)
RootNode := XML.AddChild('p:test');
RootNode.DeclareNamespace('ds', 'Attributes1');
RootNode.DeclareNamespace('p', 'Attributes2');
RootNode.Attributes['versione'] := 'FPR12';
CurNode := RootNode.AddChild('HeadNode', 'Attributes2');
CurNode := CurNode.AddChild('SubNode');
CurNode.Text := 'Test';
CurNode := CurNode.ParentNode;
CurNode := CurNode.AddChild('Codice');
CurNode.Text := '01234567890';
CurNode := CurNode.ParentNode;
CurNode := CurNode.ParentNode;
s := 'C:\Users\web\Desktop\file.xml';
XML.SaveToFile(s);
end;
<?xml version="1.0"?>
<p:test xmlns:ds="Attributes1" xmlns:p="Attributes2" versione="True">
<HeadNode xmlns="Attributes2">
<SubNode>Test</SubNode>
<Codice>01234567890</Codice>
</HeadNode>
</p:test>