如何在perl中创建一个新的XML :: DOM :: Document根目录

时间:2014-11-27 18:39:56

标签: xml perl dom

我尝试修改一些使用XML::LibXML使用XML::DOM的代码,因为前者在我的fatcow服务器上不可用。

如何设置XML::DOM::Document对象的根文档? setDocumentElement中没有XML::DOM::Document方法。

以下是有问题的代码(来自XML::XML2JSON),我想知道如何更换标有星号的代码。

=head2 obj2dom

Takes a perl data structure as input. (Must be a hashref.)
Returns an XML::DOM::Document object.    #JMO

This method expects the object to be in the same format as
would be returned by the xml2obj method.

=cut

sub obj2dom
{
    my ( $Self, $Obj ) = @_;

    croak "Object must be a hashref" unless ref($Obj) eq 'HASH';

    my $Version  = $Obj->{ $Self->{attribute_prefix} . 'version' }  || $Obj->{'version'}  || '1.0';
    my $Encoding = $Obj->{ $Self->{attribute_prefix} . 'encoding' } || $Obj->{'encoding'} || 'UTF-8';

    #my $Dom = $XMLPARSER->createDocument( $Version, $Encoding ); #JMO
    my $Dom = XML::DOM::Document->new();                          #JMO
    $Dom->setXMLDecl($Dom->createXMLDecl($Version, $Encoding));   #JMO

    my $GotRoot = 0;

     #delete @$Obj{ grep { /^$Self->{attribute_prefix}/ } keys %$Obj };

    foreach my $Key ( keys %$Obj )
    {
        $Obj->{$Key} = "" unless defined($Obj->{$Key});

        my $RefType = ref( $Obj->{$Key} );
        warn "Value ref type for $Key is: $RefType (value seems to be $Obj->{$Key})" if $Self->{debug};

        my $Name = $Key;

        # replace a "$" in the name with a ":"
        $Name =~ s/([^^])\$/$1\:/;

        if ( $RefType eq 'HASH' )
        {
            warn "Creating root element: $Name" if $Self->{debug};

            croak "You may only have one root element: $Key" if $GotRoot;
            $GotRoot = 1;

            my $Root = $Dom->createElement($Name);
            $Dom->setDocumentElement($Root);        # **********

            $Self->_process_element_hash( $Dom, $Root, $Obj->{$Key} );
        }
        elsif ( $RefType eq 'ARRAY' )
        {
            croak "You cant have an array of root nodes: $Key";
        }
        elsif ( !$RefType )
        {       
            if ( $Obj->{$Key} ne '' )
            {
                unless ($GotRoot)
                {
                    my $Root;
                    eval { $Root = $Dom->createElement($Name) };
                    if ( $@ ) {
                        die "Problem creating root element $Name: $@";
                    }
                    $Dom->setDocumentElement($Root);        # **********
                    $Root->appendText( $Obj->{$Key} );
                    $GotRoot = 1;
                }
            }
            else
            {
              croak "Invalid data for key: $Key";
            }
        }
        else
        {
            warn "unknown reference: $RefType";
        }
    }

    return $Dom;
}

1 个答案:

答案 0 :(得分:2)

XML::DOM::Document对象代表文档根文档实体。请注意,它与根元素之间存在区别,根元素是文档根目录的唯一子元素,也是XML文档的最外层元素。

获得XML::DOM::Document个对象后,使用appendChild添加到其中的第一个子项将成为根元素。如果您尝试附加元素节点以外的任何内容,则会出现错误

XML::DOM::DOMException(Code=3, Name=HIERARCHY_REQUEST_ERR, Message=bad node type)

或者如果您尝试添加多个节点,您将看到

XML::DOM::DOMException(Code=3, Name=HIERARCHY_REQUEST_ERR, Message=document can have only one Element)

换句话说,与setDocumentElement最接近的等价物只是appendChild,就像这样

my $Root = $Dom->createElement($Name);
$Dom->appendChild($Root);

这是一个构建完整XML文档树的示例程序。它会将一个带有标记root的元素附加到文档对象,然后创建两个带有标记child1child2的子元素,为每个元素添加一些文本,然后将它们附加到根元素。

use strict;
use 5.010;
use warnings;

use XML::DOM;

my $dom = XML::DOM::Document->new;
$dom->setXMLDecl($dom->createXMLDecl(qw/ 1.0 UTF-8 /));

my $root = $dom->createElement('root');
$dom->appendChild($root);

for my $tag (qw/ child1 child2 /) {

  my $child = $dom->createElement($tag);
  $root->appendChild($child);

  my $text = $dom->createTextNode("Text for $tag");
  $child->appendChild($text);
}

print $dom->toString;

<强>输出

<?xml version="1.0" encoding="UTF-8"?>
<root><child1>Text for child1</child1><child2>Text for child2</child2></root>

最后一点。标识符中的大写字母通常保留给全局变量,例如Package::Names。词法范围的变量应该使用小写字母数字和下划线标识符。但是,在这种情况下,我意识到XML::XML2JSON模块本身违反了这条规则!