简体   繁体   English

如何使用 IXMLDOCUMENT 使用 Delphi 正确创建 XML 标头(以 xfdf 格式填充 pdf 文档)

[英]How to properly create XML header (to fill pdf documents in xfdf format) with Delphi using IXMLDOCUMENT

please I need help to achieve this xml, I have a problme with the third line, this is what I get with my code:请我需要帮助来实现这个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>

and this is what I need:这就是我需要的:

<?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>

I dont know how to create the "f" tag like in the second example, notice that it's a little bit different and it closes in the same line and not before the last line like in the first example.我不知道如何像第二个示例中那样创建“f”标签,请注意它有点不同,它在同一行中关闭,而不是在第一个示例中的最后一行之前。

Here is my code:这是我的代码:

....
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');

you mixed node你混合节点

f is child xfdf f 是孩子 xfdf

filds is also child xfdf filds 也是孩子 xfdf

solution解决方案

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;

You are getting a bad result because:你得到一个糟糕的结果,因为:

  1. you are not handling XML namespaces correctly.您没有正确处理 XML 名称空间。

  2. you are creating the fields node as a child of the f node instead of as a child of the xfdf node.您正在创建fields节点作为f节点的子节点而不是xfdf节点的子节点。

When a child node is added, it inherits its parent node's namespace unless you explicitly specify a different namespace, and the namespace cannot be changed once assigned.添加子节点时,除非您明确指定不同的命名空间,否则它将继承其父节点的命名空间,并且命名空间一旦分配就无法更改。

In your case, your xfdf node is not actually being added to the Adobe namespace, you are faking it!在您的情况下,您的xfdf节点实际上并未添加到 Adob​​e 命名空间中,您是在伪造它! The XML engine does not know about the namespace, so the xfdf node has a blank namespace, which the f child node inherits. XML 引擎不知道命名空间,因此xfdf节点有一个空白命名空间, f子节点继承了它。 That is why the f node ends up with the unwanted xmlns="" attribute, so there is no ambiguity as it which namespace child nodes belong to.这就是为什么f节点以不需要的xmlns=""属性结束,因此没有歧义,因为它属于哪个命名空间子节点。

To declare a namespace correctly so the XML engine knows about it, you need to use the IXMLNode.DeclareNamespace() method instead of using the IXMLNode.Attributes property.要正确声明命名空间以便 XML 引擎知道它,您需要使用IXMLNode.DeclareNamespace()方法而不是使用IXMLNode.Attributes属性。

You can either:您可以:

  1. explicitly declare the Adobe namespace on the xfdf node after adding it to the document.将其添加到文档后,在xfdf节点上显式声明 Adob​​e 命名空间。 The xfdf node itself will not be in the namespace (as evident by the IXMLNode.NamespaceURI property still being blank), but the namespace can then be explicitly applied when adding the f and fields child nodes: xfdf节点本身不会在命名空间中(从IXMLNode.NamespaceURI属性仍然为空白可以看出),但是在添加ffields子节点时可以显式应用命名空间:

     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;
  2. alternatively, declare the Adobe namespace on the xfdf node at the time you add that node to the document, and then that node will be in the namespace so the f and fields child nodes inherit it without you having to call DeclareNamespace() manually ( AddChild() calls it internally for you):或者,在您将该节点添加到文档时在xfdf节点上声明 Adob​​e 命名空间,然后该节点将在命名空间中,因此ffields子节点继承它,而无需手动调用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;

Either approach will remove the xmlns="" attribute on the f and fields nodes since they belong to a namespace that is declared in the xfdf node, and subsequent child nodes will inherit the namespace as expected:这两种方法都将删除ffields节点上的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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM