【问题标题】:How to properly create XML header (to fill pdf documents in xfdf format) with Delphi using IXMLDOCUMENT如何使用 IXMLDOCUMENT 使用 Delphi 正确创建 XML 标头(以 xfdf 格式填充 pdf 文档)
【发布时间】:2017-02-11 03:51:52
【问题描述】:

我需要帮助来实现这个 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');

【问题讨论】:

    标签: xml delphi xfdf


    【解决方案1】:

    你得到了一个不好的结果,因为:

    1. 您没有正确处理 XML 命名空间。

    2. 您将 fields 节点创建为 f 节点的子节点,而不是 xfdf 节点的子节点。

    添加子节点时,它会继承其父节点的命名空间,除非您明确指定不同的命名空间,并且命名空间一旦分配就不能更改。

    在你的情况下,你的 xfdf 节点实际上并没有被添加到 Adob​​e 命名空间,你在伪造它! XML 引擎不知道命名空间,所以 xfdf 节点有一个空白命名空间,f 子节点继承。这就是为什么 f 节点最终会带有不需要的 xmlns="" 属性,因此不会有歧义,因为它属于哪个命名空间子节点。

    要正确声明命名空间以便 XML 引擎知道它,您需要使用 IXMLNode.DeclareNamespace() 方法而不是使用 IXMLNode.Attributes 属性。

    您可以:

    1. 在将 Adob​​e 命名空间添加到文档后,在 xfdf 节点上显式声明它。 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. 或者,在您将节点添加到文档时在 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;
      

    任何一种方法都会删除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>
    

    【讨论】:

    • 哇,非常感谢您抽出宝贵的时间,如此清晰且解释清楚。我喜欢第二种方法,因为它的代码冗余少一点,子节点的命名空间是从根节点继承的,我不必再次指定。
    • 当然结果是预期的,没有节点“f”和“fields”中不需要的属性 xmlns=""。现在很清楚了! :)
    • @Jiug:如果此答案解决了您的问题,请务必将其标记为已接受。见What should I do when someone answers my question?
    【解决方案2】:

    你的混合节点

    f 是子 xfdf

    filds 也是子 xfdf

    解决方案

    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;
    

    【讨论】:

    • 有效!非常感谢,下面我还有一个问题要问你:)
    • 更改行 RootNode := XML.addChild('xfdf') 与 XML.DocumentElement := XML.CreateElement('xfdf','ns.adobe.com/xfdf/'); RootNode := XML.DocumentElement;并删除添加属性 xmlns
    • 再次感谢,现在完美了:)
    • @ceha: AddChild() 可用于创建和分配DocumentElement 节点。所以在原始代码中,RootNodeXML.DocumentElement 在添加f 时是同一个元素。 AddChild() 有一个接受命名空间作为输入的重载版本。您无需直接拨打CreateElement()
    猜你喜欢
    • 2013-02-20
    • 1970-01-01
    • 2018-06-04
    • 1970-01-01
    • 1970-01-01
    • 2023-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多