如何使用 IXMLDOCUMENT 使用 Delphi 正确创建 XML header(以 xfdf 格式填充 pdf 文档)
How to properly create XML header (to fill pdf documents in xfdf format) with Delphi using IXMLDOCUMENT
我需要帮助来实现这个 xml,我的第三行有问题,这就是我的代码:
<?xml version="1.0" encoding="utf-8"?>
<xfdf xmlns="http://ns.adobe.com/xfdf/" xml:space="preserve">
<f xmlns="" href="myExample.pdf">
<fields>
<field name="chk01">
<value>X</value>
</field>
<field name="chk02">
<value>X</value>
</field>
<field name="edt11">
<value>Some text</value>
</field>
</fields>
</f>
</xfdf>
这就是我需要的:
<?xml version="1.0" encoding="UTF-8"?>
<xfdf xmlns="http://ns.adobe.com/xfdf/" xml:space="preserve">
<f href="myExample.pdf"/>
<fields>
<field name="chk01">
<value>X</value>
</field>
<field name="chk02">
<value>X</value>
</field>
<field name="edt11">
<value>Some text</value>
</field>
</fields>
</xfdf>
我不知道如何像第二个示例那样创建 "f" 标签,请注意它有点不同,它在同一行结束,而不是像第一个示例那样在最后一行之前结束。
这是我的代码:
....
Var
XML : IXMLDOCUMENT;
RootNode, NodeLevel1, CurNode : IXMLNODE;
Begin
XML := NewXMLDocument;
XML.Encoding := 'utf-8';
XML.Options := [doNodeAutoIndent];
RootNode := XML.AddChild('xfdf');
RootNode.Attributes['xmlns']:= 'http://ns.adobe.com/xfdf/';
RootNode.Attributes['xml:space']:= 'preserve';
RootNode := XML.DocumentElement.AddChild('f');
RootNode.Attributes['href']:= 'myExample.pdf';
NodeLevel1 := RootNode.AddChild('fields');
CurNode := NodeLevel1.AddChild('field');
CurNode.Attributes['name'] := 'chk01';
CurNode := CurNode.AddChild('value');
CurNode.Text:= 'X';
CurNode := NodeLevel1.AddChild('field');
CurNode.Attributes['name'] := 'chk02';
CurNode := CurNode.AddChild('value');
CurNode.Text:= 'X';
CurNode := NodeLevel1.AddChild('field');
CurNode.Attributes['name'] := 'edt11';
CurNode := CurNode.AddChild('value');
CurNode.Text:= 'Some text';
XMl.SaveToFile('C:\New.fdf');
你混节点
f 是 child xfdf
filds 也是 childxfdf
解决方案
Var
XML : IXMLDOCUMENT;
fnode, RootNode, NodeLevel1, CurNode : IXMLNODE;
Begin
XML := NewXMLDocument;
XML.Encoding := 'utf-8';
XML.Options := [doNodeAutoIndent];
RootNode := XML.AddChild('xfdf');
RootNode.Attributes['xmlns']:= 'http://ns.adobe.com/xfdf/';
RootNode.Attributes['xml:space']:= 'preserve';
fnode := RootNode.AddChild('f');
fNode.Attributes['href']:= 'myExample.pdf';
NodeLevel1 := RootNode.AddChild('fields');
CurNode := NodeLevel1.AddChild('field');
CurNode.Attributes['name'] := 'chk01';
CurNode := CurNode.AddChild('value');
CurNode.Text:= 'X';
CurNode := NodeLevel1.AddChild('field');
CurNode.Attributes['name'] := 'chk02';
CurNode := CurNode.AddChild('value');
CurNode.Text:= 'X';
CurNode := NodeLevel1.AddChild('field');
CurNode.Attributes['name'] := 'edt11';
CurNode := CurNode.AddChild('value');
CurNode.Text:= 'Some text';
XMl.SaveToFile('C:\tmp\New.fdf');end;
您的结果很差,因为:
您没有正确处理 XML 命名空间。
您正在创建 fields
节点作为 f
节点的子节点而不是 xfdf
节点的子节点。
添加子节点时,除非您明确指定不同的命名空间,否则它会继承其父节点的命名空间,并且命名空间一旦分配就无法更改。
在你的情况下,你的 xfdf
节点实际上并没有被添加到 Adobe 命名空间,你是在伪造它! XML 引擎没有知道命名空间,所以 xfdf
节点有一个空白的命名空间,f
子节点继承了它。这就是 f
节点以不需要的 xmlns=""
属性结束的原因,因此没有歧义,因为它属于哪个名称空间子节点。
要正确声明命名空间以便 XML 引擎知道它,您需要使用 IXMLNode.DeclareNamespace()
方法而不是使用 IXMLNode.Attributes
属性.
您可以:
在将 xfdf
节点添加到文档后显式声明 Adobe 命名空间。 xfdf
节点本身不会在命名空间中(从 IXMLNode.NamespaceURI
属性 仍然是空白可以看出),但是在添加 f
时可以显式应用命名空间和 fields
个子节点:
const
NsAdobeXfdf = 'http://ns.adobe.com/xfdf/';
var
XML: IXMLDocument;
RootNode, FNode, FieldsNode, FieldNode: IXMLNode;
begin
XML := NewXMLDocument;
XML.Encoding := 'utf-8';
XML.Options := [doNodeAutoIndent];
RootNode := XML.AddChild('xfdf'); // <-- xfdf is not in any namespace
RootNode.DeclareNamespace('', NsAdobeXfdf); // <-- declare the namespace
RootNode.Attributes['xml:space'] := 'preserve';
FNode := RootNode.AddChild('f', NsAdobeXfdf); // <-- f is in the Adobe namespace
FNode.Attributes['href'] := 'myExample.pdf';
FieldsNode := RootNode.AddChild('fields', NsAdobeXfdf); // <-- fields is in the Adobe namespace
FieldNode := FieldsNode.AddChild('field'); // <-- inherits namespace from fields
FieldNode.Attributes['name'] := 'chk01';
FieldNode.AddChild('value').Text := 'X'; // <-- inherits namespace from field
FieldNode := FieldsNode.AddChild('field'); // <-- inherits namespace from fields
FieldNode.Attributes['name'] := 'chk02';
FieldNode.AddChild('value').Text := 'X'; // <-- inherits namespace from field
FieldNode := FieldsNode.AddChild('field'); // <-- inherits namespace from fields
FieldNode.Attributes['name'] := 'edt11';
FieldNode.AddChild('value').Text := 'Some text'; // <-- inherits namespace from field
XML.SaveToFile('C:\New.fdf');
end;
或者,在将节点添加到文档时在 xfdf
节点上声明 Adobe 命名空间,然后该节点将位于命名空间中,因此 f
和 fields
子节点无需手动调用 DeclareNamespace()
即可继承它(AddChild()
在内部为您调用):
const
NsAdobeXfdf = 'http://ns.adobe.com/xfdf/';
var
XML: IXMLDocument;
RootNode, FNode, FieldsNode, FieldNode: IXMLNode;
begin
XML := NewXMLDocument;
XML.Encoding := 'utf-8';
XML.Options := [doNodeAutoIndent];
RootNode := XML.AddChild('xfdf', NsAdobeXfdf); // <-- xfdf is in the Adobe namespace
RootNode.Attributes['xml:space'] := 'preserve';
FNode := RootNode.AddChild('f'); // <-- inherits namespace from xfdf
FNode.Attributes['href'] := 'myExample.pdf';
FieldsNode := RootNode.AddChild('fields'); // <-- inherits namespace from xfdf
FieldNode := FieldsNode.AddChild('field'); // <-- inherits namespace from fields
FieldNode.Attributes['name'] := 'chk01';
FieldNode.AddChild('value').Text := 'X'; // <-- inherits namespace from field
FieldNode := FieldsNode.AddChild('field'); // <-- inherits namespace from fields
FieldNode.Attributes['name'] := 'chk02';
FieldNode.AddChild('value').Text := 'X'; // <-- inherits namespace from field
FieldNode := FieldsNode.AddChild('field'); // <-- inherits namespace from fields
FieldNode.Attributes['name'] := 'edt11';
FieldNode.AddChild('value').Text := 'Some text'; // <-- inherits namespace from field
XML.SaveToFile('C:\New.fdf');
end;
任何一种方法都将删除 f
和 fields
节点上的 xmlns=""
属性,因为它们属于在 xfdf
节点中声明的名称空间,随后子节点将按预期继承命名空间:
<?xml version="1.0" encoding="utf-8"?>
<xfdf xmlns="http://ns.adobe.com/xfdf/" xml:space="preserve">
<f href="myExample.pdf"/>
<fields>
<field name="chk01">
<value>X</value>
</field>
<field name="chk02">
<value>X</value>
</field>
<field name="edt11">
<value>Some text</value>
</field>
</fields>
</xfdf>
我需要帮助来实现这个 xml,我的第三行有问题,这就是我的代码:
<?xml version="1.0" encoding="utf-8"?>
<xfdf xmlns="http://ns.adobe.com/xfdf/" xml:space="preserve">
<f xmlns="" href="myExample.pdf">
<fields>
<field name="chk01">
<value>X</value>
</field>
<field name="chk02">
<value>X</value>
</field>
<field name="edt11">
<value>Some text</value>
</field>
</fields>
</f>
</xfdf>
这就是我需要的:
<?xml version="1.0" encoding="UTF-8"?>
<xfdf xmlns="http://ns.adobe.com/xfdf/" xml:space="preserve">
<f href="myExample.pdf"/>
<fields>
<field name="chk01">
<value>X</value>
</field>
<field name="chk02">
<value>X</value>
</field>
<field name="edt11">
<value>Some text</value>
</field>
</fields>
</xfdf>
我不知道如何像第二个示例那样创建 "f" 标签,请注意它有点不同,它在同一行结束,而不是像第一个示例那样在最后一行之前结束。
这是我的代码:
....
Var
XML : IXMLDOCUMENT;
RootNode, NodeLevel1, CurNode : IXMLNODE;
Begin
XML := NewXMLDocument;
XML.Encoding := 'utf-8';
XML.Options := [doNodeAutoIndent];
RootNode := XML.AddChild('xfdf');
RootNode.Attributes['xmlns']:= 'http://ns.adobe.com/xfdf/';
RootNode.Attributes['xml:space']:= 'preserve';
RootNode := XML.DocumentElement.AddChild('f');
RootNode.Attributes['href']:= 'myExample.pdf';
NodeLevel1 := RootNode.AddChild('fields');
CurNode := NodeLevel1.AddChild('field');
CurNode.Attributes['name'] := 'chk01';
CurNode := CurNode.AddChild('value');
CurNode.Text:= 'X';
CurNode := NodeLevel1.AddChild('field');
CurNode.Attributes['name'] := 'chk02';
CurNode := CurNode.AddChild('value');
CurNode.Text:= 'X';
CurNode := NodeLevel1.AddChild('field');
CurNode.Attributes['name'] := 'edt11';
CurNode := CurNode.AddChild('value');
CurNode.Text:= 'Some text';
XMl.SaveToFile('C:\New.fdf');
你混节点
f 是 child xfdf
filds 也是 childxfdf
解决方案
Var
XML : IXMLDOCUMENT;
fnode, RootNode, NodeLevel1, CurNode : IXMLNODE;
Begin
XML := NewXMLDocument;
XML.Encoding := 'utf-8';
XML.Options := [doNodeAutoIndent];
RootNode := XML.AddChild('xfdf');
RootNode.Attributes['xmlns']:= 'http://ns.adobe.com/xfdf/';
RootNode.Attributes['xml:space']:= 'preserve';
fnode := RootNode.AddChild('f');
fNode.Attributes['href']:= 'myExample.pdf';
NodeLevel1 := RootNode.AddChild('fields');
CurNode := NodeLevel1.AddChild('field');
CurNode.Attributes['name'] := 'chk01';
CurNode := CurNode.AddChild('value');
CurNode.Text:= 'X';
CurNode := NodeLevel1.AddChild('field');
CurNode.Attributes['name'] := 'chk02';
CurNode := CurNode.AddChild('value');
CurNode.Text:= 'X';
CurNode := NodeLevel1.AddChild('field');
CurNode.Attributes['name'] := 'edt11';
CurNode := CurNode.AddChild('value');
CurNode.Text:= 'Some text';
XMl.SaveToFile('C:\tmp\New.fdf');end;
您的结果很差,因为:
您没有正确处理 XML 命名空间。
您正在创建
fields
节点作为f
节点的子节点而不是xfdf
节点的子节点。
添加子节点时,除非您明确指定不同的命名空间,否则它会继承其父节点的命名空间,并且命名空间一旦分配就无法更改。
在你的情况下,你的 xfdf
节点实际上并没有被添加到 Adobe 命名空间,你是在伪造它! XML 引擎没有知道命名空间,所以 xfdf
节点有一个空白的命名空间,f
子节点继承了它。这就是 f
节点以不需要的 xmlns=""
属性结束的原因,因此没有歧义,因为它属于哪个名称空间子节点。
要正确声明命名空间以便 XML 引擎知道它,您需要使用 IXMLNode.DeclareNamespace()
方法而不是使用 IXMLNode.Attributes
属性.
您可以:
在将
xfdf
节点添加到文档后显式声明 Adobe 命名空间。xfdf
节点本身不会在命名空间中(从IXMLNode.NamespaceURI
属性 仍然是空白可以看出),但是在添加f
时可以显式应用命名空间和fields
个子节点:const NsAdobeXfdf = 'http://ns.adobe.com/xfdf/'; var XML: IXMLDocument; RootNode, FNode, FieldsNode, FieldNode: IXMLNode; begin XML := NewXMLDocument; XML.Encoding := 'utf-8'; XML.Options := [doNodeAutoIndent]; RootNode := XML.AddChild('xfdf'); // <-- xfdf is not in any namespace RootNode.DeclareNamespace('', NsAdobeXfdf); // <-- declare the namespace RootNode.Attributes['xml:space'] := 'preserve'; FNode := RootNode.AddChild('f', NsAdobeXfdf); // <-- f is in the Adobe namespace FNode.Attributes['href'] := 'myExample.pdf'; FieldsNode := RootNode.AddChild('fields', NsAdobeXfdf); // <-- fields is in the Adobe namespace FieldNode := FieldsNode.AddChild('field'); // <-- inherits namespace from fields FieldNode.Attributes['name'] := 'chk01'; FieldNode.AddChild('value').Text := 'X'; // <-- inherits namespace from field FieldNode := FieldsNode.AddChild('field'); // <-- inherits namespace from fields FieldNode.Attributes['name'] := 'chk02'; FieldNode.AddChild('value').Text := 'X'; // <-- inherits namespace from field FieldNode := FieldsNode.AddChild('field'); // <-- inherits namespace from fields FieldNode.Attributes['name'] := 'edt11'; FieldNode.AddChild('value').Text := 'Some text'; // <-- inherits namespace from field XML.SaveToFile('C:\New.fdf'); end;
或者,在将节点添加到文档时在
xfdf
节点上声明 Adobe 命名空间,然后该节点将位于命名空间中,因此f
和fields
子节点无需手动调用DeclareNamespace()
即可继承它(AddChild()
在内部为您调用):const NsAdobeXfdf = 'http://ns.adobe.com/xfdf/'; var XML: IXMLDocument; RootNode, FNode, FieldsNode, FieldNode: IXMLNode; begin XML := NewXMLDocument; XML.Encoding := 'utf-8'; XML.Options := [doNodeAutoIndent]; RootNode := XML.AddChild('xfdf', NsAdobeXfdf); // <-- xfdf is in the Adobe namespace RootNode.Attributes['xml:space'] := 'preserve'; FNode := RootNode.AddChild('f'); // <-- inherits namespace from xfdf FNode.Attributes['href'] := 'myExample.pdf'; FieldsNode := RootNode.AddChild('fields'); // <-- inherits namespace from xfdf FieldNode := FieldsNode.AddChild('field'); // <-- inherits namespace from fields FieldNode.Attributes['name'] := 'chk01'; FieldNode.AddChild('value').Text := 'X'; // <-- inherits namespace from field FieldNode := FieldsNode.AddChild('field'); // <-- inherits namespace from fields FieldNode.Attributes['name'] := 'chk02'; FieldNode.AddChild('value').Text := 'X'; // <-- inherits namespace from field FieldNode := FieldsNode.AddChild('field'); // <-- inherits namespace from fields FieldNode.Attributes['name'] := 'edt11'; FieldNode.AddChild('value').Text := 'Some text'; // <-- inherits namespace from field XML.SaveToFile('C:\New.fdf'); end;
任何一种方法都将删除 f
和 fields
节点上的 xmlns=""
属性,因为它们属于在 xfdf
节点中声明的名称空间,随后子节点将按预期继承命名空间:
<?xml version="1.0" encoding="utf-8"?>
<xfdf xmlns="http://ns.adobe.com/xfdf/" xml:space="preserve">
<f href="myExample.pdf"/>
<fields>
<field name="chk01">
<value>X</value>
</field>
<field name="chk02">
<value>X</value>
</field>
<field name="edt11">
<value>Some text</value>
</field>
</fields>
</xfdf>